diff --git a/.github/workflows/basic_cli_test_arm64.yml b/.github/workflows/basic_cli_test_arm64.yml new file mode 100644 index 0000000000..c9fd4f14f4 --- /dev/null +++ b/.github/workflows/basic_cli_test_arm64.yml @@ -0,0 +1,22 @@ +on: + workflow_dispatch: + +# this cancels workflows currently in progress if you start a new one +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + test-basic-cli-release-arm64: + runs-on: [self-hosted, Linux, ARM64] + steps: + - name: clone basic-cli repo + uses: actions/checkout@v3 + with: + repository: roc-lang/basic-cli + ref: main + + - name: Run all tests with latest roc nightly + latest basic-cli release + run: | + sed -i 's/x86_64/arm64/g' ./ci/test_latest_release.sh + ./ci/test_latest_release.sh diff --git a/.github/workflows/devtools_test.yml b/.github/workflows/devtools_test.yml new file mode 100644 index 0000000000..42910f8085 --- /dev/null +++ b/.github/workflows/devtools_test.yml @@ -0,0 +1,57 @@ +on: + pull_request: + +name: Test the devtools nix files + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + devtools-test: + name: devtools-test + runs-on: [ubuntu-20.04] + timeout-minutes: 120 + steps: + - uses: actions/checkout@v3 + + - name: Only run all steps if flake.lock changed + id: checklock + run: | + if git diff --name-only ${{ github.event.before }} ${{ github.sha }} | grep 'flake.lock'; then + echo "Flake.lock was changed. Testing devtools nix files..." + echo "::set-output name=changed::true" + else + echo "Flake.lock was not changed. No need to run tests." + echo "::set-output name=changed::false" + fi + + - uses: cachix/install-nix-action@v23 + if: steps.checklock.outputs.changed == 'true' + with: + nix_path: nixpkgs=channel:nixos-unstable + + - name: test devtools/flake.nix + if: steps.checklock.outputs.changed == 'true' + id: devtools_test_step + run: | + sed -i "s|/home/username/gitrepos/roc|$(realpath .)|g" devtools/flake.nix + cat devtools/flake.nix + mkdir -p ../temp + cp devtools/flake.nix ../temp + cp devtools/flake.lock ../temp + cd ../temp + git init + git add flake.nix flake.lock + nix develop + + - name: Print tip on fail + if: steps.devtools_test_step.outcome == 'failure' + run: | + echo "The devtools test failed, this can likely be fixed by" + echo "locally deleting devtools/flake.lock and following the" + echo "instructions in devtools/README.md. This will create a" + echo "new flake.lock you should use to replace the old devtools/flake.lock" + + + diff --git a/.github/workflows/nix_linux_x86_64.yml b/.github/workflows/nix_linux_x86_64.yml index c86e12af5c..0e5eeaa6ae 100644 --- a/.github/workflows/nix_linux_x86_64.yml +++ b/.github/workflows/nix_linux_x86_64.yml @@ -31,3 +31,9 @@ jobs: - name: test the dev backend # these tests require an explicit feature flag run: nix develop -c cargo test --locked --release --package test_gen --no-default-features --features gen-dev + + - name: wasm repl tests + run: nix develop -c crates/repl_test/test_wasm.sh + + - name: test building wasm repl + run: nix develop -c ./ci/www-repl.sh diff --git a/.github/workflows/nix_macos_apple_silicon.yml b/.github/workflows/nix_macos_apple_silicon.yml index 09fe8922bf..4239f581fd 100644 --- a/.github/workflows/nix_macos_apple_silicon.yml +++ b/.github/workflows/nix_macos_apple_silicon.yml @@ -39,11 +39,18 @@ jobs: run: cd examples/platform-switching/rust-platform && nix develop -c cargo test --release --locked - name: test launching the editor - run: cargo test --release --locked editor_launch_test::launch -- --ignored # `--ignored` to run this test that is ignored for "normal" runs + run: nix develop -c cargo test --release --locked editor_launch_test::launch -- --ignored # `--ignored` to run this test that is ignored for "normal" runs # we run the llvm wasm tests only on this machine because it is fast and wasm should be cross-target - name: execute llvm wasm tests with --release run: nix develop -c cargo test-gen-llvm-wasm --locked --release - - name: test website build script - run: REPL_DEBUG=1 bash www/build.sh + - name: set env var and test website build script + run: | + nix develop -c bash www/build.sh + + - name: wasm repl tests + run: nix develop -c crates/repl_test/test_wasm.sh + + - name: test building wasm repl + run: nix develop -c ./ci/www-repl.sh diff --git a/.github/workflows/test_nightly_many_os.yml b/.github/workflows/test_nightly_many_os.yml index aeb25e52d6..c4160648f1 100644 --- a/.github/workflows/test_nightly_many_os.yml +++ b/.github/workflows/test_nightly_many_os.yml @@ -2,15 +2,15 @@ on: #pull_request: workflow_dispatch: -name: Test latest nightly release for macOS, ubu 20.04, ubu 22.04 x86_64 +name: Test latest nightly releases for macOS and Linux x86_64 jobs: test-nightly: - name: test nightly macos 11, macos 12, ubu 20.04, ubu 22.04 + name: test nightly macos 11/12/13, ubuntu 20.04/22.04 strategy: fail-fast: false matrix: - os: [ macos-11, macos-12, ubuntu-20.04, ubuntu-22.04 ] + os: [ macos-11, macos-12, macos-13, ubuntu-20.04, ubuntu-22.04 ] runs-on: ${{ matrix.os }} timeout-minutes: 90 steps: diff --git a/.github/workflows/ubuntu_x86_64.yml b/.github/workflows/ubuntu_x86_64.yml index 709428b06d..457253dea4 100644 --- a/.github/workflows/ubuntu_x86_64.yml +++ b/.github/workflows/ubuntu_x86_64.yml @@ -65,4 +65,4 @@ jobs: #TODO verify-no-git-changes - name: test website build script - run: REPL_DEBUG=1 bash www/build.sh + run: bash www/build.sh diff --git a/.github/workflows/windows_tests.yml b/.github/workflows/windows_tests.yml index 9bd857dad3..9c42671fb7 100644 --- a/.github/workflows/windows_tests.yml +++ b/.github/workflows/windows_tests.yml @@ -1,5 +1,5 @@ on: - #pull_request: + #pull_request: name: windows - subset of tests diff --git a/Cargo.lock b/Cargo.lock index 0562d973a6..bdd7d5a49f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4099,6 +4099,7 @@ dependencies = [ "roc_debug_flags", "roc_error_macros", "roc_module", + "roc_parse", "roc_region", "roc_serialize", "static_assertions", @@ -4784,7 +4785,6 @@ dependencies = [ "criterion", "indoc", "inkwell", - "lazy_static", "libc", "libloading", "roc_bitcode", diff --git a/FAQ.md b/FAQ.md index ff00856f08..461e674004 100644 --- a/FAQ.md +++ b/FAQ.md @@ -31,61 +31,6 @@ fantastical, and it has incredible potential for puns. Here are some different w Fun fact: "roc" translates to 鹏 in Chinese, [which means](https://www.mdbg.net/chinese/dictionary?page=worddict&wdrst=0&wdqb=%E9%B9%8F) "a large fabulous bird." -## Why make a new editor instead of making an LSP plugin for VSCode, Vim or Emacs? - -The Roc editor is one of the key areas where we want to innovate. Constraining ourselves to a plugin for existing editors would severely limit our possibilities for innovation. - -A key part of our editor will be the use of plugins that are shipped with libraries. Think of a regex visualizer, parser debugger, or color picker. For library authors, it would be most convenient to write these plugins in Roc. Trying to dynamically load library plugins (written in Roc) in for example VSCode seems very difficult. - -## Is there syntax highlighting for Vim/Emacs/VS Code or a LSP? - -Not currently. Although they will presumably exist someday, while Roc is in the early days there's actually a conscious -effort to focus on the Roc Editor _instead of_ adding Roc support to other editors - specifically in order to give the Roc -Editor the best possible chance at kickstarting a virtuous cycle of plugin authorship. - -This is an unusual approach, but there are more details in [this 2021 interview](https://youtu.be/ITrDd6-PbvY?t=212). - -In the meantime, using CoffeeScript syntax highlighting for .roc files turns out to work surprisingly well! - -## Why won't the editor be able to edit non-roc files like .md, .gitignore, .yml, ... ? - -The downside of having the Roc editor support files other than .roc is that it seems extremely difficult to avoid scope creep if we allow it. For example, it starts with just editing json as plaintext but then it's annoying that there's no syntax highlighting, so maybe we add the capability to do syntax highlighting for json but of course then some people want it for toml, .md, etc, so we need to add a way to specify custom syntax highlighting rules for all of those. - -Then of course people don't want to be copy/pasting syntax highlighting rules from online, so maybe someone develops a third party "plugin manager" for the editor to distribute these syntax highlighting definitions. -So maybe we add sharing syntax highlighting as a first-class thing, so people don't have to download a separate tool to use their editor normally but then some people who are using it for .json and .yaml start using it for .css too. Syntax highlighting is okay but it's annoying that they don't get error reporting when they mess up syntax or type an invalid selector or import and pretty soon there's demand for the Roc editor to do all the hardest parts of VS code. - -We have to draw the line somewhere in there...but where to draw it? -It seems like drawing a bright line at .roc files is the most straightforward. It means the roc editor is the absolute best at editing .roc files and it isn't a weak editor for anything else because it doesn't try to be an editor for anything else and it means the scope is very clear. - -## Why is there no way to specify "import everything this module exposes" in `imports`? - -In [Elm](https://elm-lang.org), it's possible to import a module in a way that brings everything that module -exposes into scope. It can be convenient, but like all programming language features, it has downsides. - -A minor reason Roc doesn't have this feature is that exposing everything can make it more difficult -outside the editor (e.g. on a website) to tell where something comes from, especially if multiple imports are -using this. ("I don't see `blah` defined in this module, so it must be coming from an import...but which of -these several import-exposing-everything modules could it be? I'll have to check all of them, or -download this code base and open it up in the editor so I can jump to definition!") - -The main reason for this design, though, is compiler performance. - -Currently, the name resolution step in compilation can be parallelized across modules, because it's possible to -tell if there's a naming error within a module using only the contents of that module. If "expose everything" is -allowed, then it's no longer clear whether anything is a naming error or not, until all the "expose everything" -modules have been processed, so we know exactly which names they expose. Because that feature doesn't exist in Roc, -all modules can do name resolution in parallel. - -Of note, allowing this feature would only slow down modules that used it; modules that didn't use it would still be -parallelizable. However, when people find out ways to speed up their builds (in any language), advice starts to -circulate about how to unlock those speed boosts. If Roc had this feature, it's predictable that a commonly-accepted -piece of advice would eventually circulate: "don't use this feature because it slows down your builds." - -If a feature exists in a language, but the common recommendation is never to use it, that's cause for reconsidering -whether the feature should be in the language at all. In the case of this feature, I think it's simpler if the -language doesn't have it; that way nobody has to learn (or spend time spreading the word) about the -performance-boosting advice not to use it. - ## Why can't functions be compared for equality using the `==` operator? Function equality has been proven to be undecidable in the general case because of the [halting problem](https://en.wikipedia.org/wiki/Halting_problem). @@ -126,6 +71,35 @@ The first of these problems could be addressed by having function equality alway Each of these designs makes Roc a language that's some combination of more error-prone, more confusing, and more brittle to change. Disallowing function equality at compile time eliminates all of these drawbacks. +## Why is there no way to specify "import everything this module exposes" in `imports`? + +In [Elm](https://elm-lang.org), it's possible to import a module in a way that brings everything that module +exposes into scope. It can be convenient, but like all programming language features, it has downsides. + +A minor reason Roc doesn't have this feature is that exposing everything can make it more difficult +outside the editor (e.g. on a website) to tell where something comes from, especially if multiple imports are +using this. ("I don't see `blah` defined in this module, so it must be coming from an import...but which of +these several import-exposing-everything modules could it be? I'll have to check all of them, or +download this code base and open it up in the editor so I can jump to definition!") + +The main reason for this design, though, is compiler performance. + +Currently, the name resolution step in compilation can be parallelized across modules, because it's possible to +tell if there's a naming error within a module using only the contents of that module. If "expose everything" is +allowed, then it's no longer clear whether anything is a naming error or not, until all the "expose everything" +modules have been processed, so we know exactly which names they expose. Because that feature doesn't exist in Roc, +all modules can do name resolution in parallel. + +Of note, allowing this feature would only slow down modules that used it; modules that didn't use it would still be +parallelizable. However, when people find out ways to speed up their builds (in any language), advice starts to +circulate about how to unlock those speed boosts. If Roc had this feature, it's predictable that a commonly-accepted +piece of advice would eventually circulate: "don't use this feature because it slows down your builds." + +If a feature exists in a language, but the common recommendation is never to use it, that's cause for reconsidering +whether the feature should be in the language at all. In the case of this feature, it's simpler if the +language doesn't have it; that way nobody has to learn (or spend time spreading the word) about the +performance-boosting advice not to use it. + ## Why doesn't Roc have a `Maybe` or `Option` or `Optional` type, or `null` or `nil` or `undefined`? It's common for programming languages to have a [null reference](https://en.wikipedia.org/wiki/Null_pointer) @@ -174,7 +148,7 @@ On a historical note, `Maybe` may have been thought of as a substitute for null ## Why doesn't Roc have higher-kinded polymorphism or arbitrary-rank types? -_Since this is a FAQ answer, I'm going to assume familiarity with higher-kinded types and higher-rank types instead of including a primer on them._ +_Since this is a FAQ answer, it assumes familiarity with higher-kinded types and higher-rank types instead of including a primer on them._ A valuable aspect of Roc's type system is that it has decidable [principal](https://en.wikipedia.org/wiki/Principal_type) type inference. This means that: @@ -188,34 +162,33 @@ would be unable to infer a type—and you'd have to write a type annotation. Thi situations where the editor would not be able to reliably tell you the type of part of your program, unlike today where it can accurately tell you the type of anything, even if you have no type annotations in your entire code base. -assuming that's right, here is a proposed new FAQ entry: +This is one factor that higher-rank and higher-kinded types have in common. There are other factors which are specific +to each. ### Higher-rank types -Roc uses a Rank-1 type system. Other languages, like Haskell, support Rank-2 or even arbitrary-rank (aka "Rank-N") types. Supporting higher-rank types in Roc has been discussed before, but it has several important downsides: - -- It would remove principal decidable type inference. (Only Rank-1 types are compatible with principal decidable type inference; Rank-2 types are decidable but the inferred types are not principal, and Rank 3+ types are not even fully decidable.) +Supporting higher-rank types in Roc has been discussed before, but it has several important downsides: + - It would increase the complexity of the language. - It would make some compiler error messages more confusing (e.g. they might mention `forall` because that was the most general type that could be inferred, even if that wasn't helpful or related to the actual problem). - It would substantially increase the complexity of the type checker, which would necessarily slow it down. -- Most significantly, it would make the runtime slower, because Roc compiles programs by fully specializing all function calls to their type instances (this is sometimes called monomorphization). It's unclear how we could fully specialize programs containing Rank-2 types, which means compiling programs that included Rank-2 types (or higher) would require losing specialization in general—which would substantially degrade runtime performance. +- It would make some Roc programs run significantly more slowly. Roc compiles programs by [monomorphizing](https://en.wikipedia.org/wiki/Monomorphization), and it's unclear how we could fully monomorphize programs containing Rank-2 types. This means compiling programs which include Rank-2 types (or higher) would require sacrificing monomorphization, which would substantially degrade runtime performance. As such, the plan is for Roc to stick with Rank-1 types indefinitely. ### Higher-kinded polymorphism -I want to be really clear about this one: the explicit plan is that Roc will never support higher-kinded polymorphism. +The explicit plan is that Roc will never support higher-kinded polymorphism. -On the technical side, the reasons for this are ordinary: I understand the practical benefits and -drawbacks of HKP, and I think the drawbacks outweigh the benefits when it comes to Roc. (Those who come to a -different conclusion may think HKP's drawbacks would be less of a big a deal in Roc than I do. That's reasonable; -we programmers often weigh the same trade-offs differently.) To be clear, I think this in the specific context of -Roc; there are plenty of other languages where HKP seems like a great fit. For example, it's hard to imagine Haskell -without it. Similarly, I think lifetime annotations are a great fit for Rust, but don't think they'd be right -for Roc either. +On the technical side, the reasons for this are ordinary: like any language feature, HKP has both benefits and drawbacks, +and in the context of Roc, the drawbacks seem to outweigh the benefits. (Those who come to a different conclusion may +think HKP's drawbacks would be less of a big a deal in Roc. That's reasonable; we programmers often weigh the same +trade-offs differently.) To be clear, this analysis of HKP is in the specific context of Roc; there are plenty of +other languages where HKP seems like a great fit. For example, it's hard to imagine Haskell without it. Similarly, +lifetime annotations might be a natural fit for Rust, but they wouldn't be a good fit for Roc either. -I also think it's important to consider the cultural implications of deciding whether or not to support HKP. -To illustrate what I mean, imagine this conversation: +It's also important to consider the cultural implications of deciding whether or not to support HKP. +To illustrate these implications, imagine this conversation: **Programmer 1:** "How do you feel about higher-kinded polymorphism?" @@ -225,9 +198,9 @@ To illustrate what I mean, imagine this conversation: **Programmer 2:** "OH NO." -I've had several variations of this conversation: I'm talking about higher-kinded types, -another programmer asks what that means, I give monads as an example, and their reaction is strongly negative. -I've also had plenty of conversations with programmers who love HKP and vigorously advocate for its addition +For some, this conversation does not require imagining, because it's so familiar: higher-kinded types come up in +conversation, another programmer asks what that means, monads are given as an example, and their reaction is +strongly negative. On the flip side, plenty of programmers love HKP and vigorously advocate for its addition to languages they use which don't have it. Feelings about HKP seem strongly divided, maybe more so than any other type system feature besides static and dynamic types. @@ -237,67 +210,28 @@ language will inevitably follow. If the language does support HKP, one or more a around monads will inevitably follow, along with corresponding cultural changes. (See Scala for example.) Culturally, to support HKP is to take a side, and to decline to support it is also to take a side. -Given this, language designers have three options: +Given this, languages have three options: - Have HKP and have Monad in the standard library. Embrace them and build a culture and ecosystem around them. - Have HKP and don't have Monad in the standard library. An alternate standard library built around monads will inevitably emerge, and both the community and ecosystem will divide themselves along pro-monad and anti-monad lines. - Don't have HKP; build a culture and ecosystem around other things. -Considering that these are the only three options, I think the best choice for Roc—not only on a technical -level, but on a cultural level as well—is to make it clear that the plan is for Roc never to support HKP. -I hope this clarity can save a lot of community members' time that would otherwise be spent on advocacy or -arguing between the two sides of the divide. Again, I think it's completely reasonable for anyone to have a -different preference, but given that language designers can only choose one of these options, I'm confident -I've made the right choice for Roc by designing it never to have higher-kinded polymorphism. - -## Why do Roc's syntax and standard library differ from Elm's? - -Roc is a direct descendant of [Elm](https://elm-lang.org/). However, there are some differences between the two languages. - -Syntactic differences are among these. This is a feature, not a bug; if Roc had identical syntax to Elm, then it's -predictable that people would write code that was designed to work in both languages - and would then rely on -that being true, for example by making a package which advertised "Works in both Elm and Roc!" This in turn -would mean that later if either language were to change its syntax in a way that didn't make sense for the other, -the result would be broken code and sadness. - -So why does Roc have the specific syntax changes it does? Here are some brief explanations: - -- `#` instead of `--` for comments - this allows [hashbang](https://senthilnayagan.medium.com/shebang-hashbang-10966b8f28a8)s to work without needing special syntax. That isn't a use case Elm supports, but it is one Roc is designed to support. -- `{}` instead of `()` for the unit type - Elm has both, and they can both be used as a unit type. Since `{}` has other uses in the type system, but `()` doesn't, I consider it redundant and took it out. -- `when`...`is` instead of `case`...`of` - I predict it will be easier for beginners to pick up, because usually the way I explain `case`...`of` to beginners is by saying the words "when" and "is" out loud - e.g. "when `color` is `Red`, it runs this first branch; when `color` is `Blue`, it runs this other branch..." -- `:` instead of `=` for record field definitions (e.g. `{ foo: bar }` where Elm syntax would be `{ foo = bar }`): I like `=` being reserved for definitions, and `:` is the most popular alternative. -- Backpassing syntax - since Roc is designed to be used for use cases like command-line apps, shell scripts, and servers, I expect chained effects to come up a lot more often than they do in Elm. I think backpassing is nice for those use cases, similarly to how `do` notation is nice for them in Haskell. -- Tag unions instead of Elm's custom types (aka algebraic data types). This isn't just a syntactic change; tag unions are mainly in Roc because they can facilitate errors being accumulated across chained effects, which (as noted a moment ago) I expect to be a lot more common in Roc than in Elm. If you have tag unions, you don't really need a separate language feature for algebraic data types, since closed tag unions essentially work the same way - aside from not giving you a way to selectively expose variants or define phantom types. Roc's opaque types language feature covers those use cases instead. -- No `::` operator, or `::` pattern matching for lists. Both of these are for the same reason: an Elm `List` is a linked list, so both prepending to it and removing an element from the front are very cheap operations. In contrast, a Roc `List` is a flat array, so both prepending to it and removing an element from the front are among the most expensive operations you can possibly do with it! To get good performance, this usage pattern should be encouraged in Elm and discouraged in Roc. Since having special syntax would encourage it, it would not be good for Roc to have that syntax! -- No `<|` operator. In Elm, I almost exclusively found myself wanting to use this in conjunction with anonymous functions (e.g. `foo <| \bar -> ...`) or conditionals (e.g. `foo <| if bar then ...`). In Roc you can do both of these without the `<|`. That means the main remaining use for `<|` is to reduce parentheses, but I tend to think `|>` is better at that (or else the parens are fine), so after the other syntactic changes, I considered `<|` an unnecessary stylistic alternative to `|>` or parens. -- The `|>` operator passes the expression before the `|>` as the _first_ argument to the function after the `|>` instead of as the last argument. See the section on currying for details on why this works this way. -- `:` instead of `type alias` - I like to avoid reserved keywords for terms that are desirable in userspace, so that people don't have to name things `typ` because `type` is a reserved keyword, or `clazz` because `class` is reserved. (I couldn't think of satisfactory alternatives for `as`, `when`, `is`, or `if` other than different reserved keywords. I could see an argument for `then`—and maybe even `is`—being replaced with a `->` or `=>` or something, but I don't anticipate missing either of those words much in userspace. `then` is used in JavaScript promises, but I think there are several better names for that function.) -- No underscores in variable names - I've seen Elm beginners reflexively use `snake_case` over `camelCase` and then need to un-learn the habit after the compiler accepted it. I'd rather have the compiler give feedback that this isn't the way to do it in Roc, and suggest a camelCase alternative. I've also seen underscores used for lazy naming, e.g. `foo` and then `foo_`. If lazy naming is the goal, `foo2` is just as concise as `foo_`, but `foo3` is more concise than `foo__`. So in a way, removing `_` is a forcing function for improved laziness. (Of course, more descriptive naming would be even better.) Acronyms also use camelCase despite being capitalized in English, eg. `xmlHttpRequest` for a variable and `XmlHttpRequest` for a type. Each word starts with a capital letter, so if acronyms are only capitals it's harder to see where the words start. eg. `XMLHTTPRequest` is less clear than `XmlHttpRequest`, unless you already know the acronyms. -- Trailing commas - I've seen people walk away (in some cases physically!) from Elm as soon as they saw the leading commas in collection literals. While I think they've made a mistake by not pushing past this aesthetic preference to give the language a chance, I also would prefer not put them in a position to make such a mistake in the first place. Secondarily, while I'm personally fine with either style, between the two I prefer the look of trailing commas. -- The `!` unary prefix operator. I didn't want to have a `Basics` module (more on that in a moment), and without `Basics`, this would either need to be called fully-qualified (`Bool.not`) or else a module import of `Bool.{ not }` would be necessary. Both seemed less nice than supporting the `!` prefix that's common to so many widely-used languages, especially when we already have a unary prefix operator of `-` for negation (e.g. `-x`). -- `!=` for the inequality operator (instead of Elm's `/=`) - this one pairs more naturally with the `!` prefix operator and is also very common in other languages. - -Roc also has a different standard library from Elm. Some of the differences come down to platforms and applications (e.g. having `Task` in Roc's standard library wouldn't make sense), but others do not. Here are some brief explanations: - -- No `Basics` module. I wanted to have a simple rule of "all modules in the standard library are imported by default, and so are their exposed types," and that's it. Given that I wanted the comparison operators (e.g. `<`) to work only on numbers, it ended up that having `Num` and `Bool` modules meant that almost nothing would be left for a `Basics` equivalent in Roc except `identity` and `Never`. The Roc type `[]` (empty tag union) is equivalent to `Never`, so that wasn't necessary, and I generally think that `identity` is a good concept but a sign of an incomplete API whenever its use comes up in practice. For example, instead of calling `|> List.filterMap identity` I'd rather have access to a more self-descriptive function like `|> List.dropNothings`. With `Num` and `Bool`, and without `identity` and `Never`, there was nothing left in `Basics`. -- `Str` instead of `String` - after using the `str` type in Rust, I realized I had no issue whatsoever with the more concise name, especially since it was used in so many places (similar to `Msg` and `Cmd` in Elm) - so I decided to save a couple of letters. -- No function composition operators - I stopped using these in Elm so long ago, at one point I forgot they were in the language! See the FAQ entry on currying for details about why. -- No `Char`. What most people think of as a "character" is a rendered glyph. However, rendered glyphs are comprised of [grapheme clusters](https://stackoverflow.com/a/27331885), which are a variable number of Unicode code points - and there's no upper bound on how many code points there can be in a single cluster. In a world of emoji, I think this makes `Char` error-prone and it's better to have `Str` be the only first-class unit. For convenience when working with unicode code points (e.g. for performance-critical tasks like parsing), the single-quote syntax is sugar for the corresponding `U32` code point - for example, writing `'鹏'` is exactly the same as writing `40527`. Like Rust, you get a compiler error if you put something in single quotes that's not a valid [Unicode scalar value](http://www.unicode.org/glossary/#unicode_scalar_value). -- No `Maybe`. See the "Why doesn't Roc have a `Maybe`/`Option`/`Optional` type" FAQ question +Considering that these are the only three options, an early decision in Roc's design—not only on a technical +level, but on a cultural level as well—was to make it clear that the plan is for Roc never to support HKP. +The hope is that this clarity can save a lot of community members' time that would otherwise be spent on advocacy or +arguing between the two sides of the divide. Again, it's completely reasonable for anyone to have a different preference, +but given that languages can only choose one of these options, it seems clear that the right choice for Roc +is for it to never have higher-kinded polymorphism. ## Why aren't Roc functions curried by default? Although technically any language with first-class functions makes it possible to curry -any function (e.g. I can manually curry a Roc function `\x, y, z ->` by writing `\x -> \y -> \z ->` instead), +any function (e.g. anyone can manually curry a Roc function `\x, y, z ->` by writing `\x -> \y -> \z ->` instead), typically what people mean when they say Roc isn't a curried language is that Roc functions aren't curried -by default. For the rest of this section, I'll use "currying" as a shorthand for "functions that are curried +by default. The rest of this section will use "currying" as a shorthand for "functions that are curried by default" for the sake of brevity. -As I see it, currying has one major upside and several major downsides. The upside: - -- It makes function calls more concise in some cases. - -The downsides: +Currying makes function calls more concise in some cases, but it has several significant downsides: - It lowers error message quality, because there can no longer be an error for "function called with too few arguments." (Calling a function with fewer arguments is always valid in curried functions; the error you get instead will unavoidably be some other sort of type mismatch, and it will be up to you to figure out that the real problem was that you forgot an argument.) - It makes the `|>` operator more error-prone in some cases. @@ -306,10 +240,10 @@ The downsides: - It facilitates pointfree function composition. (More on why this is listed as a downside later.) There's also a downside that it would make runtime performance of compiled programs worse by default, -but I assume it would be possible to optimize that away at the cost of slightly longer compile times. +but it would most likely be possible to optimize that away at the cost of slightly longer compile times. -I consider the one upside (conciseness in some places) extremely minor, and have almost never missed it in Roc. -Here are some more details about the downsides as I see them. +These downsides seem to outweigh the one upside (conciseness in some places). Here are some more details about each of +the downsides. ### Currying and the `|>` operator @@ -324,11 +258,17 @@ Str.concat "Hello, " "World!" |> Str.concat "World!" ``` -In curried languages with a `|>` operator, the first expression still returns `"Hello, World!"` but the second one returns `"World!Hello, "`. This is because Roc's `|>` operator uses the expression before the `|>` as the _first_ argument, whereas in curried languages, `|>` uses it as the _last_ argument. +It's unsurprising to most beginners that these work the same way; it's common for a beginner who has recently learned +how `|>` works to assume that `|> Str.concat "!"` would concatenate `!` onto the end of a string. -(For example, this is how `|>` works in both [F#](https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/symbol-and-operator-reference/#function-symbols-and-operators) and in [Elm](https://package.elm-lang.org/packages/elm/core/1.0.5/Basics#|%3E), both of which are curried languages. In contrast, Roc's `|>` design uses the same argument ordering as [Elixir](https://hexdocs.pm/elixir/1.14.0/Kernel.html#%7C%3E/2) and [Gleam](https://gleam.run/book/tour/functions.html#pipe-operator), neither of which is a curried language.) +This is not how it works in curried languages, however. In curried languages with a `|>` operator, the first expression +still returns `"Hello, World!"` but the second one returns `"World!Hello, "` instead. This can be an unpleasant surprise +for beginners, but even experienced users commonly find that this behavior is less useful than having both of +these expressions evaluate to the same thing. -This comes up in other situations as well. For example, consider subtraction and division: +In Roc, both expressions evaluate to the same thing because Roc's `|>` operator uses the expression before the `|>` as the _first_ argument, whereas in curried languages, `|>` uses it as the _last_ argument. For example, this is how `|>` works in both [F#](https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/symbol-and-operator-reference/#function-symbols-and-operators) and in [Elm](https://package.elm-lang.org/packages/elm/core/1.0.5/Basics#|%3E), both of which are curried languages. In contrast, Roc's `|>` design uses the same argument ordering as [Elixir](https://hexdocs.pm/elixir/1.14.0/Kernel.html#%7C%3E/2) and [Gleam](https://gleam.run/book/tour/functions.html#pipe-operator), none of which are curried languages. + +This comes up in other situations besides string concatenation. For example, consider subtraction and division: ```elixir someNumber @@ -340,11 +280,14 @@ someNumber |> Num.sub 1 ``` -What do you expect these expressions to do? +Again, it's reasonable to expect that `|> Num.div 2` will divide a number by 2, and that +`|> Num.sub 1` will subtract 1 from a number. In Roc, this is how they work, but in +curried languages they work the opposite way: `|> Num.div 2` takes the number 2 and +divides it by a number, and `|> Num.sub 1` takes the number 1 and subtracts a number +from it. This is once again both more surprising to beginners and less useful to +experienced users. -In Roc, the first divides `someNumber` by 2 and the second one subtracts 1 from `someNumber`. In languages where `|>` uses the other argument ordering, the first example instead takes 2 and divides it by `someNumber`, while the second takes 1 and subtracts `someNumber` from it. This was a pain point I ran into with curried languages, and I was pleasantly surprised that changing the argument ordering in `|>` addressed the pain point. - -This style has a second benefit when it comes to higher-order functions. Consider these two examples: +The way `|>` works in Roc has a second benefit when it comes to higher-order functions. Consider these two examples: ```elixir answer = List.map numbers \num -> @@ -387,29 +330,33 @@ answer = numbers ``` -This was also a pain point I'd encountered in curried languages. I prefer the way the former example reads, but that style doesn't work with the argument order that currying encourages for higher-order functions like `List.map`. (Prior to using curried languages, I'd used [CoffeeScript](https://coffeescript.org/) in a functional style with [`_.map`](https://underscorejs.org/#map), and was disappointed to realize that I could no longer use the enjoyable style of `answer = _.map numbers (num) -> …` as I had before. In Roc, this style works.) +The Roc version of this is nicer in that it doesn't require parentheses around the function argument. A curried language +could theoretically adopt Roc's style of `|>` (where it pipes in the first argument instead of the last argument), but +to get this second benefit, the language would also need to have `List.map` take the function as its second argument +instead of the first. However, this would work against currying's one upside; it would no longer work to write +`(List.map negate)` if the `List.map` arguments were flipped, the way they are in Roc. So currying and `|>` are unavoidably +in tension. As a historical note, these stylistic benefits (of `|> Num.sub 1` working as expected, and being able to write `List.map numbers \num ->`) were not among the original reasons Roc did not have currying. These benefits were discovered after the decision had already been made that Roc would not be a curried language, and they served to reinforce after the fact that the decision was the right one for Roc given the language's goals. ### Currying and learning curve -Prior to designing Roc, I taught a lot of beginner [Elm](https://elm-lang.org/) workshops. Sometimes at -conferences, sometimes for [Frontend Masters](https://frontendmasters.com/courses/intro-elm/), -sometimes for free at local coding bootcamps or meetup groups. -In total I've spent well over 100 hours standing in front of a class, introducing the students to their -first pure functional programming language. +Currying leads to function signatures that look surprising to beginners. For example, in Roc, the +[`Bool.and`](https://www.roc-lang.org/builtins/Bool#and) function has the type `Bool, Bool -> Bool`. If Roc were a +curried language, this function would instead have the type `Bool -> Bool -> Bool`. Since no mainstream programming +languages today are curried, anyone who knows a mainstream language and is learning their first curried language will +require additional explanation about why function types look this way. -Here was my experience teaching currying: +This explanation is nontrivial. It requires explaining partial application, how curried functions facilitate partial +application, how function signatures accurately reflect that they're curried, and going through examples for all of these. +All of it builds up to the punchline that "technically, all functions in this language have a single argument," which +some percentage of learners find interesting, and some percentage still find confusing even after all that explanation. -- The only way to avoid teaching it is to refuse to explain why multi-argument functions have multiple `->`s in them. (If you don't explain it, at least one student will ask about it - and many if not all of the others will wonder.) -- Teaching currying properly takes a solid chunk of time, because it requires explaining partial application, explaining how curried functions facilitate partial application, how function signatures accurately reflect that they're curried, and going through examples for all of these. -- Even after doing all this, and iterating on my approach each time to try to explain it more effectively than I had the time before, I'd estimate that under 50% of the class ended up actually understanding currying. I consistently heard that in practice it only "clicked" for most people after spending significantly more time writing code with it. - -This is not the end of the world, especially because it's easy enough to think "okay, I still don't totally get this -even after that explanation, but I can remember that function arguments are separated by `->` in this language -and maybe I'll understand the rest later." (Which they almost always do, if they stick with the language.) -Clearly currying doesn't preclude a language from being easy to learn, because Elm has currying, and Elm's learning -curve is famously gentle. +It's common for beginners to report that currying only "clicked" for them after spending significant time writing code +in a curried language. This is not the end of the world, especially because it's easy enough to think "I still don't +totally get this even after that explanation, but I can remember that function arguments are separated by `->` in this +language and maybe I'll understand the rest later." Clearly currying doesn't preclude a language from being easy to learn, +because Elm has currying, and Elm's learning curve is famously gentle. That said, beginners who feel confused while learning the language are less likely to continue with it. And however easy Roc would be to learn if it had currying, the language is certainly easier to learn without it. @@ -428,37 +375,26 @@ compose : (a -> b), (c -> a) -> (c -> b) compose = \f, g, x -> f (g x) ``` -Here's how I would instead write this: +Here's a way to write it without pointfree function composition: ```elm reverseSort : List elem -> List elem reverseSort = \list -> List.reverse (List.sort list) ``` -I've consistently found that I can more quickly and accurately understand function definitions that use -named arguments, even though the code is longer. I suspect this is because I'm faster at reading than I am at -eta-expanding ( e.g. converting `List.sort` into `\l -> List.sort l` ). Whenever I read -the top version I end up needing to mentally eta-expand it into the bottom version. -In more complex examples (this is among the tamest pointfree function composition examples I've seen), I make -a mistake in my mental eta-expansion, and misunderstand what the function is doing - which can cause bugs. +It's common for programmers to build a mental model of what `compose List.reverse List.sort` does by mentally +translating it into `\list -> List.reverse (List.sort list)`. This extra mental translation step makes it take +longer to read and to understand despite being technically more concise. In more complex examples (this +is among the tamest of pointfree function composition examples), the chances increase of making a mistake in +the mental translation step, leading to a misundesrtanding of what the function is doing—which can cause bugs. -I assumed I would get faster and more accurate at this over time. However, by now it's been about a decade -since I first learned about the technique, and I'm still slower and less accurate at reading code that uses -pointfree function composition (including if I wrote it - but even moreso if I didn't) than code written with -with named arguments. I've asked a lot of other programmers about their experiences with pointfree function -composition over the years, and the overwhelming majority of responses have been consistent with my experience. - -As such, my opinion about pointfree function composition has gotten less and less nuanced over time. I've now moved -past "it's the right tool for the job, sometimes" to concluding it's best thought of as an antipattern. This is -because I realized how much time I was spending evaluating on a case-by-case basis whether it might be the -right fit for a given situation. The time spent on this analysis alone vastly outweighed the sum of all the -benefits I got in the rare cases where I concluded it was a fit. So I've found the way to get the most out of -pointfree function composition is to never even think about using it; every other strategy leads to a worse outcome. - -Currying facilitates the antipattern of pointfree function composition, which I view as a downside of currying. +Some languages place such a high value on conciseness that they would consider the conciceness upside to outweigh +these downsides, but Roc is not one of those languages. It's considered stylistically better in Roc to write the +second version above. Given this, since currying facilitates pointfree function composition, making Roc a curried +language would have the downside of facilitating an antipattern in the language. Stacking up all these downsides of currying against the one upside of making certain function calls more concise, -I concluded that it would be a mistake to have it in Roc. +it seems clear that Roc should not be a curried language. ## Will Roc ever have linear types, dependent types, refinement types, or uniqueness types? diff --git a/ci/basic_nightly_test.sh b/ci/basic_nightly_test.sh index dca5da8ae0..ea60517be6 100755 --- a/ci/basic_nightly_test.sh +++ b/ci/basic_nightly_test.sh @@ -29,11 +29,26 @@ mv roc_nightly* roc_nightly cd roc_nightly # test roc hello world -./roc examples/helloWorld.roc +./roc examples/helloWorld.roc ./roc examples/platform-switching/rocLovesRust.roc -./roc examples/platform-switching/rocLovesZig.roc +run_zig_test=true +# Detect macOS version +if [[ "$(uname)" == "Darwin" ]]; then + macos_version=$(sw_vers -productVersion) + major_version=$(echo $macos_version | cut -d. -f1) + + # If macOS 13, then set the flag to skip + if [[ $major_version -eq 13 ]]; then + echo "Skipping zig test on macOS 13 due to https://github.com/roc-lang/roc/issues/5590..." + run_zig_test=false + fi +fi + +if $run_zig_test ; then + ./roc examples/platform-switching/rocLovesZig.roc +fi ./roc examples/platform-switching/rocLovesC.roc diff --git a/crates/cli/tests/cli_run.rs b/crates/cli/tests/cli_run.rs index f39dce01bb..a1fb9c49f0 100644 --- a/crates/cli/tests/cli_run.rs +++ b/crates/cli/tests/cli_run.rs @@ -309,7 +309,7 @@ mod cli_run { if !actual.ends_with(expected_ending) { panic!( - "expected output to end with:\n{}\nbut instead got:\n{}\n stderr was:\n{}", + "> expected output to end with:\n{}\n> but instead got:\n{}\n> stderr was:\n{}", expected_ending, actual, out.stderr ); } @@ -387,7 +387,7 @@ mod cli_run { let mut custom_flags: Vec<&str> = Vec::new(); match executable_filename { - "form" | "hello-gui" | "breakout" | "libhello" => { + "form" | "hello-gui" | "breakout" | "libhello" | "inspect-gui" => { // Since these require things the build system often doesn't have // (e.g. GUIs open a window, Ruby needs ruby installed, WASM needs a browser) // we do `roc build` on them but don't run them. @@ -938,6 +938,30 @@ mod cli_run { test_roc_expect("examples/parser/package", "ParserHttp.roc") } + #[test] + #[cfg_attr(windows, ignore)] + fn inspect_logging() { + test_roc_app_slim( + "examples", + "inspect-logging.roc", + "inspect-logging", + r#"{people: [{firstName: "John", lastName: "Smith", age: 27, hasBeard: true, favoriteColor: Blue}, {firstName: "Debby", lastName: "Johnson", age: 47, hasBeard: false, favoriteColor: Green}, {firstName: "Jane", lastName: "Doe", age: 33, hasBeard: false, favoriteColor: (RGB (255, 255, 0))}], friends: [{2}, {2}, {0, 1}]} +"#, + UseValgrind::Yes, + ) + } + + #[test] + fn inspect_gui() { + test_roc_app_slim( + "examples", + "inspect-gui.roc", + "inspect-gui", + "", + UseValgrind::No, + ) + } + // TODO not sure if this cfg should still be here: #[cfg(not(debug_assertions))] // this is for testing the benchmarks, to perform proper benchmarks see crates/cli/benches/README.md mod test_benchmarks { diff --git a/crates/cli_testing_examples/benchmarks/AStar.roc b/crates/cli_testing_examples/benchmarks/AStar.roc index 2021ac1877..14f4a42dbc 100644 --- a/crates/cli_testing_examples/benchmarks/AStar.roc +++ b/crates/cli_testing_examples/benchmarks/AStar.roc @@ -10,9 +10,9 @@ Model position : { openSet : Set position, costs : Dict position F64, cameFrom : Dict position position, -} | position has Hash & Eq +} where position implements Hash & Eq -initialModel : position -> Model position | position has Hash & Eq +initialModel : position -> Model position where position implements Hash & Eq initialModel = \start -> { evaluated: Set.empty {}, openSet: Set.single start, @@ -20,7 +20,7 @@ initialModel = \start -> { cameFrom: Dict.empty {}, } -cheapestOpen : (position -> F64), Model position -> Result position {} | position has Hash & Eq +cheapestOpen : (position -> F64), Model position -> Result position {} where position implements Hash & Eq cheapestOpen = \costFn, model -> model.openSet |> Set.toList @@ -35,13 +35,13 @@ cheapestOpen = \costFn, model -> |> Result.map .position |> Result.mapErr (\_ -> {}) -reconstructPath : Dict position position, position -> List position | position has Hash & Eq +reconstructPath : Dict position position, position -> List position where position implements Hash & Eq reconstructPath = \cameFrom, goal -> when Dict.get cameFrom goal is Err _ -> [] Ok next -> List.append (reconstructPath cameFrom next) goal -updateCost : position, position, Model position -> Model position | position has Hash & Eq +updateCost : position, position, Model position -> Model position where position implements Hash & Eq updateCost = \current, neighbor, model -> newCameFrom = Dict.insert model.cameFrom neighbor current @@ -70,7 +70,7 @@ updateCost = \current, neighbor, model -> else model -astar : (position, position -> F64), (position -> Set position), position, Model position -> Result (List position) {} | position has Hash & Eq +astar : (position, position -> F64), (position -> Set position), position, Model position -> Result (List position) {} where position implements Hash & Eq astar = \costFn, moveFn, goal, model -> when cheapestOpen (\source -> costFn source goal) model is Err {} -> Err {} diff --git a/crates/cli_testing_examples/benchmarks/platform/main.roc b/crates/cli_testing_examples/benchmarks/platform/main.roc index 0b86055696..e4802e2503 100644 --- a/crates/cli_testing_examples/benchmarks/platform/main.roc +++ b/crates/cli_testing_examples/benchmarks/platform/main.roc @@ -5,5 +5,5 @@ platform "benchmarks" imports [Task.{ Task }] provides [mainForHost] -mainForHost : Task {} [] as Fx +mainForHost : Task {} [] mainForHost = main diff --git a/crates/compiler/alias_analysis/src/lib.rs b/crates/compiler/alias_analysis/src/lib.rs index 598406dffb..77902fc496 100644 --- a/crates/compiler/alias_analysis/src/lib.rs +++ b/crates/compiler/alias_analysis/src/lib.rs @@ -14,7 +14,7 @@ use roc_module::low_level::LowLevel; use roc_module::symbol::Symbol; use roc_mono::ir::{ - Call, CallType, EntryPoint, ErasedField, Expr, HigherOrderLowLevel, HostExposedLayouts, + Call, CallType, EntryPoint, ErasedField, Expr, HigherOrderLowLevel, HostExposedLambdaSet, ListLiteralElement, Literal, ModifyRc, OptLevel, Proc, ProcLayout, SingleEntryPoint, Stmt, }; use roc_mono::layout::{ @@ -137,15 +137,17 @@ fn bytes_as_ascii(bytes: &[u8]) -> String { buf } -pub fn spec_program<'a, 'r, I>( +pub fn spec_program<'a, 'r, I1, I2>( arena: &'a Bump, interner: &'r STLayoutInterner<'a>, opt_level: OptLevel, entry_point: roc_mono::ir::EntryPoint<'a>, - procs: I, + procs: I1, + hels: I2, ) -> Result where - I: Iterator>, + I1: Iterator>, + I2: Iterator>, { let main_module = { let mut m = ModDefBuilder::new(); @@ -183,50 +185,36 @@ where let mut host_exposed_functions = Vec::new(); let mut erased_functions = Vec::new(); + for hels in hels { + match hels.raw_function_layout { + RawFunctionLayout::Function(_, _, _) => { + let it = hels.proc_layout.arguments.iter().copied(); + let bytes = + func_name_bytes_help(hels.symbol, it, Niche::NONE, hels.proc_layout.result); + + host_exposed_functions.push((bytes, hels.proc_layout.arguments)); + } + RawFunctionLayout::ErasedFunction(..) => { + let it = hels.proc_layout.arguments.iter().copied(); + let bytes = + func_name_bytes_help(hels.symbol, it, Niche::NONE, hels.proc_layout.result); + + host_exposed_functions.push((bytes, hels.proc_layout.arguments)); + } + RawFunctionLayout::ZeroArgumentThunk(_) => { + let bytes = + func_name_bytes_help(hels.symbol, [], Niche::NONE, hels.proc_layout.result); + + host_exposed_functions.push((bytes, hels.proc_layout.arguments)); + } + } + } + // all other functions for proc in procs { let bytes = func_name_bytes(proc); let func_name = FuncName(&bytes); - if let HostExposedLayouts::HostExposed { aliases, .. } = &proc.host_exposed_layouts { - for (_, hels) in aliases { - match hels.raw_function_layout { - RawFunctionLayout::Function(_, _, _) => { - let it = hels.proc_layout.arguments.iter().copied(); - let bytes = func_name_bytes_help( - hels.symbol, - it, - Niche::NONE, - hels.proc_layout.result, - ); - - host_exposed_functions.push((bytes, hels.proc_layout.arguments)); - } - RawFunctionLayout::ErasedFunction(..) => { - let it = hels.proc_layout.arguments.iter().copied(); - let bytes = func_name_bytes_help( - hels.symbol, - it, - Niche::NONE, - hels.proc_layout.result, - ); - - host_exposed_functions.push((bytes, hels.proc_layout.arguments)); - } - RawFunctionLayout::ZeroArgumentThunk(_) => { - let bytes = func_name_bytes_help( - hels.symbol, - [], - Niche::NONE, - hels.proc_layout.result, - ); - - host_exposed_functions.push((bytes, hels.proc_layout.arguments)); - } - } - } - } - if debug() { eprintln!( "{:?}: {:?} with {:?} args", diff --git a/crates/compiler/build/src/link.rs b/crates/compiler/build/src/link.rs index 7d8e800f30..03c55f767f 100644 --- a/crates/compiler/build/src/link.rs +++ b/crates/compiler/build/src/link.rs @@ -4,6 +4,7 @@ use roc_command_utils::{cargo, clang, rustup, zig}; use roc_error_macros::internal_error; use roc_mono::ir::OptLevel; use std::collections::HashMap; +use std::ffi::OsString; use std::fs::DirEntry; use std::io; use std::path::{Path, PathBuf}; @@ -785,11 +786,25 @@ fn get_target_str(target: &Triple) -> &str { } } -fn nix_path_opt() -> Option { - env::var_os("NIX_GLIBC_PATH").map(|path| path.into_string().unwrap()) +fn nix_paths() -> Vec { + let mut paths = vec![]; + + if let Some(nix_libgcc_s_path) = env::var_os("NIX_LIBGCC_S_PATH") { + paths.push(nix_libgcc_s_path.into_string().unwrap()) + } + + if let Some(nix_glibc_path) = nix_glibc_path_opt() { + paths.push(nix_glibc_path.into_string().unwrap()) + } + + paths } -fn library_path(segments: [&str; N]) -> Option { +fn nix_glibc_path_opt() -> Option { + env::var_os("NIX_GLIBC_PATH") +} + +fn build_path(segments: [&str; N]) -> Option { let mut guess_path = PathBuf::new(); for s in segments { guess_path.push(s); @@ -812,22 +827,21 @@ fn library_path(segments: [&str; N]) -> Option { /// match will be returned. /// /// If there are no matches, [`None`] will be returned. -fn look_for_library(lib_dirs: &[&[&str]], lib_filename: &str) -> Option { +fn look_for_library(lib_dirs: &[PathBuf], lib_filename: &str) -> Option { lib_dirs .iter() - .map(|lib_dir| { - lib_dir.iter().fold(PathBuf::new(), |mut path, segment| { - path.push(segment); - path - }) - }) - .map(|mut path| { - path.push(lib_filename); - path + .map(|path| { + let mut path_cl = path.clone(); + path_cl.push(lib_filename); + path_cl }) .find(|path| path.exists()) } +fn strs_to_path(strs: &[&str]) -> PathBuf { + strs.iter().collect() +} + fn link_linux( target: &Triple, output_path: PathBuf, @@ -862,50 +876,37 @@ fn link_linux( )); } - // Some things we'll need to build a list of dirs to check for libraries - let maybe_nix_path = nix_path_opt(); - let usr_lib_arch = ["/usr", "lib", &architecture]; - let lib_arch = ["/lib", &architecture]; - let nix_path_segments; - let lib_dirs_if_nix: [&[&str]; 5]; - let lib_dirs_if_nonix: [&[&str]; 4]; + let nix_paths_vec_string = nix_paths(); + let nix_paths_vec: Vec = nix_paths_vec_string.iter().map(PathBuf::from).collect(); + let usr_lib_arch_path = strs_to_path(&["/usr", "lib", &architecture]); + let lib_arch_path = strs_to_path(&["/lib", &architecture]); - // Build the aformentioned list - let lib_dirs: &[&[&str]] = - // give preference to nix_path if it's defined, this prevents bugs - if let Some(nix_path) = &maybe_nix_path { - nix_path_segments = [nix_path.as_str()]; - lib_dirs_if_nix = [ - &nix_path_segments, - &usr_lib_arch, - &lib_arch, - &["/usr", "lib"], - &["/usr", "lib64"], - ]; - &lib_dirs_if_nix - } else { - lib_dirs_if_nonix = [ - &usr_lib_arch, - &lib_arch, - &["/usr", "lib"], - &["/usr", "lib64"], - ]; - &lib_dirs_if_nonix - }; + let mut lib_dirs: Vec = vec![]; + + // start with nix paths, this prevents version incompatibility + if !nix_paths_vec.is_empty() { + lib_dirs.extend(nix_paths_vec) + } + + lib_dirs.extend([ + usr_lib_arch_path, + lib_arch_path, + strs_to_path(&["/usr", "lib"]), + strs_to_path(&["/usr", "lib64"]), + ]); // Look for the libraries we'll need - let libgcc_name = "libgcc_s.so.1"; - let libgcc_path = look_for_library(lib_dirs, libgcc_name); + let libgcc_path = look_for_library(&lib_dirs, libgcc_name); let crti_name = "crti.o"; - let crti_path = look_for_library(lib_dirs, crti_name); + let crti_path = look_for_library(&lib_dirs, crti_name); let crtn_name = "crtn.o"; - let crtn_path = look_for_library(lib_dirs, crtn_name); + let crtn_path = look_for_library(&lib_dirs, crtn_name); let scrt1_name = "Scrt1.o"; - let scrt1_path = look_for_library(lib_dirs, scrt1_name); + let scrt1_path = look_for_library(&lib_dirs, scrt1_name); // Unwrap all the paths at once so we can inform the user of all missing libs at once let (libgcc_path, crti_path, crtn_path, scrt1_path) = @@ -925,7 +926,13 @@ fn link_linux( let dirs = lib_dirs .iter() - .map(|segments| segments.join("/")) + .map(|path_buf| { + path_buf + .as_path() + .to_str() + .unwrap_or("FAILED TO CONVERT PATH TO STR") + .to_string() + }) .collect::>() .join("\n"); eprintln!("We looked in the following directories:\n{dirs}"); @@ -936,13 +943,16 @@ fn link_linux( let ld_linux = match target.architecture { Architecture::X86_64 => { // give preference to nix_path if it's defined, this prevents bugs - if let Some(nix_path) = nix_path_opt() { - library_path([&nix_path, "ld-linux-x86-64.so.2"]) + if let Some(nix_glibc_path) = nix_glibc_path_opt() { + build_path([ + &nix_glibc_path.into_string().unwrap(), + "ld-linux-x86-64.so.2", + ]) } else { - library_path(["/lib64", "ld-linux-x86-64.so.2"]) + build_path(["/lib64", "ld-linux-x86-64.so.2"]) } } - Architecture::Aarch64(_) => library_path(["/lib", "ld-linux-aarch64.so.1"]), + Architecture::Aarch64(_) => build_path(["/lib", "ld-linux-aarch64.so.1"]), _ => internal_error!( "TODO gracefully handle unsupported linux architecture: {:?}", target.architecture diff --git a/crates/compiler/build/src/program.rs b/crates/compiler/build/src/program.rs index 839b029116..c8e6fd2496 100644 --- a/crates/compiler/build/src/program.rs +++ b/crates/compiler/build/src/program.rs @@ -235,6 +235,7 @@ fn gen_from_mono_module_llvm<'a>( &loaded.layout_interner, opt_level, loaded.procedures, + loaded.host_exposed_lambda_sets, entry_point, Some(&app_ll_file), &loaded.glue_layouts, diff --git a/crates/compiler/builtins/roc/Bool.roc b/crates/compiler/builtins/roc/Bool.roc index d16e8b2494..c6d331a915 100644 --- a/crates/compiler/builtins/roc/Bool.roc +++ b/crates/compiler/builtins/roc/Bool.roc @@ -12,7 +12,7 @@ interface Bool ## be a `NaN` ([Not a Number](https://en.wikipedia.org/wiki/NaN)), and the ## [IEEE-754](https://en.wikipedia.org/wiki/IEEE_754) floating point standard ## specifies that two `NaN`s are not equal. -Eq has +Eq implements ## Returns `Bool.true` if the input values are equal. This is ## equivalent to the logic ## [XNOR](https://en.wikipedia.org/wiki/Logical_equality) gate. The infix @@ -30,11 +30,11 @@ Eq has ## for more detail. ## 5. Functions cannot be compared for structural equality, therefore Roc ## cannot derive `isEq` for types that contain functions. - isEq : a, a -> Bool | a has Eq + isEq : a, a -> Bool where a implements Eq ## Represents the boolean true and false using an opaque type. ## `Bool` implements the `Eq` ability. -Bool := [True, False] has [Eq { isEq: boolIsEq }] +Bool := [True, False] implements [Eq { isEq: boolIsEq }] boolIsEq = \@Bool b1, @Bool b2 -> structuralEq b1 b2 @@ -116,7 +116,7 @@ not : Bool -> Bool ## expect (Bool.false != Bool.false) == Bool.false ## expect "Apples" != "Oranges" ## ``` -isNotEq : a, a -> Bool | a has Eq +isNotEq : a, a -> Bool where a implements Eq isNotEq = \a, b -> structuralNotEq a b # INTERNAL COMPILER USE ONLY: used to lower calls to `isEq` to structural diff --git a/crates/compiler/builtins/roc/Decode.roc b/crates/compiler/builtins/roc/Decode.roc index 3f42aa6b62..dc68427b81 100644 --- a/crates/compiler/builtins/roc/Decode.roc +++ b/crates/compiler/builtins/roc/Decode.roc @@ -73,30 +73,30 @@ DecodeResult val : { result : Result val DecodeError, rest : List U8 } ## Decodes a `List U8` of utf-8 bytes where `val` is the type of the decoded ## value, and `fmt` is a [Decoder] which implements the [DecoderFormatting] ## ability -Decoder val fmt := List U8, fmt -> DecodeResult val | fmt has DecoderFormatting +Decoder val fmt := List U8, fmt -> DecodeResult val where fmt implements DecoderFormatting ## Definition of the [Decoding] ability -Decoding has - decoder : Decoder val fmt | val has Decoding, fmt has DecoderFormatting +Decoding implements + decoder : Decoder val fmt where val implements Decoding, fmt implements DecoderFormatting ## Definition of the [DecoderFormatting] ability -DecoderFormatting has - u8 : Decoder U8 fmt | fmt has DecoderFormatting - u16 : Decoder U16 fmt | fmt has DecoderFormatting - u32 : Decoder U32 fmt | fmt has DecoderFormatting - u64 : Decoder U64 fmt | fmt has DecoderFormatting - u128 : Decoder U128 fmt | fmt has DecoderFormatting - i8 : Decoder I8 fmt | fmt has DecoderFormatting - i16 : Decoder I16 fmt | fmt has DecoderFormatting - i32 : Decoder I32 fmt | fmt has DecoderFormatting - i64 : Decoder I64 fmt | fmt has DecoderFormatting - i128 : Decoder I128 fmt | fmt has DecoderFormatting - f32 : Decoder F32 fmt | fmt has DecoderFormatting - f64 : Decoder F64 fmt | fmt has DecoderFormatting - dec : Decoder Dec fmt | fmt has DecoderFormatting - bool : Decoder Bool fmt | fmt has DecoderFormatting - string : Decoder Str fmt | fmt has DecoderFormatting - list : Decoder elem fmt -> Decoder (List elem) fmt | fmt has DecoderFormatting +DecoderFormatting implements + u8 : Decoder U8 fmt where fmt implements DecoderFormatting + u16 : Decoder U16 fmt where fmt implements DecoderFormatting + u32 : Decoder U32 fmt where fmt implements DecoderFormatting + u64 : Decoder U64 fmt where fmt implements DecoderFormatting + u128 : Decoder U128 fmt where fmt implements DecoderFormatting + i8 : Decoder I8 fmt where fmt implements DecoderFormatting + i16 : Decoder I16 fmt where fmt implements DecoderFormatting + i32 : Decoder I32 fmt where fmt implements DecoderFormatting + i64 : Decoder I64 fmt where fmt implements DecoderFormatting + i128 : Decoder I128 fmt where fmt implements DecoderFormatting + f32 : Decoder F32 fmt where fmt implements DecoderFormatting + f64 : Decoder F64 fmt where fmt implements DecoderFormatting + dec : Decoder Dec fmt where fmt implements DecoderFormatting + bool : Decoder Bool fmt where fmt implements DecoderFormatting + string : Decoder Str fmt where fmt implements DecoderFormatting + list : Decoder elem fmt -> Decoder (List elem) fmt where fmt implements DecoderFormatting ## `record state stepField finalizer` decodes a record field-by-field. ## @@ -104,7 +104,7 @@ DecoderFormatting has ## `Skip` if the field is not a part of the decoded record. ## ## `finalizer` should produce the record value from the decoded `state`. - record : state, (state, Str -> [Keep (Decoder state fmt), Skip]), (state -> Result val DecodeError) -> Decoder val fmt | fmt has DecoderFormatting + record : state, (state, Str -> [Keep (Decoder state fmt), Skip]), (state -> Result val DecodeError) -> Decoder val fmt where fmt implements DecoderFormatting ## `tuple state stepElem finalizer` decodes a tuple element-by-element. ## @@ -113,7 +113,7 @@ DecoderFormatting has ## index passed to `stepElem` is 0-indexed. ## ## `finalizer` should produce the tuple value from the decoded `state`. - tuple : state, (state, Nat -> [Next (Decoder state fmt), TooLong]), (state -> Result val DecodeError) -> Decoder val fmt | fmt has DecoderFormatting + tuple : state, (state, Nat -> [Next (Decoder state fmt), TooLong]), (state -> Result val DecodeError) -> Decoder val fmt where fmt implements DecoderFormatting ## Build a custom [Decoder] function. For example the implementation of ## `decodeBool` could be defined as follows; @@ -125,11 +125,11 @@ DecoderFormatting has ## ['t', 'r', 'u', 'e', ..] -> { result: Ok Bool.true, rest: List.drop bytes 4 } ## _ -> { result: Err TooShort, rest: bytes } ## ``` -custom : (List U8, fmt -> DecodeResult val) -> Decoder val fmt | fmt has DecoderFormatting +custom : (List U8, fmt -> DecodeResult val) -> Decoder val fmt where fmt implements DecoderFormatting custom = \decode -> @Decoder decode ## Decode a `List U8` utf-8 bytes using a specific [Decoder] function -decodeWith : List U8, Decoder val fmt, fmt -> DecodeResult val | fmt has DecoderFormatting +decodeWith : List U8, Decoder val fmt, fmt -> DecodeResult val where fmt implements DecoderFormatting decodeWith = \bytes, @Decoder decode, fmt -> decode bytes fmt ## Decode a `List U8` utf-8 bytes and return a [DecodeResult](#DecodeResult) @@ -141,7 +141,7 @@ decodeWith = \bytes, @Decoder decode, fmt -> decode bytes fmt ## ## actual.result == expected ## ``` -fromBytesPartial : List U8, fmt -> DecodeResult val | val has Decoding, fmt has DecoderFormatting +fromBytesPartial : List U8, fmt -> DecodeResult val where val implements Decoding, fmt implements DecoderFormatting fromBytesPartial = \bytes, fmt -> decodeWith bytes decoder fmt ## Decode a `List U8` utf-8 bytes and return a [Result] with no leftover bytes @@ -155,7 +155,7 @@ fromBytesPartial = \bytes, fmt -> decodeWith bytes decoder fmt ## ## actual == expected ## ``` -fromBytes : List U8, fmt -> Result val [Leftover (List U8)]DecodeError | val has Decoding, fmt has DecoderFormatting +fromBytes : List U8, fmt -> Result val [Leftover (List U8)]DecodeError where val implements Decoding, fmt implements DecoderFormatting fromBytes = \bytes, fmt -> when fromBytesPartial bytes fmt is { result, rest } -> diff --git a/crates/compiler/builtins/roc/Dict.roc b/crates/compiler/builtins/roc/Dict.roc index ec316cf351..75d8e2882e 100644 --- a/crates/compiler/builtins/roc/Dict.roc +++ b/crates/compiler/builtins/roc/Dict.roc @@ -95,13 +95,13 @@ Dict k v := { # TODO: As an optimization, we can make all of these lists in one allocation # TODO: Grow data with the rest of the hashmap. This will require creating a list of garbage data. # TODO: Change remove to use tombstones. Store the tombstones in a bitmap. - # TODO: define Eq and Hash that are unordered. Only if value has hash/eq? + # TODO: define Eq and Hash that are unordered. Only if value implements hash/eq? metadata : List I8, dataIndices : List Nat, data : List (k, v), size : Nat, -} | k has Hash & Eq - has [ +} where k implements Hash & Eq + implements [ Eq { isEq, }, @@ -110,7 +110,7 @@ Dict k v := { }, ] -isEq : Dict k v, Dict k v -> Bool | k has Hash & Eq, v has Eq +isEq : Dict k v, Dict k v -> Bool where k implements Hash & Eq, v implements Eq isEq = \xs, ys -> if len xs != len ys then Bool.false @@ -123,14 +123,14 @@ isEq = \xs, ys -> _ -> Break Bool.false -hashDict : hasher, Dict k v -> hasher | k has Hash & Eq, v has Hash, hasher has Hasher +hashDict : hasher, Dict k v -> hasher where k implements Hash & Eq, v implements Hash, hasher implements Hasher hashDict = \hasher, dict -> Hash.hashUnordered hasher (toList dict) List.walk ## Return an empty dictionary. ## ``` ## emptyDict = Dict.empty {} ## ``` -empty : {} -> Dict k v | k has Hash & Eq +empty : {} -> Dict * * empty = \{} -> @Dict { metadata: List.repeat emptySlot 8, @@ -151,12 +151,12 @@ capacity : Dict * * -> Nat capacity = \@Dict { dataIndices } -> cap = List.len dataIndices - cap - Num.shiftRightZfBy cap 3 + Num.subWrap cap (Num.shiftRightZfBy cap 3) ## Return a dictionary with space allocated for a number of entries. This ## may provide a performance optimization if you know how many entries will be ## inserted. -withCapacity : Nat -> Dict k v | k has Hash & Eq +withCapacity : Nat -> Dict * * withCapacity = \_ -> # TODO: power of 2 * 8 and actual implementation empty {} @@ -167,7 +167,7 @@ withCapacity = \_ -> ## Dict.single "A" "B" ## |> Bool.isEq (Dict.insert (Dict.empty {}) "A" "B") ## ``` -single : k, v -> Dict k v | k has Hash & Eq +single : k, v -> Dict k v where k implements Hash & Eq single = \k, v -> insert (empty {}) k v @@ -180,7 +180,7 @@ single = \k, v -> ## |> Dict.insert 4 "Four" ## |> Bool.isEq (Dict.fromList [(1, "One"), (2, "Two"), (3, "Three"), (4, "Four")]) ## ``` -fromList : List (k, v) -> Dict k v | k has Hash & Eq +fromList : List (k, v) -> Dict k v where k implements Hash & Eq fromList = \data -> # TODO: make this efficient. Should just set data and then set all indicies in the hashmap. List.walk data (empty {}) (\dict, (k, v) -> insert dict k v) @@ -221,7 +221,7 @@ isEmpty = \@Dict { size } -> ## ## expect Dict.len clearSongs == 0 ## ``` -clear : Dict k v -> Dict k v | k has Hash & Eq +clear : Dict k v -> Dict k v where k implements Hash & Eq clear = \@Dict { metadata, dataIndices, data } -> cap = List.len dataIndices @@ -241,7 +241,7 @@ clear = \@Dict { metadata, dataIndices, data } -> ## Convert each value in the dictionary to something new, by calling a conversion ## function on each of them which receives both the key and the old value. Then return a ## new dictionary containing the same keys and the converted values. -map : Dict k a, (k, a -> b) -> Dict k b | k has Hash & Eq, b has Hash & Eq +map : Dict k a, (k, a -> b) -> Dict k b where k implements Hash & Eq, b implements Hash & Eq map = \dict, transform -> init = withCapacity (capacity dict) @@ -253,7 +253,7 @@ map = \dict, transform -> ## (using [Dict.insertAll]) into one dictionary. ## ## You may know a similar function named `concatMap` in other languages. -joinMap : Dict a b, (a, b -> Dict x y) -> Dict x y | a has Hash & Eq, x has Hash & Eq +joinMap : Dict a b, (a, b -> Dict x y) -> Dict x y where a implements Hash & Eq, x implements Hash & Eq joinMap = \dict, transform -> init = withCapacity (capacity dict) # Might be a pessimization @@ -271,7 +271,7 @@ joinMap = \dict, transform -> ## |> Dict.walk 0 (\count, _, qty -> count + qty) ## |> Bool.isEq 36 ## ``` -walk : Dict k v, state, (state, k, v -> state) -> state | k has Hash & Eq +walk : Dict k v, state, (state, k, v -> state) -> state where k implements Hash & Eq walk = \@Dict { data }, initialState, transform -> List.walk data initialState (\state, (k, v) -> transform state k v) @@ -303,7 +303,7 @@ walk = \@Dict { data }, initialState, transform -> ## ## expect someoneIsAnAdult == Bool.true ## ``` -walkUntil : Dict k v, state, (state, k, v -> [Continue state, Break state]) -> state | k has Hash & Eq +walkUntil : Dict k v, state, (state, k, v -> [Continue state, Break state]) -> state where k implements Hash & Eq walkUntil = \@Dict { data }, initialState, transform -> List.walkUntil data initialState (\state, (k, v) -> transform state k v) @@ -318,7 +318,7 @@ walkUntil = \@Dict { data }, initialState, transform -> ## expect Dict.get dictionary 1 == Ok "Apple" ## expect Dict.get dictionary 2000 == Err KeyNotFound ## ``` -get : Dict k v, k -> Result v [KeyNotFound] | k has Hash & Eq +get : Dict k v, k -> Result v [KeyNotFound] where k implements Hash & Eq get = \@Dict { metadata, dataIndices, data }, key -> hashKey = createLowLevelHasher PseudoRandSeed @@ -346,7 +346,7 @@ get = \@Dict { metadata, dataIndices, data }, key -> ## |> Dict.contains 1234 ## |> Bool.isEq Bool.true ## ``` -contains : Dict k v, k -> Bool | k has Hash & Eq +contains : Dict k v, k -> Bool where k implements Hash & Eq contains = \@Dict { metadata, dataIndices, data }, key -> hashKey = createLowLevelHasher PseudoRandSeed @@ -371,7 +371,7 @@ contains = \@Dict { metadata, dataIndices, data }, key -> ## |> Dict.get "Apples" ## |> Bool.isEq (Ok 12) ## ``` -insert : Dict k v, k, v -> Dict k v | k has Hash & Eq +insert : Dict k v, k, v -> Dict k v where k implements Hash & Eq insert = \@Dict { metadata, dataIndices, data, size }, key, value -> hashKey = createLowLevelHasher PseudoRandSeed @@ -401,7 +401,7 @@ insert = \@Dict { metadata, dataIndices, data, size }, key, value -> metadata, dataIndices, data, - size: size + 1, + size: Num.addWrap size 1, } ) @@ -417,7 +417,7 @@ insert = \@Dict { metadata, dataIndices, data, size }, key, value -> ## |> Dict.len ## |> Bool.isEq 0 ## ``` -remove : Dict k v, k -> Dict k v | k has Hash & Eq +remove : Dict k v, k -> Dict k v where k implements Hash & Eq remove = \@Dict { metadata, dataIndices, data, size }, key -> # TODO: change this from swap remove to tombstone and test is performance is still good. hashKey = @@ -430,7 +430,7 @@ remove = \@Dict { metadata, dataIndices, data, size }, key -> when findIndexHelper metadata dataIndices data h2Key key probe 0 is Ok index -> - last = List.len data - 1 + last = Num.subWrap (List.len data) 1 dataIndex = listGetUnsafe dataIndices index if dataIndex == last then @@ -438,7 +438,7 @@ remove = \@Dict { metadata, dataIndices, data, size }, key -> metadata: List.set metadata index deletedSlot, dataIndices, data: List.dropLast data, - size: size - 1, + size: Num.subWrap size 1, } else swapAndUpdateDataIndex (@Dict { metadata, dataIndices, data, size }) index last @@ -461,7 +461,7 @@ remove = \@Dict { metadata, dataIndices, data, size }, key -> ## expect Dict.update (Dict.single "a" Bool.false) "a" alterValue == Dict.single "a" Bool.true ## expect Dict.update (Dict.single "a" Bool.true) "a" alterValue == Dict.empty {} ## ``` -update : Dict k v, k, ([Present v, Missing] -> [Present v, Missing]) -> Dict k v | k has Hash & Eq +update : Dict k v, k, ([Present v, Missing] -> [Present v, Missing]) -> Dict k v where k implements Hash & Eq update = \dict, key, alter -> # TODO: look into optimizing by merging substeps and reducing lookups. possibleValue = @@ -484,7 +484,7 @@ update = \dict, key, alter -> ## |> Dict.toList ## |> Bool.isEq [(1, "One"), (2, "Two"), (3, "Three"), (4, "Four")] ## ``` -toList : Dict k v -> List (k, v) | k has Hash & Eq +toList : Dict k v -> List (k, v) where k implements Hash & Eq toList = \@Dict { data } -> data @@ -499,7 +499,7 @@ toList = \@Dict { data } -> ## |> Dict.keys ## |> Bool.isEq [1,2,3,4] ## ``` -keys : Dict k v -> List k | k has Hash & Eq +keys : Dict k v -> List k where k implements Hash & Eq keys = \@Dict { data } -> List.map data (\(k, _) -> k) @@ -514,7 +514,7 @@ keys = \@Dict { data } -> ## |> Dict.values ## |> Bool.isEq ["One","Two","Three","Four"] ## ``` -values : Dict k v -> List v | k has Hash & Eq +values : Dict k v -> List v where k implements Hash & Eq values = \@Dict { data } -> List.map data (\(_, v) -> v) @@ -542,7 +542,7 @@ values = \@Dict { data } -> ## expect ## Dict.insertAll first second == expected ## ``` -insertAll : Dict k v, Dict k v -> Dict k v | k has Hash & Eq +insertAll : Dict k v, Dict k v -> Dict k v where k implements Hash & Eq insertAll = \xs, ys -> walk ys xs insert @@ -564,7 +564,7 @@ insertAll = \xs, ys -> ## ## expect Dict.keepShared first second == first ## ``` -keepShared : Dict k v, Dict k v -> Dict k v | k has Hash & Eq +keepShared : Dict k v, Dict k v -> Dict k v where k implements Hash & Eq keepShared = \xs, ys -> walk xs @@ -596,11 +596,11 @@ keepShared = \xs, ys -> ## ## expect Dict.removeAll first second == expected ## ``` -removeAll : Dict k v, Dict k v -> Dict k v | k has Hash & Eq +removeAll : Dict k v, Dict k v -> Dict k v where k implements Hash & Eq removeAll = \xs, ys -> walk ys xs (\state, k, _ -> remove state k) -swapAndUpdateDataIndex : Dict k v, Nat, Nat -> Dict k v | k has Hash & Eq +swapAndUpdateDataIndex : Dict k v, Nat, Nat -> Dict k v where k implements Hash & Eq swapAndUpdateDataIndex = \@Dict { metadata, dataIndices, data, size }, removedIndex, lastIndex -> (key, _) = listGetUnsafe data lastIndex hashKey = @@ -626,7 +626,7 @@ swapAndUpdateDataIndex = \@Dict { metadata, dataIndices, data, size }, removedIn # Update index of swaped element. dataIndices: List.set dataIndices index dataIndex, data: nextData, - size: size - 1, + size: Num.subWrap size 1, } Err NotFound -> @@ -664,7 +664,7 @@ nextEmptyOrDeletedHelper = \metadata, probe, offset -> # TODO: investigate if this needs to be split into more specific helper functions. # There is a chance that returning specific sub-info like the value would be faster. -findIndexHelper : List I8, List Nat, List (k, v), I8, k, Probe, Nat -> Result Nat [NotFound] | k has Hash & Eq +findIndexHelper : List I8, List Nat, List (k, v), I8, k, Probe, Nat -> Result Nat [NotFound] where k implements Hash & Eq findIndexHelper = \metadata, dataIndices, data, h2Key, key, probe, offset -> # For finding a value, we must search past all deleted element tombstones. index = Num.addWrap (mul8 probe.slotIndex) offset @@ -696,12 +696,12 @@ findIndexHelper = \metadata, dataIndices, data, h2Key, key, probe, offset -> # This is how we grow the container. # If we aren't to the load factor yet, just ignore this. # The container must have an updated size including any elements about to be inserted. -maybeRehash : Dict k v -> Dict k v | k has Hash & Eq +maybeRehash : Dict k v -> Dict k v where k implements Hash & Eq maybeRehash = \@Dict { metadata, dataIndices, data, size } -> cap = List.len dataIndices maxLoadCap = # This is 7/8 * capacity, which is the max load factor. - cap - Num.shiftRightZfBy cap 3 + Num.subWrap cap (Num.shiftRightZfBy cap 3) if size > maxLoadCap then rehash (@Dict { metadata, dataIndices, data, size }) @@ -709,7 +709,7 @@ maybeRehash = \@Dict { metadata, dataIndices, data, size } -> @Dict { metadata, dataIndices, data, size } # TODO: switch rehash to iterate data and eventually clear out tombstones as well. -rehash : Dict k v -> Dict k v | k has Hash & Eq +rehash : Dict k v -> Dict k v where k implements Hash & Eq rehash = \@Dict { metadata, dataIndices, data, size } -> newLen = 2 * List.len dataIndices newDict = @@ -722,7 +722,7 @@ rehash = \@Dict { metadata, dataIndices, data, size } -> rehashHelper newDict metadata dataIndices data 0 -rehashHelper : Dict k v, List I8, List Nat, List (k, v), Nat -> Dict k v | k has Hash & Eq +rehashHelper : Dict k v, List I8, List Nat, List (k, v), Nat -> Dict k v where k implements Hash & Eq rehashHelper = \dict, oldMetadata, oldDataIndices, oldData, index -> when List.get oldMetadata index is Ok md -> @@ -737,13 +737,13 @@ rehashHelper = \dict, oldMetadata, oldDataIndices, oldData, index -> # Empty or deleted data dict - rehashHelper nextDict oldMetadata oldDataIndices oldData (index + 1) + rehashHelper nextDict oldMetadata oldDataIndices oldData (Num.addWrap index 1) Err OutOfBounds -> # Walked entire list, complete now. dict -insertForRehash : Dict k v, k, Nat -> Dict k v | k has Hash & Eq +insertForRehash : Dict k v, k, Nat -> Dict k v where k implements Hash & Eq insertForRehash = \@Dict { metadata, dataIndices, data, size }, key, dataIndex -> hashKey = createLowLevelHasher PseudoRandSeed @@ -1010,7 +1010,7 @@ expect # TODO: wyhash is slow for large keys, use something like cityhash if the keys are too long. # TODO: Add a builtin to distinguish big endian systems and change loading orders. # TODO: Switch out Wymum on systems with slow 128bit multiplication. -LowLevelHasher := { originalSeed : U64, state : U64 } has [ +LowLevelHasher := { originalSeed : U64, state : U64 } implements [ Hasher { addBytes, addU8, diff --git a/crates/compiler/builtins/roc/Encode.roc b/crates/compiler/builtins/roc/Encode.roc index 2ac900e3e7..af8b0307c1 100644 --- a/crates/compiler/builtins/roc/Encode.roc +++ b/crates/compiler/builtins/roc/Encode.roc @@ -47,40 +47,40 @@ interface Encode Bool.{ Bool }, ] -Encoder fmt := List U8, fmt -> List U8 | fmt has EncoderFormatting +Encoder fmt := List U8, fmt -> List U8 where fmt implements EncoderFormatting -Encoding has - toEncoder : val -> Encoder fmt | val has Encoding, fmt has EncoderFormatting +Encoding implements + toEncoder : val -> Encoder fmt where val implements Encoding, fmt implements EncoderFormatting -EncoderFormatting has - u8 : U8 -> Encoder fmt | fmt has EncoderFormatting - u16 : U16 -> Encoder fmt | fmt has EncoderFormatting - u32 : U32 -> Encoder fmt | fmt has EncoderFormatting - u64 : U64 -> Encoder fmt | fmt has EncoderFormatting - u128 : U128 -> Encoder fmt | fmt has EncoderFormatting - i8 : I8 -> Encoder fmt | fmt has EncoderFormatting - i16 : I16 -> Encoder fmt | fmt has EncoderFormatting - i32 : I32 -> Encoder fmt | fmt has EncoderFormatting - i64 : I64 -> Encoder fmt | fmt has EncoderFormatting - i128 : I128 -> Encoder fmt | fmt has EncoderFormatting - f32 : F32 -> Encoder fmt | fmt has EncoderFormatting - f64 : F64 -> Encoder fmt | fmt has EncoderFormatting - dec : Dec -> Encoder fmt | fmt has EncoderFormatting - bool : Bool -> Encoder fmt | fmt has EncoderFormatting - string : Str -> Encoder fmt | fmt has EncoderFormatting - list : List elem, (elem -> Encoder fmt) -> Encoder fmt | fmt has EncoderFormatting - record : List { key : Str, value : Encoder fmt } -> Encoder fmt | fmt has EncoderFormatting - tuple : List (Encoder fmt) -> Encoder fmt | fmt has EncoderFormatting - tag : Str, List (Encoder fmt) -> Encoder fmt | fmt has EncoderFormatting +EncoderFormatting implements + u8 : U8 -> Encoder fmt where fmt implements EncoderFormatting + u16 : U16 -> Encoder fmt where fmt implements EncoderFormatting + u32 : U32 -> Encoder fmt where fmt implements EncoderFormatting + u64 : U64 -> Encoder fmt where fmt implements EncoderFormatting + u128 : U128 -> Encoder fmt where fmt implements EncoderFormatting + i8 : I8 -> Encoder fmt where fmt implements EncoderFormatting + i16 : I16 -> Encoder fmt where fmt implements EncoderFormatting + i32 : I32 -> Encoder fmt where fmt implements EncoderFormatting + i64 : I64 -> Encoder fmt where fmt implements EncoderFormatting + i128 : I128 -> Encoder fmt where fmt implements EncoderFormatting + f32 : F32 -> Encoder fmt where fmt implements EncoderFormatting + f64 : F64 -> Encoder fmt where fmt implements EncoderFormatting + dec : Dec -> Encoder fmt where fmt implements EncoderFormatting + bool : Bool -> Encoder fmt where fmt implements EncoderFormatting + string : Str -> Encoder fmt where fmt implements EncoderFormatting + list : List elem, (elem -> Encoder fmt) -> Encoder fmt where fmt implements EncoderFormatting + record : List { key : Str, value : Encoder fmt } -> Encoder fmt where fmt implements EncoderFormatting + tuple : List (Encoder fmt) -> Encoder fmt where fmt implements EncoderFormatting + tag : Str, List (Encoder fmt) -> Encoder fmt where fmt implements EncoderFormatting -custom : (List U8, fmt -> List U8) -> Encoder fmt | fmt has EncoderFormatting +custom : (List U8, fmt -> List U8) -> Encoder fmt where fmt implements EncoderFormatting custom = \encoder -> @Encoder encoder -appendWith : List U8, Encoder fmt, fmt -> List U8 | fmt has EncoderFormatting +appendWith : List U8, Encoder fmt, fmt -> List U8 where fmt implements EncoderFormatting appendWith = \lst, @Encoder doEncoding, fmt -> doEncoding lst fmt -append : List U8, val, fmt -> List U8 | val has Encoding, fmt has EncoderFormatting +append : List U8, val, fmt -> List U8 where val implements Encoding, fmt implements EncoderFormatting append = \lst, val, fmt -> appendWith lst (toEncoder val) fmt -toBytes : val, fmt -> List U8 | val has Encoding, fmt has EncoderFormatting +toBytes : val, fmt -> List U8 where val implements Encoding, fmt implements EncoderFormatting toBytes = \val, fmt -> appendWith [] (toEncoder val) fmt diff --git a/crates/compiler/builtins/roc/Hash.roc b/crates/compiler/builtins/roc/Hash.roc index ae70b23615..6a52054091 100644 --- a/crates/compiler/builtins/roc/Hash.roc +++ b/crates/compiler/builtins/roc/Hash.roc @@ -28,40 +28,40 @@ interface Hash Num.{ U8, U16, U32, U64, U128, I8, I16, I32, I64, I128, Nat, Dec }, ] -## A value that can hashed. -Hash has +## A value that can be hashed. +Hash implements ## Hashes a value into a [Hasher]. ## Note that [hash] does not produce a hash value itself; the hasher must be ## [complete]d in order to extract the hash value. - hash : hasher, a -> hasher | a has Hash, hasher has Hasher + hash : hasher, a -> hasher where a implements Hash, hasher implements Hasher ## Describes a hashing algorithm that is fed bytes and produces an integer hash. ## ## The [Hasher] ability describes general-purpose hashers. It only allows ## emission of 64-bit unsigned integer hashes. It is not suitable for ## cryptographically-secure hashing. -Hasher has +Hasher implements ## Adds a list of bytes to the hasher. - addBytes : a, List U8 -> a | a has Hasher + addBytes : a, List U8 -> a where a implements Hasher ## Adds a single U8 to the hasher. - addU8 : a, U8 -> a | a has Hasher + addU8 : a, U8 -> a where a implements Hasher ## Adds a single U16 to the hasher. - addU16 : a, U16 -> a | a has Hasher + addU16 : a, U16 -> a where a implements Hasher ## Adds a single U32 to the hasher. - addU32 : a, U32 -> a | a has Hasher + addU32 : a, U32 -> a where a implements Hasher ## Adds a single U64 to the hasher. - addU64 : a, U64 -> a | a has Hasher + addU64 : a, U64 -> a where a implements Hasher ## Adds a single U128 to the hasher. - addU128 : a, U128 -> a | a has Hasher + addU128 : a, U128 -> a where a implements Hasher ## Completes the hasher, extracting a hash value from its ## accumulated hash state. - complete : a -> U64 | a has Hasher + complete : a -> U64 where a implements Hasher ## Adds a string into a [Hasher] by hashing its UTF-8 bytes. hashStrBytes = \hasher, s -> @@ -73,33 +73,33 @@ hashList = \hasher, lst -> hash accumHasher elem ## Adds a single [Bool] to a hasher. -hashBool : a, Bool -> a | a has Hasher +hashBool : a, Bool -> a where a implements Hasher hashBool = \hasher, b -> asU8 = if b then 1 else 0 addU8 hasher asU8 ## Adds a single I8 to a hasher. -hashI8 : a, I8 -> a | a has Hasher +hashI8 : a, I8 -> a where a implements Hasher hashI8 = \hasher, n -> addU8 hasher (Num.toU8 n) ## Adds a single I16 to a hasher. -hashI16 : a, I16 -> a | a has Hasher +hashI16 : a, I16 -> a where a implements Hasher hashI16 = \hasher, n -> addU16 hasher (Num.toU16 n) ## Adds a single I32 to a hasher. -hashI32 : a, I32 -> a | a has Hasher +hashI32 : a, I32 -> a where a implements Hasher hashI32 = \hasher, n -> addU32 hasher (Num.toU32 n) ## Adds a single I64 to a hasher. -hashI64 : a, I64 -> a | a has Hasher +hashI64 : a, I64 -> a where a implements Hasher hashI64 = \hasher, n -> addU64 hasher (Num.toU64 n) ## Adds a single I128 to a hasher. -hashI128 : a, I128 -> a | a has Hasher +hashI128 : a, I128 -> a where a implements Hasher hashI128 = \hasher, n -> addU128 hasher (Num.toU128 n) ## Adds a single Nat to a hasher. -hashNat : a, Nat -> a | a has Hasher +hashNat : a, Nat -> a where a implements Hasher hashNat = \hasher, n -> isPlatform32bit = x : Nat @@ -117,7 +117,7 @@ hashNat = \hasher, n -> i128OfDec : Dec -> I128 ## Adds a single [Dec] to a hasher. -hashDec : a, Dec -> a | a has Hasher +hashDec : a, Dec -> a where a implements Hasher hashDec = \hasher, n -> hashI128 hasher (i128OfDec n) ## Adds a container of [Hash]able elements to a [Hasher] by hashing each element. diff --git a/crates/compiler/builtins/roc/Inspect.roc b/crates/compiler/builtins/roc/Inspect.roc new file mode 100644 index 0000000000..f4009f38fa --- /dev/null +++ b/crates/compiler/builtins/roc/Inspect.roc @@ -0,0 +1,94 @@ +interface Inspect + exposes [ + Inspect, + Inspector, + InspectFormatter, + ElemWalker, + KeyValWalker, + inspect, + init, + list, + set, + dict, + tag, + tuple, + record, + bool, + str, + opaque, + u8, + i8, + u16, + i16, + u32, + i32, + u64, + i64, + u128, + i128, + f32, + f64, + dec, + custom, + apply, + toInspector, + ] + imports [ + Bool.{ Bool }, + Num.{ U8, U16, U32, U64, U128, I8, I16, I32, I64, I128, F32, F64, Dec }, + List, + Str, + ] + +KeyValWalker state collection key val : collection, state, (state, key, val -> state) -> state +ElemWalker state collection elem : collection, state, (state, elem -> state) -> state + +InspectFormatter implements + init : {} -> f where f implements InspectFormatter + + tag : Str, List (Inspector f) -> Inspector f where f implements InspectFormatter + tuple : List (Inspector f) -> Inspector f where f implements InspectFormatter + record : List { key : Str, value : Inspector f } -> Inspector f where f implements InspectFormatter + bool : Bool -> Inspector f where f implements InspectFormatter + str : Str -> Inspector f where f implements InspectFormatter + + list : list, ElemWalker state list elem, (elem -> Inspector f) -> Inspector f where f implements InspectFormatter + set : set, ElemWalker state set elem, (elem -> Inspector f) -> Inspector f where f implements InspectFormatter + dict : dict, KeyValWalker state dict key value, (key -> Inspector f), (value -> Inspector f) -> Inspector f where f implements InspectFormatter + + # Note opaque is used for both opaque types and functions. + # The auto deriver for functions probably could put the function type. + # For regular opaque types, I think we can use the type name, though that may lead to some reflection related issues that still need to be discussed. + # As a simple baseline, it can just use the exact words `opaque` and `function` for now. + # In text, this would render as ``, ``, etc + opaque : Str -> Inspector f where f implements InspectFormatter + + u8 : U8 -> Inspector f where f implements InspectFormatter + i8 : I8 -> Inspector f where f implements InspectFormatter + u16 : U16 -> Inspector f where f implements InspectFormatter + i16 : I16 -> Inspector f where f implements InspectFormatter + u32 : U32 -> Inspector f where f implements InspectFormatter + i32 : I32 -> Inspector f where f implements InspectFormatter + u64 : U64 -> Inspector f where f implements InspectFormatter + i64 : I64 -> Inspector f where f implements InspectFormatter + u128 : U128 -> Inspector f where f implements InspectFormatter + i128 : I128 -> Inspector f where f implements InspectFormatter + f32 : F32 -> Inspector f where f implements InspectFormatter + f64 : F64 -> Inspector f where f implements InspectFormatter + dec : Dec -> Inspector f where f implements InspectFormatter + +Inspector f := f -> f where f implements InspectFormatter + +custom : (f -> f) -> Inspector f where f implements InspectFormatter +custom = @Inspector + +apply : Inspector f, f -> f where f implements InspectFormatter +apply = \@Inspector fn, fmt -> fn fmt + +Inspect implements + toInspector : val -> Inspector f where val implements Inspect, f implements InspectFormatter + +inspect : val -> f where val implements Inspect, f implements InspectFormatter +inspect = \val -> + (@Inspector valFn) = toInspector val + valFn (init {}) diff --git a/crates/compiler/builtins/roc/List.roc b/crates/compiler/builtins/roc/List.roc index 5cd38fed8b..4692e9a5a4 100644 --- a/crates/compiler/builtins/roc/List.roc +++ b/crates/compiler/builtins/roc/List.roc @@ -28,6 +28,7 @@ interface List map2, map3, product, + walkWithIndex, walkUntil, walkFrom, walkFromUntil, @@ -391,7 +392,7 @@ repeat = \value, count -> repeatHelp : a, Nat, List a -> List a repeatHelp = \value, count, accum -> if count > 0 then - repeatHelp value (count - 1) (List.appendUnsafe accum value) + repeatHelp value (Num.subWrap count 1) (List.appendUnsafe accum value) else accum @@ -405,7 +406,7 @@ reverse = \list -> reverseHelp = \list, left, right -> if left < right then - reverseHelp (List.swap list left right) (left + 1) (right - 1) + reverseHelp (List.swap list left right) (Num.addWrap left 1) (Num.subWrap right 1) else list @@ -418,11 +419,11 @@ reverseHelp = \list, left, right -> join : List (List a) -> List a join = \lists -> totalLength = - List.walk lists 0 (\state, list -> state + List.len list) + List.walk lists 0 (\state, list -> Num.addWrap state (List.len list)) - List.walk lists (List.withCapacity totalLength) (\state, list -> List.concat state list) + List.walk lists (List.withCapacity totalLength) \state, list -> List.concat state list -contains : List a, a -> Bool | a has Eq +contains : List a, a -> Bool where a implements Eq contains = \list, needle -> List.any list (\x -> x == needle) @@ -459,12 +460,33 @@ contains = \list, needle -> ## Note that in other languages, `walk` is sometimes called `reduce`, ## `fold`, `foldLeft`, or `foldl`. walk : List elem, state, (state, elem -> state) -> state -walk = \list, state, func -> - walkHelp : _, _ -> [Continue _, Break []] - walkHelp = \currentState, element -> Continue (func currentState element) +walk = \list, init, func -> + walkHelp list init func 0 (List.len list) - when List.iterate list state walkHelp is - Continue newState -> newState +## internal helper +walkHelp : List elem, s, (s, elem -> s), Nat, Nat -> s +walkHelp = \list, state, f, index, length -> + if index < length then + nextState = f state (List.getUnsafe list index) + + walkHelp list nextState f (Num.addWrap index 1) length + else + state + +## Like [walk], but at each step the function also receives the index of the current element. +walkWithIndex : List elem, state, (state, elem, Nat -> state) -> state +walkWithIndex = \list, init, func -> + walkWithIndexHelp list init func 0 (List.len list) + +## internal helper +walkWithIndexHelp : List elem, s, (s, elem, Nat -> s), Nat, Nat -> s +walkWithIndexHelp = \list, state, f, index, length -> + if index < length then + nextState = f state (List.getUnsafe list index) index + + walkWithIndexHelp list nextState f (Num.addWrap index 1) length + else + state ## Note that in other languages, `walkBackwards` is sometimes called `reduceRight`, ## `fold`, `foldRight`, or `foldr`. @@ -478,7 +500,7 @@ walkBackwardsHelp = \list, state, f, indexPlusOne -> if indexPlusOne == 0 then state else - index = indexPlusOne - 1 + index = Num.subWrap indexPlusOne 1 nextState = f state (getUnsafe list index) walkBackwardsHelp list nextState f index @@ -510,10 +532,10 @@ walkBackwardsUntil = \list, initial, func -> ## Walks to the end of the list from a specified starting index walkFrom : List elem, Nat, state, (state, elem -> state) -> state walkFrom = \list, index, state, func -> - walkHelp : _, _ -> [Continue _, Break []] - walkHelp = \currentState, element -> Continue (func currentState element) + step : _, _ -> [Continue _, Break []] + step = \currentState, element -> Continue (func currentState element) - when List.iterHelp list state walkHelp index (List.len list) is + when List.iterHelp list state step index (List.len list) is Continue new -> new ## A combination of [List.walkFrom] and [List.walkUntil] @@ -590,9 +612,9 @@ keepIfHelp : List a, (a -> Bool), Nat, Nat, Nat -> List a keepIfHelp = \list, predicate, kept, index, length -> if index < length then if predicate (List.getUnsafe list index) then - keepIfHelp (List.swap list kept index) predicate (kept + 1) (index + 1) length + keepIfHelp (List.swap list kept index) predicate (Num.addWrap kept 1) (Num.addWrap index 1) length else - keepIfHelp list predicate kept (index + 1) length + keepIfHelp list predicate kept (Num.addWrap index 1) length else List.takeFirst list kept @@ -619,7 +641,7 @@ countIf : List a, (a -> Bool) -> Nat countIf = \list, predicate -> walkState = \state, elem -> if predicate elem then - state + 1 + Num.addWrap state 1 else state @@ -712,7 +734,7 @@ mapWithIndexHelp = \src, dest, func, index, length -> mappedElem = func elem index newDest = List.appendUnsafe dest mappedElem - mapWithIndexHelp src newDest func (index + 1) length + mapWithIndexHelp src newDest func (Num.addWrap index 1) length else dest @@ -817,7 +839,7 @@ rangeLengthHelp = \accum, i, remaining, calcNext -> else when i is Ok val -> - rangeLengthHelp (List.appendUnsafe accum val) (calcNext val) (remaining - 1) calcNext + rangeLengthHelp (List.appendUnsafe accum val) (calcNext val) (Num.subWrap remaining 1) calcNext Err _ -> # We went past the end of the numeric range and there is no next. @@ -1036,7 +1058,7 @@ findFirstIndex = \list, matcher -> if matcher elem then Break index else - Continue (index + 1) + Continue (Num.addWrap index 1) when foundIndex is Break index -> Ok index @@ -1048,10 +1070,12 @@ findFirstIndex = \list, matcher -> findLastIndex : List elem, (elem -> Bool) -> Result Nat [NotFound] findLastIndex = \list, matches -> foundIndex = List.iterateBackwards list (List.len list) \prevIndex, elem -> + answer = Num.subWrap prevIndex 1 + if matches elem then - Break (prevIndex - 1) + Break answer else - Continue (prevIndex - 1) + Continue answer when foundIndex is Break index -> Ok index @@ -1104,7 +1128,7 @@ intersperse = \list, sep -> ## is considered to "start with" an empty list. ## ## If the first list is empty, this only returns `Bool.true` if the second list is empty. -startsWith : List elem, List elem -> Bool | elem has Eq +startsWith : List elem, List elem -> Bool where elem implements Eq startsWith = \list, prefix -> # TODO once we have seamless slices, verify that this wouldn't # have better performance with a function like List.compareSublists @@ -1116,7 +1140,7 @@ startsWith = \list, prefix -> ## is considered to "end with" an empty list. ## ## If the first list is empty, this only returns `Bool.true` if the second list is empty. -endsWith : List elem, List elem -> Bool | elem has Eq +endsWith : List elem, List elem -> Bool where elem implements Eq endsWith = \list, suffix -> # TODO once we have seamless slices, verify that this wouldn't # have better performance with a function like List.compareSublists @@ -1137,7 +1161,7 @@ split = \elements, userSplitIndex -> length = List.len elements splitIndex = if length > userSplitIndex then userSplitIndex else length before = List.sublist elements { start: 0, len: splitIndex } - others = List.sublist elements { start: splitIndex, len: length - splitIndex } + others = List.sublist elements { start: splitIndex, len: Num.subWrap length splitIndex } { before, others } @@ -1146,12 +1170,12 @@ split = \elements, userSplitIndex -> ## ``` ## List.splitFirst [Foo, Z, Bar, Z, Baz] Z == Ok { before: [Foo], after: [Bar, Z, Baz] } ## ``` -splitFirst : List elem, elem -> Result { before : List elem, after : List elem } [NotFound] | elem has Eq +splitFirst : List elem, elem -> Result { before : List elem, after : List elem } [NotFound] where elem implements Eq splitFirst = \list, delimiter -> when List.findFirstIndex list (\elem -> elem == delimiter) is Ok index -> before = List.sublist list { start: 0, len: index } - after = List.sublist list { start: index + 1, len: List.len list - index - 1 } + after = List.sublist list { start: Num.addWrap index 1, len: Num.subWrap (List.len list) index |> Num.subWrap 1 } Ok { before, after } @@ -1162,12 +1186,12 @@ splitFirst = \list, delimiter -> ## ``` ## List.splitLast [Foo, Z, Bar, Z, Baz] Z == Ok { before: [Foo, Z, Bar], after: [Baz] } ## ``` -splitLast : List elem, elem -> Result { before : List elem, after : List elem } [NotFound] | elem has Eq +splitLast : List elem, elem -> Result { before : List elem, after : List elem } [NotFound] where elem implements Eq splitLast = \list, delimiter -> when List.findLastIndex list (\elem -> elem == delimiter) is Ok index -> before = List.sublist list { start: 0, len: index } - after = List.sublist list { start: index + 1, len: List.len list - index - 1 } + after = List.sublist list { start: Num.addWrap index 1, len: Num.subWrap (List.len list) index |> Num.subWrap 1 } Ok { before, after } @@ -1202,7 +1226,7 @@ walkTryHelp : List elem, state, (state, elem -> Result state err), Nat, Nat -> R walkTryHelp = \list, state, f, index, length -> if index < length then when f state (List.getUnsafe list index) is - Ok nextState -> walkTryHelp list nextState f (index + 1) length + Ok nextState -> walkTryHelp list nextState f (Num.addWrap index 1) length Err b -> Err b else Ok state @@ -1217,7 +1241,7 @@ iterHelp : List elem, s, (s, elem -> [Continue s, Break b]), Nat, Nat -> [Contin iterHelp = \list, state, f, index, length -> if index < length then when f state (List.getUnsafe list index) is - Continue nextState -> iterHelp list nextState f (index + 1) length + Continue nextState -> iterHelp list nextState f (Num.addWrap index 1) length Break b -> Break b else Continue state @@ -1232,7 +1256,7 @@ iterateBackwards = \list, init, func -> iterBackwardsHelp : List elem, s, (s, elem -> [Continue s, Break b]), Nat -> [Continue s, Break b] iterBackwardsHelp = \list, state, f, prevIndex -> if prevIndex > 0 then - index = prevIndex - 1 + index = Num.subWrap prevIndex 1 when f state (List.getUnsafe list index) is Continue nextState -> iterBackwardsHelp list nextState f index diff --git a/crates/compiler/builtins/roc/Num.roc b/crates/compiler/builtins/roc/Num.roc index 24e265cd9e..2779518924 100644 --- a/crates/compiler/builtins/roc/Num.roc +++ b/crates/compiler/builtins/roc/Num.roc @@ -540,7 +540,7 @@ bytesToU16 = \bytes, index -> # we need at least 1 more byte offset = 1 - if index + offset < List.len bytes then + if Num.addSaturated index offset < List.len bytes then Ok (bytesToU16Lowlevel bytes index) else Err OutOfBounds @@ -550,7 +550,7 @@ bytesToU32 = \bytes, index -> # we need at least 3 more bytes offset = 3 - if index + offset < List.len bytes then + if Num.addSaturated index offset < List.len bytes then Ok (bytesToU32Lowlevel bytes index) else Err OutOfBounds @@ -560,7 +560,7 @@ bytesToU64 = \bytes, index -> # we need at least 7 more bytes offset = 7 - if index + offset < List.len bytes then + if Num.addSaturated index offset < List.len bytes then Ok (bytesToU64Lowlevel bytes index) else Err OutOfBounds @@ -570,7 +570,7 @@ bytesToU128 = \bytes, index -> # we need at least 15 more bytes offset = 15 - if index + offset < List.len bytes then + if Num.addSaturated index offset < List.len bytes then Ok (bytesToU128Lowlevel bytes index) else Err OutOfBounds diff --git a/crates/compiler/builtins/roc/Set.roc b/crates/compiler/builtins/roc/Set.roc index 7fc76c9807..19e6a82ebf 100644 --- a/crates/compiler/builtins/roc/Set.roc +++ b/crates/compiler/builtins/roc/Set.roc @@ -29,8 +29,8 @@ interface Set ## Provides a [set](https://en.wikipedia.org/wiki/Set_(abstract_data_type)) ## type which stores a collection of unique values, without any ordering -Set k := Dict.Dict k {} | k has Hash & Eq - has [ +Set k := Dict.Dict k {} where k implements Hash & Eq + implements [ Eq { isEq, }, @@ -39,7 +39,7 @@ Set k := Dict.Dict k {} | k has Hash & Eq }, ] -isEq : Set k, Set k -> Bool | k has Hash & Eq +isEq : Set k, Set k -> Bool where k implements Hash & Eq isEq = \xs, ys -> if len xs != len ys then Bool.false @@ -50,7 +50,7 @@ isEq = \xs, ys -> else Break Bool.false -hashSet : hasher, Set k -> hasher | k has Hash & Eq, hasher has Hasher +hashSet : hasher, Set k -> hasher where k implements Hash & Eq, hasher implements Hasher hashSet = \hasher, @Set inner -> Hash.hash hasher inner ## Creates a new empty `Set`. @@ -60,13 +60,13 @@ hashSet = \hasher, @Set inner -> Hash.hash hasher inner ## ## expect countValues == 0 ## ``` -empty : {} -> Set k | k has Hash & Eq +empty : {} -> Set * empty = \{} -> @Set (Dict.empty {}) ## Return a dictionary with space allocated for a number of entries. This ## may provide a performance optimization if you know how many entries will be ## inserted. -withCapacity : Nat -> Set k | k has Hash & Eq +withCapacity : Nat -> Set * withCapacity = \cap -> @Set (Dict.withCapacity cap) @@ -77,7 +77,7 @@ withCapacity = \cap -> ## ## expect countValues == 1 ## ``` -single : k -> Set k | k has Hash & Eq +single : k -> Set k where k implements Hash & Eq single = \key -> Dict.single key {} |> @Set @@ -93,7 +93,7 @@ single = \key -> ## ## expect countValues == 3 ## ``` -insert : Set k, k -> Set k | k has Hash & Eq +insert : Set k, k -> Set k where k implements Hash & Eq insert = \@Set dict, key -> Dict.insert dict key {} |> @Set @@ -178,7 +178,7 @@ expect ## expect has10 == Bool.false ## expect has20 == Bool.true ## ``` -remove : Set k, k -> Set k | k has Hash & Eq +remove : Set k, k -> Set k where k implements Hash & Eq remove = \@Set dict, key -> Dict.remove dict key |> @Set @@ -197,7 +197,7 @@ remove = \@Set dict, key -> ## expect hasApple == Bool.true ## expect hasBanana == Bool.false ## ``` -contains : Set k, k -> Bool | k has Hash & Eq +contains : Set k, k -> Bool where k implements Hash & Eq contains = \@Set dict, key -> Dict.contains dict key @@ -210,7 +210,7 @@ contains = \@Set dict, key -> ## ## expect Set.toList numbers == values ## ``` -toList : Set k -> List k | k has Hash & Eq +toList : Set k -> List k where k implements Hash & Eq toList = \@Set dict -> Dict.keys dict @@ -224,7 +224,7 @@ toList = \@Set dict -> ## ## expect Set.fromList [Pear, Apple, Banana] == values ## ``` -fromList : List k -> Set k | k has Hash & Eq +fromList : List k -> Set k where k implements Hash & Eq fromList = \list -> initial = @Set (Dict.withCapacity (List.len list)) @@ -240,7 +240,7 @@ fromList = \list -> ## ## expect Set.union set1 set2 == Set.fromList [Left, Right] ## ``` -union : Set k, Set k -> Set k | k has Hash & Eq +union : Set k, Set k -> Set k where k implements Hash & Eq union = \@Set dict1, @Set dict2 -> Dict.insertAll dict1 dict2 |> @Set @@ -253,7 +253,7 @@ union = \@Set dict1, @Set dict2 -> ## ## expect Set.intersection set1 set2 == Set.single Left ## ``` -intersection : Set k, Set k -> Set k | k has Hash & Eq +intersection : Set k, Set k -> Set k where k implements Hash & Eq intersection = \@Set dict1, @Set dict2 -> Dict.keepShared dict1 dict2 |> @Set @@ -267,7 +267,7 @@ intersection = \@Set dict1, @Set dict2 -> ## ## expect Set.difference first second == Set.fromList [Up, Down] ## ``` -difference : Set k, Set k -> Set k | k has Hash & Eq +difference : Set k, Set k -> Set k where k implements Hash & Eq difference = \@Set dict1, @Set dict2 -> Dict.removeAll dict1 dict2 |> @Set @@ -290,14 +290,14 @@ difference = \@Set dict1, @Set dict2 -> ## ## expect result == 2 ## ``` -walk : Set k, state, (state, k -> state) -> state | k has Hash & Eq +walk : Set k, state, (state, k -> state) -> state where k implements Hash & Eq walk = \@Set dict, state, step -> Dict.walk dict state (\s, k, _ -> step s k) ## Convert each value in the set to something new, by calling a conversion ## function on each of them which receives the old value. Then return a ## new set containing the converted values. -map : Set a, (a -> b) -> Set b | a has Hash & Eq, b has Hash & Eq +map : Set a, (a -> b) -> Set b where a implements Hash & Eq, b implements Hash & Eq map = \set, transform -> init = withCapacity (capacity set) @@ -309,7 +309,7 @@ map = \set, transform -> ## (using [Set.union]) into one set. ## ## You may know a similar function named `concatMap` in other languages. -joinMap : Set a, (a -> Set b) -> Set b | a has Hash & Eq, b has Hash & Eq +joinMap : Set a, (a -> Set b) -> Set b where a implements Hash & Eq, b implements Hash & Eq joinMap = \set, transform -> init = withCapacity (capacity set) # Might be a pessimization @@ -331,7 +331,7 @@ joinMap = \set, transform -> ## ## expect result == FoundTheAnswer ## ``` -walkUntil : Set k, state, (state, k -> [Continue state, Break state]) -> state | k has Hash & Eq +walkUntil : Set k, state, (state, k -> [Continue state, Break state]) -> state where k implements Hash & Eq walkUntil = \@Set dict, state, step -> Dict.walkUntil dict state (\s, k, _ -> step s k) diff --git a/crates/compiler/builtins/roc/Str.roc b/crates/compiler/builtins/roc/Str.roc index 3783b8edc7..f2a0da3f34 100644 --- a/crates/compiler/builtins/roc/Str.roc +++ b/crates/compiler/builtins/roc/Str.roc @@ -400,7 +400,7 @@ expect (Str.fromUtf8 [255]) |> Result.isErr ## ``` fromUtf8Range : List U8, { start : Nat, count : Nat } -> Result Str [BadUtf8 Utf8ByteProblem Nat, OutOfBounds] fromUtf8Range = \bytes, config -> - if config.start + config.count <= List.len bytes then + if Num.addSaturated config.start config.count <= List.len bytes then result = fromUtf8RangeLowlevel bytes config.start config.count if result.cIsOk then @@ -721,7 +721,7 @@ splitFirst = \haystack, needle -> remaining = Str.countUtf8Bytes haystack - Str.countUtf8Bytes needle - index before = Str.substringUnsafe haystack 0 index - after = Str.substringUnsafe haystack (index + Str.countUtf8Bytes needle) remaining + after = Str.substringUnsafe haystack (Num.addWrap index (Str.countUtf8Bytes needle)) remaining Ok { before, after } @@ -757,7 +757,7 @@ firstMatchHelp = \haystack, needle, index, lastPossible -> if matchesAt haystack index needle then Some index else - firstMatchHelp haystack needle (index + 1) lastPossible + firstMatchHelp haystack needle (Num.addWrap index 1) lastPossible else None @@ -775,7 +775,7 @@ splitLast = \haystack, needle -> remaining = Str.countUtf8Bytes haystack - Str.countUtf8Bytes needle - index before = Str.substringUnsafe haystack 0 index - after = Str.substringUnsafe haystack (index + Str.countUtf8Bytes needle) remaining + after = Str.substringUnsafe haystack (Num.addWrap index (Str.countUtf8Bytes needle)) remaining Ok { before, after } @@ -820,7 +820,7 @@ matchesAt : Str, Nat, Str -> Bool matchesAt = \haystack, haystackIndex, needle -> haystackLength = Str.countUtf8Bytes haystack needleLength = Str.countUtf8Bytes needle - endIndex = min (haystackIndex + needleLength) haystackLength + endIndex = min (Num.addSaturated haystackIndex needleLength) haystackLength matchesAtHelp { haystack, @@ -847,8 +847,8 @@ matchesAtHelp = \state -> doesRestMatch = matchesAtHelp { state & - haystackIndex: haystackIndex + 1, - needleIndex: needleIndex + 1, + haystackIndex: Num.addWrap haystackIndex 1, + needleIndex: Num.addWrap needleIndex 1, } doesThisMatch && doesRestMatch @@ -871,7 +871,7 @@ walkUtf8WithIndexHelp = \string, state, step, index, length -> byte = Str.getUnsafe string index newState = step state byte index - walkUtf8WithIndexHelp string newState step (index + 1) length + walkUtf8WithIndexHelp string newState step (Num.addWrap index 1) length else state @@ -892,7 +892,7 @@ walkUtf8Help = \str, state, step, index, length -> byte = Str.getUnsafe str index newState = step state byte - walkUtf8Help str newState step (index + 1) length + walkUtf8Help str newState step (Num.addWrap index 1) length else state @@ -942,7 +942,7 @@ walkScalarsHelp = \string, state, step, index, length -> { scalar, bytesParsed } = getScalarUnsafe string index newState = step state scalar - walkScalarsHelp string newState step (index + bytesParsed) length + walkScalarsHelp string newState step (Num.addWrap index bytesParsed) length else state @@ -970,7 +970,7 @@ walkScalarsUntilHelp = \string, state, step, index, length -> when step state scalar is Continue newState -> - walkScalarsUntilHelp string newState step (index + bytesParsed) length + walkScalarsUntilHelp string newState step (Num.addWrap index bytesParsed) length Break newState -> newState diff --git a/crates/compiler/builtins/roc/TotallyNotJson.roc b/crates/compiler/builtins/roc/TotallyNotJson.roc index 6df2a9cf7c..b4aecb5179 100644 --- a/crates/compiler/builtins/roc/TotallyNotJson.roc +++ b/crates/compiler/builtins/roc/TotallyNotJson.roc @@ -44,7 +44,7 @@ interface TotallyNotJson ## An opaque type with the `EncoderFormatting` and ## `DecoderFormatting` abilities. Json := { fieldNameMapping : FieldNameMapping } - has [ + implements [ EncoderFormatting { u8: encodeU8, u16: encodeU16, diff --git a/crates/compiler/builtins/src/roc.rs b/crates/compiler/builtins/src/roc.rs index 22c7dc9325..158c698de2 100644 --- a/crates/compiler/builtins/src/roc.rs +++ b/crates/compiler/builtins/src/roc.rs @@ -15,6 +15,7 @@ pub fn module_source(module_id: ModuleId) -> &'static str { ModuleId::ENCODE => ENCODE, ModuleId::DECODE => DECODE, ModuleId::HASH => HASH, + ModuleId::INSPECT => INSPECT, ModuleId::JSON => JSON, _ => internal_error!( "ModuleId {:?} is not part of the standard library", @@ -34,4 +35,5 @@ const BOOL: &str = include_str!("../roc/Bool.roc"); const ENCODE: &str = include_str!("../roc/Encode.roc"); const DECODE: &str = include_str!("../roc/Decode.roc"); const HASH: &str = include_str!("../roc/Hash.roc"); +const INSPECT: &str = include_str!("../roc/Inspect.roc"); const JSON: &str = include_str!("../roc/TotallyNotJson.roc"); diff --git a/crates/compiler/can/src/abilities.rs b/crates/compiler/can/src/abilities.rs index 893702add1..2d0ee1badb 100644 --- a/crates/compiler/can/src/abilities.rs +++ b/crates/compiler/can/src/abilities.rs @@ -80,7 +80,7 @@ impl AbilityMemberData { /// Solved lambda sets for an ability member specialization. For example, if we have /// -/// Default has default : {} -[[] + a:default:1]-> a | a has Default +/// Default implements default : {} -[[] + a:default:1]-> a where a implements Default /// /// A := {} /// default = \{} -[[closA]]-> @A {} @@ -144,7 +144,7 @@ pub struct IAbilitiesStore { /// /// For example, in the program /// - /// Hash has hash : a -> U64 | a has Hash + /// Hash implements hash : a -> U64 where a implements Hash /// /// Id := {} implements [Hash {hash: myHash}] /// myHash = \@Id n -> n @@ -155,7 +155,7 @@ pub struct IAbilitiesStore { /// Information about all members composing abilities. ability_members: MutMap>, - /// Maps a tuple (member, type) specifying that `type` has an implementation of an ability + /// Maps a tuple (member, type) specifying that `type` implements an ability /// member `member`, to how that implementation is defined. declared_implementations: MutMap, @@ -284,7 +284,7 @@ impl IAbilitiesStore { } /// Finds the implementation key for a symbol specializing the ability member, if it specializes any. - /// For example, suppose `hashId : Id -> U64` specializes `hash : a -> U64 | a has Hash`. + /// For example, suppose `hashId : Id -> U64` specializes `hash : a -> U64 where a implements Hash`. /// Calling this with `hashId` would retrieve (hash, hashId). pub fn impl_key(&self, specializing_symbol: Symbol) -> Option<&ImplKey> { self.specialization_to_root.get(&specializing_symbol) @@ -392,7 +392,7 @@ pub enum MarkError { impl IAbilitiesStore { /// Finds the symbol name and ability member definition for a symbol specializing the ability /// member, if it specializes any. - /// For example, suppose `hashId : Id -> U64` specializes `hash : a -> U64 | a has Hash`. + /// For example, suppose `hashId : Id -> U64` specializes `hash : a -> U64 where a implements Hash`. /// Calling this with `hashId` would retrieve the ability member data for `hash`, and what type /// `hashId` is specializing for. pub fn impl_key_and_def( @@ -414,7 +414,7 @@ impl IAbilitiesStore { } /// Returns an iterator over pairs ((ability member, type), implementation) specifying that - /// the give type has an implementation of an ability member. + /// the given type implements an ability member. pub fn iter_declared_implementations( &self, ) -> impl Iterator + '_ { diff --git a/crates/compiler/can/src/annotation.rs b/crates/compiler/can/src/annotation.rs index 6866cfa3ff..e3525f3e23 100644 --- a/crates/compiler/can/src/annotation.rs +++ b/crates/compiler/can/src/annotation.rs @@ -122,7 +122,7 @@ pub struct NamedVariable { pub first_seen: Region, } -/// A type variable bound to an ability, like "a has Hash". +/// A type variable bound to an ability, like "a implements Hash". #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct AbleVariable { pub variable: Variable, @@ -296,7 +296,7 @@ pub(crate) fn canonicalize_annotation( let (annotation, region) = match annotation { TypeAnnotation::Where(annotation, clauses) => { - // Add each "has" clause. The association of a variable to an ability will be saved on + // Add each "implements" clause. The association of a variable to an ability will be saved on // `introduced_variables`, which we'll process later. for clause in clauses.iter() { let opt_err = canonicalize_has_clause( @@ -847,29 +847,17 @@ fn can_annotation_help( let alias = scope.lookup_alias(symbol).unwrap(); local_aliases.insert(symbol, alias.clone()); - if vars.is_empty() && env.home == symbol.module_id() { - let actual_var = var_store.fresh(); - introduced_variables.insert_host_exposed_alias(symbol, actual_var); - Type::HostExposedAlias { - name: symbol, - type_arguments: vars, - lambda_set_variables: alias.lambda_set_variables.clone(), - actual: Box::new(alias.typ.clone()), - actual_var, - } - } else { - Type::Alias { - symbol, - type_arguments: vars.into_iter().map(OptAbleType::unbound).collect(), - lambda_set_variables: alias.lambda_set_variables.clone(), - infer_ext_in_output_types: alias - .infer_ext_in_output_variables - .iter() - .map(|v| Type::Variable(*v)) - .collect(), - actual: Box::new(alias.typ.clone()), - kind: alias.kind, - } + Type::Alias { + symbol, + type_arguments: vars.into_iter().map(OptAbleType::unbound).collect(), + lambda_set_variables: alias.lambda_set_variables.clone(), + infer_ext_in_output_types: alias + .infer_ext_in_output_variables + .iter() + .map(|v| Type::Variable(*v)) + .collect(), + actual: Box::new(alias.typ.clone()), + kind: alias.kind, } } @@ -1041,8 +1029,8 @@ fn can_annotation_help( Where(_annotation, clauses) => { debug_assert!(!clauses.is_empty()); - // Has clauses are allowed only on the top level of a signature, which we handle elsewhere. - env.problem(roc_problem::can::Problem::IllegalHasClause { + // Implements clauses are allowed only on the top level of a signature, which we handle elsewhere. + env.problem(roc_problem::can::Problem::IllegalImplementsClause { region: Region::across_all(clauses.iter().map(|clause| &clause.region)), }); @@ -1065,13 +1053,13 @@ fn canonicalize_has_clause( scope: &mut Scope, var_store: &mut VarStore, introduced_variables: &mut IntroducedVariables, - clause: &Loc>, + clause: &Loc>, pending_abilities_in_scope: &PendingAbilitiesInScope, references: &mut VecSet, ) -> Result<(), Type> { let Loc { region, - value: roc_parse::ast::HasClause { var, abilities }, + value: roc_parse::ast::ImplementsClause { var, abilities }, } = clause; let region = *region; @@ -1097,13 +1085,13 @@ fn canonicalize_has_clause( // or an ability that was imported from elsewhere && !scope.abilities_store.is_ability(symbol) { - env.problem(roc_problem::can::Problem::HasClauseIsNotAbility { region }); + env.problem(roc_problem::can::Problem::ImplementsClauseIsNotAbility { region }); return Err(Type::Error); } symbol } _ => { - env.problem(roc_problem::can::Problem::HasClauseIsNotAbility { region }); + env.problem(roc_problem::can::Problem::ImplementsClauseIsNotAbility { region }); return Err(Type::Error); } }; @@ -1112,7 +1100,7 @@ fn canonicalize_has_clause( let already_seen = can_abilities.insert(ability); if already_seen { - env.problem(roc_problem::can::Problem::DuplicateHasAbility { ability, region }); + env.problem(roc_problem::can::Problem::DuplicateImplementsAbility { ability, region }); } } diff --git a/crates/compiler/can/src/def.rs b/crates/compiler/can/src/def.rs index e8110c5ea4..2496689eb8 100644 --- a/crates/compiler/can/src/def.rs +++ b/crates/compiler/can/src/def.rs @@ -191,7 +191,7 @@ enum PendingTypeDef<'a> { name: Loc, vars: Vec>, ann: &'a Loc>, - derived: Option<&'a Loc>>, + derived: Option<&'a Loc>>, }, Ability { @@ -497,7 +497,7 @@ fn canonicalize_claimed_ability_impl<'a>( // // interface F imports [] exposes [] // - // Hello := {} has [Encoding.{ toEncoder }] + // Hello := {} implements [Encoding.{ toEncoder }] // // toEncoder = \@Hello {} -> ... // @@ -509,7 +509,7 @@ fn canonicalize_claimed_ability_impl<'a>( // // interface F imports [Encoding.{ toEncoder }] exposes [] // - // Hello := {} has [Encoding.{ toEncoder }] + // Hello := {} implements [Encoding.{ toEncoder }] // // toEncoder = \@Hello {} -> ... // @@ -527,9 +527,9 @@ fn canonicalize_claimed_ability_impl<'a>( // definition symbol, for example when the ability is defined in the same // module as an implementer: // - // Eq has eq : a, a -> U64 | a has Eq + // Eq implements eq : a, a -> U64 where a implements Eq // - // A := U8 has [Eq {eq}] + // A := U8 implements [Eq {eq}] // // So, do a final check that the implementation symbol is not resolved directly // to the member. @@ -689,7 +689,7 @@ fn canonicalize_opaque<'a>( name_str: &'a str, ann: &'a Loc>, vars: &[Loc], - has_abilities: Option<&'a Loc>>, + has_abilities: Option<&'a Loc>>, ) -> Result, ()> { let alias = canonicalize_alias( env, @@ -712,7 +712,7 @@ fn canonicalize_opaque<'a>( for has_ability in has_abilities.items { let region = has_ability.region; let (ability, opt_impls) = match has_ability.value.extract_spaces().item { - ast::HasAbility::HasAbility { ability, impls } => (ability, impls), + ast::ImplementsAbility::ImplementsAbility { ability, impls } => (ability, impls), _ => internal_error!("spaces not extracted"), }; @@ -766,8 +766,8 @@ fn canonicalize_opaque<'a>( // Did the user claim this implementation for a specialization of a different // type? e.g. // - // A has [Hash {hash: myHash}] - // B has [Hash {hash: myHash}] + // A implements [Hash {hash: myHash}] + // B implements [Hash {hash: myHash}] // // If so, that's an error and we drop the impl for this opaque type. let member_impl = match scope.abilities_store.impl_key(impl_symbol) { @@ -1198,7 +1198,7 @@ fn canonicalize_type_defs<'a>( Loc, Vec>, &'a Loc>, - Option<&'a Loc>>, + Option<&'a Loc>>, ), Ability(Loc, Vec>), } @@ -1404,7 +1404,7 @@ fn resolve_abilities( [] => { // There are no variables bound to the parent ability - then this member doesn't // need to be a part of the ability. - env.problem(Problem::AbilityMemberMissingHasClause { + env.problem(Problem::AbilityMemberMissingImplementsClause { member: member_sym, ability, region: member_name_region, @@ -1414,7 +1414,7 @@ fn resolve_abilities( } [..] => { // There is more than one variable bound to the member signature, so something like - // Eq has eq : a, b -> Bool | a has Eq, b has Eq + // Eq implements eq : a, b -> Bool where a implements Eq, b implements Eq // We have no way of telling what type implements a particular instance of Eq in // this case (a or b?), so disallow it. let span_has_clauses = Region::across_all( @@ -1427,7 +1427,7 @@ fn resolve_abilities( env.problem(Problem::AbilityMemberMultipleBoundVars { member: member_sym, ability, - span_has_clauses, + span_implements_clauses: span_has_clauses, bound_var_names, }); // Pretend the member isn't a part of the ability @@ -2558,7 +2558,7 @@ fn to_pending_alias_or_opaque<'a>( name: &'a Loc<&'a str>, vars: &'a [Loc>], ann: &'a Loc>, - opt_derived: Option<&'a Loc>>, + opt_derived: Option<&'a Loc>>, kind: AliasKind, ) -> PendingTypeDef<'a> { let region = Region::span_across(&name.region, &ann.region); @@ -2677,7 +2677,7 @@ fn to_pending_type_def<'a>( Ability { header: TypeHeader { name, vars }, members, - loc_has: _, + loc_implements: _, } => { let name = match scope .introduce_without_shadow_symbol(&Ident::from(name.value), name.region) diff --git a/crates/compiler/can/src/pattern.rs b/crates/compiler/can/src/pattern.rs index 2f61468fa2..e0cf6de1ff 100644 --- a/crates/compiler/can/src/pattern.rs +++ b/crates/compiler/can/src/pattern.rs @@ -76,7 +76,7 @@ pub enum Pattern { Underscore, /// An identifier that marks a specialization of an ability member. - /// For example, given an ability member definition `hash : a -> U64 | a has Hash`, + /// For example, given an ability member definition `hash : a -> U64 where a implements Hash`, /// there may be the specialization `hash : Bool -> U64`. In this case we generate a /// new symbol for the specialized "hash" identifier. AbilityMemberSpecialization { diff --git a/crates/compiler/can/src/scope.rs b/crates/compiler/can/src/scope.rs index 88a139a45d..b427f869a5 100644 --- a/crates/compiler/can/src/scope.rs +++ b/crates/compiler/can/src/scope.rs @@ -33,7 +33,7 @@ pub struct Scope { imports: Vec<(Ident, Symbol, Region)>, /// Shadows of an ability member, for example a local specialization of `eq` for the ability - /// member `Eq has eq : a, a -> Bool | a has Eq` gets a shadow symbol it can use for its + /// member `Eq implements eq : a, a -> Bool where a implements Eq` gets a shadow symbol it can use for its /// implementation. /// /// Only one shadow of an ability member is permitted per scope. diff --git a/crates/compiler/can/src/traverse.rs b/crates/compiler/can/src/traverse.rs index c22096ea72..cbd0c43938 100644 --- a/crates/compiler/can/src/traverse.rs +++ b/crates/compiler/can/src/traverse.rs @@ -674,7 +674,7 @@ pub enum FoundSymbol { Symbol(Symbol), } -/// Given an ability Foo has foo : ..., returns (T, foo1) if the symbol at the given region is a +/// Given an ability Foo implements foo : ..., returns (T, foo1) if the symbol at the given region is a /// symbol foo1 that specializes foo for T. Otherwise if the symbol is foo but the specialization /// is unknown, (Foo, foo) is returned. Otherwise [None] is returned. pub fn find_symbol_at( diff --git a/crates/compiler/derive/src/decoding.rs b/crates/compiler/derive/src/decoding.rs index 2ba0b8cff8..9f0b29c807 100644 --- a/crates/compiler/derive/src/decoding.rs +++ b/crates/compiler/derive/src/decoding.rs @@ -63,7 +63,7 @@ fn wrap_in_decode_custom_decode_with( // Decode.decodeWith bytes inner_decoder fmt : DecodeResult val let (decode_with_call, decode_with_result_var) = { - // Decode.decodeWith : List U8, Decoder val fmt, fmt -> DecodeResult val | fmt has DecoderFormatting + // Decode.decodeWith : List U8, Decoder val fmt, fmt -> DecodeResult val where fmt implements DecoderFormatting let decode_with_type = env.import_builtin_symbol_var(Symbol::DECODE_DECODE_WITH); // Decode.decodeWith : bytes, inner_decoder, fmt -> DecoderResult (List val) @@ -80,7 +80,7 @@ fn wrap_in_decode_custom_decode_with( )), ); - // List U8, Decoder val fmt, fmt -> DecodeResult val | fmt has DecoderFormatting + // List U8, Decoder val fmt, fmt -> DecodeResult val where fmt implements DecoderFormatting // ~ bytes, Decoder (List elem) fmt, fmt -> DecoderResult (List val) env.unify(decode_with_type, this_decode_with_fn_var); @@ -169,7 +169,7 @@ fn wrap_in_decode_custom_decode_with( // Decode.custom \bytes, fmt -> Decode.decodeWith bytes inner_decoder fmt let (decode_custom_call, decoder_var) = { - // (List U8, fmt -> DecodeResult val) -> Decoder val fmt | fmt has DecoderFormatting + // (List U8, fmt -> DecodeResult val) -> Decoder val fmt where fmt implements DecoderFormatting let decode_custom_type = env.import_builtin_symbol_var(Symbol::DECODE_CUSTOM); // (List U8, fmt -> DecodeResult (List elem)) -> Decoder (List elem) fmt @@ -185,7 +185,7 @@ fn wrap_in_decode_custom_decode_with( )), ); - // (List U8, fmt -> DecodeResult val) -> Decoder val fmt | fmt has DecoderFormatting + // (List U8, fmt -> DecodeResult val) -> Decoder val fmt where fmt implements DecoderFormatting // ~ (List U8, fmt -> DecodeResult (List elem)) -> Decoder (List elem) fmt env.unify(decode_custom_type, this_decode_custom_fn_var); diff --git a/crates/compiler/derive/src/decoding/list.rs b/crates/compiler/derive/src/decoding/list.rs index 53c89fd1bd..ed2cd66de8 100644 --- a/crates/compiler/derive/src/decoding/list.rs +++ b/crates/compiler/derive/src/decoding/list.rs @@ -15,7 +15,7 @@ use crate::util::Env; pub(crate) fn decoder(env: &mut Env<'_>, _def_symbol: Symbol) -> (Expr, Variable) { // Build // - // def_symbol : Decoder (List elem) fmt | elem has Decoding, fmt has DecoderFormatting + // def_symbol : Decoder (List elem) fmt where elem implements Decoding, fmt implements DecoderFormatting // def_symbol = Decode.custom \bytes, fmt -> Decode.decodeWith bytes (Decode.list Decode.decoder) fmt // // NB: reduction to `Decode.list Decode.decoder` is not possible to the HRR. @@ -27,10 +27,10 @@ pub(crate) fn decoder(env: &mut Env<'_>, _def_symbol: Symbol) -> (Expr, Variable // List elem let elem_var = env.subs.fresh_unnamed_flex_var(); - // Decode.decoder : Decoder elem fmt | elem has Decoding, fmt has EncoderFormatting + // Decode.decoder : Decoder elem fmt where elem implements Decoding, fmt implements EncoderFormatting let (elem_decoder, elem_decoder_var) = { // build `Decode.decoder : Decoder elem fmt` type - // Decoder val fmt | val has Decoding, fmt has EncoderFormatting + // Decoder val fmt where val implements Decoding, fmt implements EncoderFormatting let elem_decoder_var = env.import_builtin_symbol_var(Symbol::DECODE_DECODER); // set val ~ elem @@ -52,7 +52,7 @@ pub(crate) fn decoder(env: &mut Env<'_>, _def_symbol: Symbol) -> (Expr, Variable }; // Build `Decode.list Decode.decoder` type - // Decoder val fmt -[uls]-> Decoder (List val) fmt | fmt has DecoderFormatting + // Decoder val fmt -[uls]-> Decoder (List val) fmt where fmt implements DecoderFormatting let decode_list_fn_var = env.import_builtin_symbol_var(Symbol::DECODE_LIST); // Decoder elem fmt -a-> b @@ -68,7 +68,7 @@ pub(crate) fn decoder(env: &mut Env<'_>, _def_symbol: Symbol) -> (Expr, Variable )), ); - // Decoder val fmt -[uls]-> Decoder (List val) fmt | fmt has DecoderFormatting + // Decoder val fmt -[uls]-> Decoder (List val) fmt where fmt implements DecoderFormatting // ~ Decoder elem fmt -a -> b env.unify(decode_list_fn_var, this_decode_list_fn_var); diff --git a/crates/compiler/derive/src/decoding/record.rs b/crates/compiler/derive/src/decoding/record.rs index d62ffe2f90..adc0196002 100644 --- a/crates/compiler/derive/src/decoding/record.rs +++ b/crates/compiler/derive/src/decoding/record.rs @@ -27,7 +27,7 @@ use super::wrap_in_decode_custom_decode_with; /// we'd like to generate an impl like /// /// ```roc -/// decoder : Decoder {first: a, second: b} fmt | a has Decoding, b has Decoding, fmt has DecoderFormatting +/// decoder : Decoder {first: a, second: b} fmt where a implements Decoding, b implements Decoding, fmt implements DecoderFormatting /// decoder = /// initialState : {f0: Result a [NoField], f1: Result b [NoField]} /// initialState = {f0: Err NoField, f1: Err NoField} diff --git a/crates/compiler/derive/src/decoding/tuple.rs b/crates/compiler/derive/src/decoding/tuple.rs index b6ce201691..a327bdfded 100644 --- a/crates/compiler/derive/src/decoding/tuple.rs +++ b/crates/compiler/derive/src/decoding/tuple.rs @@ -28,7 +28,7 @@ use super::wrap_in_decode_custom_decode_with; /// we'd like to generate an impl like /// /// ```roc -/// decoder : Decoder (a, b) fmt | a has Decoding, b has Decoding, fmt has DecoderFormatting +/// decoder : Decoder (a, b) fmt where a implements Decoding, b implements Decoding, fmt implements DecoderFormatting /// decoder = /// initialState : {e0: Result a [NoElem], e1: Result b [NoElem]} /// initialState = {e0: Err NoElem, e1: Err NoElem} diff --git a/crates/compiler/derive/src/encoding.rs b/crates/compiler/derive/src/encoding.rs index 4073e960a9..ccade76936 100644 --- a/crates/compiler/derive/src/encoding.rs +++ b/crates/compiler/derive/src/encoding.rs @@ -121,7 +121,7 @@ fn to_encoder_list(env: &mut Env<'_>, fn_name: Symbol) -> (Expr, Variable) { ); // build `toEncoder elem` type - // val -[uls]-> Encoder fmt | fmt has EncoderFormatting + // val -[uls]-> Encoder fmt where fmt implements EncoderFormatting let to_encoder_fn_var = env.import_builtin_symbol_var(Symbol::ENCODE_TO_ENCODER); // elem -[clos]-> t1 @@ -136,11 +136,11 @@ fn to_encoder_list(env: &mut Env<'_>, fn_name: Symbol) -> (Expr, Variable) { )), ); - // val -[uls]-> Encoder fmt | fmt has EncoderFormatting + // val -[uls]-> Encoder fmt where fmt implements EncoderFormatting // ~ elem -[clos]-> t1 env.unify(to_encoder_fn_var, elem_to_encoder_fn_var); - // toEncoder : (typeof rcd.a) -[clos]-> Encoder fmt | fmt has EncoderFormatting + // toEncoder : (typeof rcd.a) -[clos]-> Encoder fmt where fmt implements EncoderFormatting let to_encoder_var = AbilityMember(Symbol::ENCODE_TO_ENCODER, None, elem_to_encoder_fn_var); let to_encoder_fn = Box::new(( to_encoder_fn_var, @@ -201,7 +201,7 @@ fn to_encoder_list(env: &mut Env<'_>, fn_name: Symbol) -> (Expr, Variable) { }); // build `Encode.list lst (\elem -> Encode.toEncoder elem)` type - // List e, (e -> Encoder fmt) -[uls]-> Encoder fmt | fmt has EncoderFormatting + // List e, (e -> Encoder fmt) -[uls]-> Encoder fmt where fmt implements EncoderFormatting let encode_list_fn_var = env.import_builtin_symbol_var(Symbol::ENCODE_LIST); // List elem, to_elem_encoder_fn_var -[clos]-> t1 @@ -218,11 +218,11 @@ fn to_encoder_list(env: &mut Env<'_>, fn_name: Symbol) -> (Expr, Variable) { )), ); - // List e, (e -> Encoder fmt) -[uls]-> Encoder fmt | fmt has EncoderFormatting + // List e, (e -> Encoder fmt) -[uls]-> Encoder fmt where fmt implements EncoderFormatting // ~ List elem, to_elem_encoder_fn_var -[clos]-> t1 env.unify(encode_list_fn_var, this_encode_list_fn_var); - // Encode.list : List elem, to_elem_encoder_fn_var -[clos]-> Encoder fmt | fmt has EncoderFormatting + // Encode.list : List elem, to_elem_encoder_fn_var -[clos]-> Encoder fmt where fmt implements EncoderFormatting let encode_list = AbilityMember(Symbol::ENCODE_LIST, None, this_encode_list_fn_var); let encode_list_fn = Box::new(( this_encode_list_fn_var, @@ -340,7 +340,7 @@ fn to_encoder_record( }; // build `toEncoder rcd.a` type - // val -[uls]-> Encoder fmt | fmt has EncoderFormatting + // val -[uls]-> Encoder fmt where fmt implements EncoderFormatting let to_encoder_fn_var = env.import_builtin_symbol_var(Symbol::ENCODE_TO_ENCODER); // (typeof rcd.a) -[clos]-> t1 @@ -355,11 +355,11 @@ fn to_encoder_record( )), ); - // val -[uls]-> Encoder fmt | fmt has EncoderFormatting + // val -[uls]-> Encoder fmt where fmt implements EncoderFormatting // ~ (typeof rcd.a) -[clos]-> t1 env.unify(to_encoder_fn_var, this_to_encoder_fn_var); - // toEncoder : (typeof rcd.a) -[clos]-> Encoder fmt | fmt has EncoderFormatting + // toEncoder : (typeof rcd.a) -[clos]-> Encoder fmt where fmt implements EncoderFormatting let to_encoder_var = AbilityMember(Symbol::ENCODE_TO_ENCODER, None, to_encoder_fn_var); let to_encoder_fn = Box::new(( to_encoder_fn_var, @@ -420,7 +420,7 @@ fn to_encoder_record( }; // build `Encode.record [ { key: .., value: ..}, .. ]` type - // List { key : Str, value : Encoder fmt } -[uls]-> Encoder fmt | fmt has EncoderFormatting + // List { key : Str, value : Encoder fmt } -[uls]-> Encoder fmt where fmt implements EncoderFormatting let encode_record_fn_var = env.import_builtin_symbol_var(Symbol::ENCODE_RECORD); // fields_list_var -[clos]-> t1 @@ -437,11 +437,11 @@ fn to_encoder_record( )), ); - // List { key : Str, value : Encoder fmt } -[uls]-> Encoder fmt | fmt has EncoderFormatting + // List { key : Str, value : Encoder fmt } -[uls]-> Encoder fmt where fmt implements EncoderFormatting // ~ fields_list_var -[clos]-> t1 env.unify(encode_record_fn_var, this_encode_record_fn_var); - // Encode.record : fields_list_var -[clos]-> Encoder fmt | fmt has EncoderFormatting + // Encode.record : fields_list_var -[clos]-> Encoder fmt where fmt implements EncoderFormatting let encode_record_var = AbilityMember(Symbol::ENCODE_RECORD, None, encode_record_fn_var); let encode_record_fn = Box::new(( encode_record_fn_var, @@ -543,7 +543,7 @@ fn to_encoder_tuple( }; // build `toEncoder tup.0` type - // val -[uls]-> Encoder fmt | fmt has EncoderFormatting + // val -[uls]-> Encoder fmt where fmt implements EncoderFormatting let to_encoder_fn_var = env.import_builtin_symbol_var(Symbol::ENCODE_TO_ENCODER); // (typeof tup.0) -[clos]-> t1 @@ -558,11 +558,11 @@ fn to_encoder_tuple( )), ); - // val -[uls]-> Encoder fmt | fmt has EncoderFormatting + // val -[uls]-> Encoder fmt where fmt implements EncoderFormatting // ~ (typeof tup.0) -[clos]-> t1 env.unify(to_encoder_fn_var, this_to_encoder_fn_var); - // toEncoder : (typeof tup.0) -[clos]-> Encoder fmt | fmt has EncoderFormatting + // toEncoder : (typeof tup.0) -[clos]-> Encoder fmt where fmt implements EncoderFormatting let to_encoder_var = AbilityMember(Symbol::ENCODE_TO_ENCODER, None, to_encoder_fn_var); let to_encoder_fn = Box::new(( to_encoder_fn_var, @@ -603,7 +603,7 @@ fn to_encoder_tuple( }; // build `Encode.tuple [ toEncoder tup.0, toEncoder tup.1 ]` type - // List (Encoder fmt) -[uls]-> Encoder fmt | fmt has EncoderFormatting + // List (Encoder fmt) -[uls]-> Encoder fmt where fmt implements EncoderFormatting let encode_tuple_fn_var = env.import_builtin_symbol_var(Symbol::ENCODE_TUPLE); // elem_encoders_list_var -[clos]-> t1 @@ -620,11 +620,11 @@ fn to_encoder_tuple( )), ); - // List (Encoder fmt) -[uls]-> Encoder fmt | fmt has EncoderFormatting + // List (Encoder fmt) -[uls]-> Encoder fmt where fmt implements EncoderFormatting // ~ elem_encoders_list_var -[clos]-> t1 env.unify(encode_tuple_fn_var, this_encode_tuple_fn_var); - // Encode.tuple : elem_encoders_list_var -[clos]-> Encoder fmt | fmt has EncoderFormatting + // Encode.tuple : elem_encoders_list_var -[clos]-> Encoder fmt where fmt implements EncoderFormatting let encode_tuple_var = AbilityMember(Symbol::ENCODE_TUPLE, None, encode_tuple_fn_var); let encode_tuple_fn = Box::new(( encode_tuple_fn_var, @@ -741,7 +741,7 @@ fn to_encoder_tag_union( .zip(payload_vars.iter()) .map(|(&sym, &sym_var)| { // build `toEncoder v1` type - // expected: val -[uls]-> Encoder fmt | fmt has EncoderFormatting + // expected: val -[uls]-> Encoder fmt where fmt implements EncoderFormatting let to_encoder_fn_var = env.import_builtin_symbol_var(Symbol::ENCODE_TO_ENCODER); @@ -759,11 +759,11 @@ fn to_encoder_tag_union( )), ); - // val -[uls]-> Encoder fmt | fmt has EncoderFormatting + // val -[uls]-> Encoder fmt where fmt implements EncoderFormatting // ~ t1 -[clos]-> t' env.unify(to_encoder_fn_var, this_to_encoder_fn_var); - // toEncoder : t1 -[clos]-> Encoder fmt | fmt has EncoderFormatting + // toEncoder : t1 -[clos]-> Encoder fmt where fmt implements EncoderFormatting let to_encoder_var = AbilityMember(Symbol::ENCODE_TO_ENCODER, None, this_to_encoder_fn_var); let to_encoder_fn = Box::new(( @@ -802,7 +802,7 @@ fn to_encoder_tag_union( }; // build `Encode.tag "A" [ ... ]` type - // expected: Str, List (Encoder fmt) -[uls]-> Encoder fmt | fmt has EncoderFormatting + // expected: Str, List (Encoder fmt) -[uls]-> Encoder fmt where fmt implements EncoderFormatting let encode_tag_fn_var = env.import_builtin_symbol_var(Symbol::ENCODE_TAG); // wanted: Str, List whole_encoders_var -[clos]-> t' @@ -821,11 +821,11 @@ fn to_encoder_tag_union( )), ); - // Str, List (Encoder fmt) -[uls]-> Encoder fmt | fmt has EncoderFormatting + // Str, List (Encoder fmt) -[uls]-> Encoder fmt where fmt implements EncoderFormatting // ~ Str, List whole_encoders_var -[clos]-> t' env.unify(encode_tag_fn_var, this_encode_tag_fn_var); - // Encode.tag : Str, List whole_encoders_var -[clos]-> Encoder fmt | fmt has EncoderFormatting + // Encode.tag : Str, List whole_encoders_var -[clos]-> Encoder fmt where fmt implements EncoderFormatting let encode_tag_var = AbilityMember(Symbol::ENCODE_TAG, None, this_encode_tag_fn_var); let encode_tag_fn = Box::new(( this_encode_tag_fn_var, @@ -954,15 +954,15 @@ fn wrap_in_encode_custom( let bytes_sym = env.new_symbol("bytes"); let bytes_var = Variable::LIST_U8; - // fmt: fmt | fmt has EncoderFormatting + // fmt: fmt where fmt implements EncoderFormatting let fmt_sym = env.new_symbol("fmt"); let fmt_var = env.subs.fresh_unnamed_flex_var(); // build `Encode.appendWith bytes encoder fmt` type - // expected: Encode.appendWith : List U8, Encoder fmt, fmt -[appendWith]-> List U8 | fmt has EncoderFormatting + // expected: Encode.appendWith : List U8, Encoder fmt, fmt -[appendWith]-> List U8 where fmt implements EncoderFormatting let append_with_fn_var = env.import_builtin_symbol_var(Symbol::ENCODE_APPEND_WITH); - // wanted: Encode.appendWith : List U8, encoder_var, fmt -[clos]-> List U8 | fmt has EncoderFormatting + // wanted: Encode.appendWith : List U8, encoder_var, fmt -[clos]-> List U8 where fmt implements EncoderFormatting let this_append_with_args_var_slice = VariableSubsSlice::insert_into_subs(env.subs, [Variable::LIST_U8, encoder_var, fmt_var]); let this_append_with_clos_var = env.subs.fresh_unnamed_flex_var(); // -[clos]-> @@ -975,11 +975,11 @@ fn wrap_in_encode_custom( )), ); - // List U8, Encoder fmt, fmt -[appendWith]-> List U8 | fmt has EncoderFormatting - // ~ List U8, encoder_var, fmt -[clos]-> List U8 | fmt has EncoderFormatting + // List U8, Encoder fmt, fmt -[appendWith]-> List U8 where fmt implements EncoderFormatting + // ~ List U8, encoder_var, fmt -[clos]-> List U8 where fmt implements EncoderFormatting env.unify(append_with_fn_var, this_append_with_fn_var); - // Encode.appendWith : List U8, encoder_var, fmt -[appendWith]-> List U8 | fmt has EncoderFormatting + // Encode.appendWith : List U8, encoder_var, fmt -[appendWith]-> List U8 where fmt implements EncoderFormatting let append_with_fn = Box::new(( this_append_with_fn_var, Loc::at_zero(Var(Symbol::ENCODE_APPEND_WITH, this_append_with_fn_var)), @@ -1050,7 +1050,7 @@ fn wrap_in_encode_custom( // Build // Encode.custom \bytes, fmt -> Encode.appendWith bytes encoder fmt // - // expected: Encode.custom : (List U8, fmt -> List U8) -> Encoder fmt | fmt has EncoderFormatting + // expected: Encode.custom : (List U8, fmt -> List U8) -> Encoder fmt where fmt implements EncoderFormatting let custom_fn_var = env.import_builtin_symbol_var(Symbol::ENCODE_CUSTOM); // wanted: Encode.custom : fn_var -[clos]-> t' @@ -1066,11 +1066,11 @@ fn wrap_in_encode_custom( )), ); - // (List U8, fmt -> List U8) -[..]-> Encoder fmt | fmt has EncoderFormatting + // (List U8, fmt -> List U8) -[..]-> Encoder fmt where fmt implements EncoderFormatting // ~ fn_var -[clos]-> t' env.unify(custom_fn_var, this_custom_fn_var); - // Encode.custom : (List U8, fmt -> List U8) -> Encoder fmt | fmt has EncoderFormatting + // Encode.custom : (List U8, fmt -> List U8) -> Encoder fmt where fmt implements EncoderFormatting let custom_fn = Box::new(( this_custom_fn_var, Loc::at_zero(Var(Symbol::ENCODE_CUSTOM, this_custom_fn_var)), diff --git a/crates/compiler/derive/src/hash.rs b/crates/compiler/derive/src/hash.rs index a960fdf0c2..f890f787b1 100644 --- a/crates/compiler/derive/src/hash.rs +++ b/crates/compiler/derive/src/hash.rs @@ -75,7 +75,7 @@ fn hash_record(env: &mut Env<'_>, fn_name: Symbol, fields: Vec) -> (V // Now, a hasher for this record is // - // hash_rcd : hasher, { f1: t1, ..., fn: tn } -> hasher | hasher has Hasher + // hash_rcd : hasher, { f1: t1, ..., fn: tn } -> hasher where hasher implements Hasher // hash_rcd = \hasher, rcd -> // Hash.hash ( // Hash.hash @@ -144,7 +144,7 @@ fn hash_tuple(env: &mut Env<'_>, fn_name: Symbol, arity: u32) -> (Variable, Expr // Now, a hasher for this tuple is // - // hash_tup : hasher, (t1, ..., tn) -> hasher | hasher has Hasher + // hash_tup : hasher, (t1, ..., tn) -> hasher where hasher implements Hasher // hash_tup = \hasher, tup -> // Hash.hash ( // Hash.hash @@ -227,7 +227,7 @@ fn hash_tag_union( // Now, a hasher for this tag union is // - // hash_union : hasher, [ A t11 .. t1n, ..., Q tq1 .. tqm ] -> hasher | hasher has Hasher + // hash_union : hasher, [ A t11 .. t1n, ..., Q tq1 .. tqm ] -> hasher where hasher implements Hasher // hash_union = \hasher, union -> // when union is // A x11 .. x1n -> Hash.hash (... (Hash.hash (Hash.uN hasher 0) x11) ...) x1n @@ -393,7 +393,7 @@ fn hash_newtype_tag_union( // Now, a hasher for this tag union is // - // hash_union : hasher, [ A t1 .. tn ] -> hasher | hasher has Hasher + // hash_union : hasher, [ A t1 .. tn ] -> hasher where hasher implements Hasher // hash_union = \hasher, A x1 .. xn -> // Hash.hash (... (Hash.hash discrHasher x1) ...) xn let hasher_sym = env.new_symbol("hasher"); @@ -462,7 +462,7 @@ fn call_hash_ability_member( // build `member ...` function type. `member` here is `Hash.hash` or `Hash.addU16`. // - // hasher, val -[uls]-> hasher | hasher has Hasher, val has Hash + // hasher, val -[uls]-> hasher where hasher implements Hasher, val implements Hash let exposed_hash_fn_var = env.import_builtin_symbol_var(member); // (typeof body), (typeof field) -[clos]-> hasher_result @@ -479,11 +479,11 @@ fn call_hash_ability_member( )), ); - // hasher, val -[uls]-> hasher | hasher has Hasher, val has Hash + // hasher, val -[uls]-> hasher where hasher implements Hasher, val implements Hash // ~ (typeof body), (typeof field) -[clos]-> hasher_result env.unify(exposed_hash_fn_var, this_hash_fn_var); - // Hash.hash : hasher, (typeof field) -[clos]-> hasher | hasher has Hasher, (typeof field) has Hash + // Hash.hash : hasher, (typeof field) -[clos]-> hasher where hasher implements Hasher, (typeof field) implements Hash let hash_fn_head = Expr::AbilityMember(member, None, this_hash_fn_var); let hash_fn_data = Box::new(( this_hash_fn_var, diff --git a/crates/compiler/derive/src/util.rs b/crates/compiler/derive/src/util.rs index 26d5d2085a..14e3d9518e 100644 --- a/crates/compiler/derive/src/util.rs +++ b/crates/compiler/derive/src/util.rs @@ -146,7 +146,7 @@ impl Env<'_> { }) .collect(); - // Since we're doing `{foo} ~ a | a has Encoding`, we may see "lambda sets to + // Since we're doing `{foo} ~ a where a implements Encoding`, we may see "lambda sets to // specialize" for e.g. `{foo}:toEncoder:1`, but these are actually just the // specialization lambda sets, so we don't need to do any extra work! // diff --git a/crates/compiler/fmt/src/annotation.rs b/crates/compiler/fmt/src/annotation.rs index 8f7614af34..56762d9c31 100644 --- a/crates/compiler/fmt/src/annotation.rs +++ b/crates/compiler/fmt/src/annotation.rs @@ -4,8 +4,8 @@ use crate::{ Buf, }; use roc_parse::ast::{ - AssignedField, Collection, Expr, ExtractSpaces, HasAbilities, HasAbility, HasClause, HasImpls, - RecordBuilderField, Tag, TypeAnnotation, TypeHeader, + AbilityImpls, AssignedField, Collection, Expr, ExtractSpaces, ImplementsAbilities, + ImplementsAbility, ImplementsClause, RecordBuilderField, Tag, TypeAnnotation, TypeHeader, }; use roc_parse::ident::UppercaseIdent; use roc_region::all::Loc; @@ -350,16 +350,23 @@ impl<'a> Formattable for TypeAnnotation<'a> { } } - Where(annot, has_clauses) => { + Where(annot, implements_clauses) => { annot.format_with_options(buf, parens, newlines, indent); - if has_clauses.iter().any(|has| has.is_multiline()) { + if implements_clauses + .iter() + .any(|implements| implements.is_multiline()) + { buf.newline(); buf.indent(indent); } else { buf.spaces(1); } - for (i, has) in has_clauses.iter().enumerate() { - buf.push(if i == 0 { '|' } else { ',' }); + for (i, has) in implements_clauses.iter().enumerate() { + buf.push_str(if i == 0 { + roc_parse::keyword::WHERE + } else { + "," + }); buf.spaces(1); has.format_with_options(buf, parens, newlines, indent); } @@ -645,16 +652,16 @@ impl<'a> Formattable for Tag<'a> { } } -impl<'a> Formattable for HasClause<'a> { +impl<'a> Formattable for ImplementsClause<'a> { fn is_multiline(&self) -> bool { - // No, always put abilities in a "has" clause on one line + // No, always put abilities in an "implements" clause on one line false } fn format_with_options(&self, buf: &mut Buf, parens: Parens, newlines: Newlines, indent: u16) { buf.push_str(self.var.value.extract_spaces().item); buf.spaces(1); - buf.push_str("has"); + buf.push_str(roc_parse::keyword::IMPLEMENTS); buf.spaces(1); for (i, ab) in self.abilities.iter().enumerate() { @@ -668,30 +675,30 @@ impl<'a> Formattable for HasClause<'a> { } } -impl<'a> Formattable for HasImpls<'a> { +impl<'a> Formattable for AbilityImpls<'a> { fn is_multiline(&self) -> bool { match self { - HasImpls::SpaceBefore(_, _) | HasImpls::SpaceAfter(_, _) => true, - HasImpls::HasImpls(impls) => is_collection_multiline(impls), + AbilityImpls::SpaceBefore(_, _) | AbilityImpls::SpaceAfter(_, _) => true, + AbilityImpls::AbilityImpls(impls) => is_collection_multiline(impls), } } fn format_with_options(&self, buf: &mut Buf, parens: Parens, newlines: Newlines, indent: u16) { match self { - HasImpls::HasImpls(impls) => { + AbilityImpls::AbilityImpls(impls) => { if newlines == Newlines::Yes { buf.newline(); buf.indent(indent); } fmt_collection(buf, indent, Braces::Curly, *impls, Newlines::No); } - HasImpls::SpaceBefore(impls, spaces) => { + AbilityImpls::SpaceBefore(impls, spaces) => { buf.newline(); buf.indent(indent); fmt_comments_only(buf, spaces.iter(), NewlineAt::Bottom, indent); impls.format_with_options(buf, parens, Newlines::No, indent); } - HasImpls::SpaceAfter(impls, spaces) => { + AbilityImpls::SpaceAfter(impls, spaces) => { impls.format_with_options(buf, parens, newlines, indent); fmt_comments_only(buf, spaces.iter(), NewlineAt::Bottom, indent); } @@ -699,11 +706,11 @@ impl<'a> Formattable for HasImpls<'a> { } } -impl<'a> Formattable for HasAbility<'a> { +impl<'a> Formattable for ImplementsAbility<'a> { fn is_multiline(&self) -> bool { match self { - HasAbility::SpaceAfter(..) | HasAbility::SpaceBefore(..) => true, - HasAbility::HasAbility { ability, impls } => { + ImplementsAbility::SpaceAfter(..) | ImplementsAbility::SpaceBefore(..) => true, + ImplementsAbility::ImplementsAbility { ability, impls } => { ability.is_multiline() || impls.map(|i| i.is_multiline()).unwrap_or(false) } } @@ -711,7 +718,7 @@ impl<'a> Formattable for HasAbility<'a> { fn format_with_options(&self, buf: &mut Buf, parens: Parens, newlines: Newlines, indent: u16) { match self { - HasAbility::HasAbility { ability, impls } => { + ImplementsAbility::ImplementsAbility { ability, impls } => { if newlines == Newlines::Yes { buf.newline(); buf.indent(indent); @@ -722,13 +729,13 @@ impl<'a> Formattable for HasAbility<'a> { impls.format_with_options(buf, parens, newlines, indent); } } - HasAbility::SpaceBefore(ab, spaces) => { + ImplementsAbility::SpaceBefore(ab, spaces) => { buf.newline(); buf.indent(indent); fmt_comments_only(buf, spaces.iter(), NewlineAt::Bottom, indent); ab.format_with_options(buf, parens, Newlines::No, indent) } - HasAbility::SpaceAfter(ab, spaces) => { + ImplementsAbility::SpaceAfter(ab, spaces) => { ab.format_with_options(buf, parens, newlines, indent); fmt_comments_only(buf, spaces.iter(), NewlineAt::Bottom, indent); } @@ -736,32 +743,34 @@ impl<'a> Formattable for HasAbility<'a> { } } -impl<'a> Formattable for HasAbilities<'a> { +impl<'a> Formattable for ImplementsAbilities<'a> { fn is_multiline(&self) -> bool { match self { - HasAbilities::SpaceAfter(..) | HasAbilities::SpaceBefore(..) => true, - HasAbilities::Has(has_abilities) => is_collection_multiline(has_abilities), + ImplementsAbilities::SpaceAfter(..) | ImplementsAbilities::SpaceBefore(..) => true, + ImplementsAbilities::Implements(has_abilities) => { + is_collection_multiline(has_abilities) + } } } fn format_with_options(&self, buf: &mut Buf, parens: Parens, newlines: Newlines, indent: u16) { match self { - HasAbilities::Has(has_abilities) => { + ImplementsAbilities::Implements(has_abilities) => { if newlines == Newlines::Yes { buf.newline(); buf.indent(indent); } - buf.push_str("has"); + buf.push_str(roc_parse::keyword::IMPLEMENTS); buf.spaces(1); fmt_collection(buf, indent, Braces::Square, *has_abilities, Newlines::No); } - HasAbilities::SpaceBefore(has_abilities, spaces) => { + ImplementsAbilities::SpaceBefore(has_abilities, spaces) => { buf.newline(); buf.indent(indent); fmt_comments_only(buf, spaces.iter(), NewlineAt::Bottom, indent); has_abilities.format_with_options(buf, parens, Newlines::No, indent) } - HasAbilities::SpaceAfter(has_abilities, spaces) => { + ImplementsAbilities::SpaceAfter(has_abilities, spaces) => { has_abilities.format_with_options(buf, parens, newlines, indent); fmt_comments_only(buf, spaces.iter(), NewlineAt::Bottom, indent); } diff --git a/crates/compiler/fmt/src/def.rs b/crates/compiler/fmt/src/def.rs index 997edb8a37..456ff34b34 100644 --- a/crates/compiler/fmt/src/def.rs +++ b/crates/compiler/fmt/src/def.rs @@ -123,7 +123,7 @@ impl<'a> Formattable for TypeDef<'a> { } Ability { header: TypeHeader { name, vars }, - loc_has: _, + loc_implements: _, members, } => { buf.indent(indent); @@ -133,8 +133,8 @@ impl<'a> Formattable for TypeDef<'a> { fmt_pattern(buf, &var.value, indent, Parens::NotNeeded); buf.indent(indent); } - - buf.push_str(" has"); + buf.spaces(1); + buf.push_str(roc_parse::keyword::IMPLEMENTS); if !self.is_multiline() { debug_assert_eq!(members.len(), 1); diff --git a/crates/compiler/fmt/src/spaces.rs b/crates/compiler/fmt/src/spaces.rs index 84d8c36531..4264b208d5 100644 --- a/crates/compiler/fmt/src/spaces.rs +++ b/crates/compiler/fmt/src/spaces.rs @@ -3,10 +3,10 @@ use bumpalo::Bump; use roc_module::called_via::{BinOp, UnaryOp}; use roc_parse::{ ast::{ - AbilityMember, AssignedField, Collection, CommentOrNewline, Defs, Expr, Has, HasAbilities, - HasAbility, HasClause, HasImpls, Header, Module, Pattern, RecordBuilderField, Spaced, - Spaces, StrLiteral, StrSegment, Tag, TypeAnnotation, TypeDef, TypeHeader, ValueDef, - WhenBranch, + AbilityImpls, AbilityMember, AssignedField, Collection, CommentOrNewline, Defs, Expr, + Header, Implements, ImplementsAbilities, ImplementsAbility, ImplementsClause, Module, + Pattern, RecordBuilderField, Spaced, Spaces, StrLiteral, StrSegment, Tag, TypeAnnotation, + TypeDef, TypeHeader, ValueDef, WhenBranch, }, header::{ AppHeader, ExposedName, HostedHeader, ImportsEntry, InterfaceHeader, KeywordItem, @@ -507,14 +507,14 @@ impl<'a> RemoveSpaces<'a> for TypeDef<'a> { }, Ability { header: TypeHeader { name, vars }, - loc_has, + loc_implements: loc_has, members, } => Ability { header: TypeHeader { name: name.remove_spaces(arena), vars: vars.remove_spaces(arena), }, - loc_has: loc_has.remove_spaces(arena), + loc_implements: loc_has.remove_spaces(arena), members: members.remove_spaces(arena), }, } @@ -569,9 +569,9 @@ impl<'a> RemoveSpaces<'a> for ValueDef<'a> { } } -impl<'a> RemoveSpaces<'a> for Has<'a> { +impl<'a> RemoveSpaces<'a> for Implements<'a> { fn remove_spaces(&self, _arena: &'a Bump) -> Self { - Has::Has + Implements::Implements } } @@ -870,9 +870,9 @@ impl<'a> RemoveSpaces<'a> for TypeAnnotation<'a> { } } -impl<'a> RemoveSpaces<'a> for HasClause<'a> { +impl<'a> RemoveSpaces<'a> for ImplementsClause<'a> { fn remove_spaces(&self, arena: &'a Bump) -> Self { - HasClause { + ImplementsClause { var: self.var.remove_spaces(arena), abilities: self.abilities.remove_spaces(arena), } @@ -893,38 +893,43 @@ impl<'a> RemoveSpaces<'a> for Tag<'a> { } } -impl<'a> RemoveSpaces<'a> for HasImpls<'a> { +impl<'a> RemoveSpaces<'a> for AbilityImpls<'a> { fn remove_spaces(&self, arena: &'a Bump) -> Self { match *self { - HasImpls::HasImpls(impls) => HasImpls::HasImpls(impls.remove_spaces(arena)), - HasImpls::SpaceBefore(has, _) | HasImpls::SpaceAfter(has, _) => { + AbilityImpls::AbilityImpls(impls) => { + AbilityImpls::AbilityImpls(impls.remove_spaces(arena)) + } + AbilityImpls::SpaceBefore(has, _) | AbilityImpls::SpaceAfter(has, _) => { has.remove_spaces(arena) } } } } -impl<'a> RemoveSpaces<'a> for HasAbility<'a> { +impl<'a> RemoveSpaces<'a> for ImplementsAbility<'a> { fn remove_spaces(&self, arena: &'a Bump) -> Self { match *self { - HasAbility::HasAbility { ability, impls } => HasAbility::HasAbility { - ability: ability.remove_spaces(arena), - impls: impls.remove_spaces(arena), - }, - HasAbility::SpaceBefore(has, _) | HasAbility::SpaceAfter(has, _) => { + ImplementsAbility::ImplementsAbility { ability, impls } => { + ImplementsAbility::ImplementsAbility { + ability: ability.remove_spaces(arena), + impls: impls.remove_spaces(arena), + } + } + ImplementsAbility::SpaceBefore(has, _) | ImplementsAbility::SpaceAfter(has, _) => { has.remove_spaces(arena) } } } } -impl<'a> RemoveSpaces<'a> for HasAbilities<'a> { +impl<'a> RemoveSpaces<'a> for ImplementsAbilities<'a> { fn remove_spaces(&self, arena: &'a Bump) -> Self { match *self { - HasAbilities::Has(derived) => HasAbilities::Has(derived.remove_spaces(arena)), - HasAbilities::SpaceBefore(derived, _) | HasAbilities::SpaceAfter(derived, _) => { - derived.remove_spaces(arena) + ImplementsAbilities::Implements(derived) => { + ImplementsAbilities::Implements(derived.remove_spaces(arena)) } + ImplementsAbilities::SpaceBefore(derived, _) + | ImplementsAbilities::SpaceAfter(derived, _) => derived.remove_spaces(arena), } } } diff --git a/crates/compiler/gen_dev/src/generic64/mod.rs b/crates/compiler/gen_dev/src/generic64/mod.rs index 98a9dfc5ca..918302e383 100644 --- a/crates/compiler/gen_dev/src/generic64/mod.rs +++ b/crates/compiler/gen_dev/src/generic64/mod.rs @@ -985,7 +985,8 @@ impl< let dst_reg = self.storage_manager.claim_float_reg(&mut self.buf, dst); ASM::mov_freg64_freg64(&mut self.buf, dst_reg, CC::FLOAT_RETURN_REGS[0]); } - LayoutRepr::I128 | LayoutRepr::U128 => { + // Note that on windows there is only 1 general return register so we can't use this optimisation + LayoutRepr::I128 | LayoutRepr::U128 if CC::GENERAL_RETURN_REGS.len() > 1 => { let offset = self.storage_manager.claim_stack_area(dst, 16); ASM::mov_base32_reg64(&mut self.buf, offset, CC::GENERAL_RETURN_REGS[0]); diff --git a/crates/compiler/gen_dev/src/generic64/x86_64.rs b/crates/compiler/gen_dev/src/generic64/x86_64.rs index 918330fc58..a5d969f1d7 100644 --- a/crates/compiler/gen_dev/src/generic64/x86_64.rs +++ b/crates/compiler/gen_dev/src/generic64/x86_64.rs @@ -8,7 +8,7 @@ use roc_builtins::bitcode::{FloatWidth, IntWidth}; use roc_error_macros::internal_error; use roc_module::symbol::Symbol; use roc_mono::layout::{ - Builtin, InLayout, LayoutInterner, LayoutRepr, STLayoutInterner, UnionLayout, + Builtin, InLayout, Layout, LayoutInterner, LayoutRepr, STLayoutInterner, UnionLayout, }; use super::{CompareOperation, RegisterWidth}; @@ -546,7 +546,7 @@ impl CallConv for X86_64Syste } } -fn copy_symbol_to_stack<'a, CC>( +fn copy_symbol_to_stack_offset<'a, CC>( buf: &mut Vec<'a, u8>, storage_manager: &mut X86_64StorageManager<'a, '_, CC>, sym: Symbol, @@ -600,6 +600,59 @@ where size } +fn copy_to_base_offset( + buf: &mut Vec<'_, u8>, + dst_base_offset: i32, + stack_size: u32, + ptr_reg: GeneralReg, + tmp_reg: GeneralReg, + read_offset: i32, +) where + FloatReg: RegTrait, + GeneralReg: RegTrait, + ASM: Assembler, +{ + let mut copied = 0; + let size = stack_size as i32; + let base_offset = dst_base_offset; + + if size - copied >= 8 { + for _ in (0..(size - copied)).step_by(8) { + ASM::mov_reg64_mem64_offset32(buf, tmp_reg, ptr_reg, read_offset + copied); + ASM::mov_base32_reg64(buf, base_offset + copied, tmp_reg); + + copied += 8; + } + } + + if size - copied >= 4 { + for _ in (0..(size - copied)).step_by(4) { + ASM::mov_reg32_mem32_offset32(buf, tmp_reg, ptr_reg, read_offset + copied); + ASM::mov_base32_reg32(buf, base_offset + copied, tmp_reg); + + copied += 4; + } + } + + if size - copied >= 2 { + for _ in (0..(size - copied)).step_by(2) { + ASM::mov_reg16_mem16_offset32(buf, tmp_reg, ptr_reg, read_offset + copied); + ASM::mov_base32_reg16(buf, base_offset + copied, tmp_reg); + + copied += 2; + } + } + + if size - copied >= 1 { + for _ in (0..(size - copied)).step_by(1) { + ASM::mov_reg8_mem8_offset32(buf, tmp_reg, ptr_reg, read_offset + copied); + ASM::mov_base32_reg8(buf, base_offset + copied, tmp_reg); + + copied += 1; + } + } +} + struct X64_64SystemVStoreArgs { general_i: usize, float_i: usize, @@ -658,7 +711,8 @@ impl X64_64SystemVStoreArgs { // Just copy onto the stack. let stack_offset = self.tmp_stack_offset; - let size = copy_symbol_to_stack(buf, storage_manager, sym, tmp_reg, stack_offset); + let size = + copy_symbol_to_stack_offset(buf, storage_manager, sym, tmp_reg, stack_offset); self.tmp_stack_offset += size as i32; } @@ -672,14 +726,16 @@ impl X64_64SystemVStoreArgs { LayoutRepr::Struct { .. } => { let stack_offset = self.tmp_stack_offset; - let size = copy_symbol_to_stack(buf, storage_manager, sym, tmp_reg, stack_offset); + let size = + copy_symbol_to_stack_offset(buf, storage_manager, sym, tmp_reg, stack_offset); self.tmp_stack_offset += size as i32; } LayoutRepr::Union(UnionLayout::NonRecursive(_)) => { let stack_offset = self.tmp_stack_offset; - let size = copy_symbol_to_stack(buf, storage_manager, sym, tmp_reg, stack_offset); + let size = + copy_symbol_to_stack_offset(buf, storage_manager, sym, tmp_reg, stack_offset); self.tmp_stack_offset += size as i32; } @@ -762,6 +818,8 @@ impl X64_64WindowsFastCallStoreArgs { sym: Symbol, in_layout: InLayout<'a>, ) { + type ASM = X86_64Assembler; + // we use the return register as a temporary register; it will be overwritten anyway let tmp_reg = Self::GENERAL_RETURN_REGS[0]; @@ -776,31 +834,50 @@ impl X64_64WindowsFastCallStoreArgs { let reg1 = Self::GENERAL_PARAM_REGS[self.general_i]; let reg2 = Self::GENERAL_PARAM_REGS[self.general_i + 1]; - X86_64Assembler::mov_reg64_base32(buf, reg1, offset); - X86_64Assembler::mov_reg64_base32(buf, reg2, offset + 8); + ASM::mov_reg64_base32(buf, reg1, offset); + ASM::mov_reg64_base32(buf, reg2, offset + 8); self.general_i += 2; } else { // Copy to stack using return reg as buffer. let reg = Self::GENERAL_RETURN_REGS[0]; - X86_64Assembler::mov_reg64_base32(buf, reg, offset); - X86_64Assembler::mov_stack32_reg64(buf, self.tmp_stack_offset, reg); + ASM::mov_reg64_base32(buf, reg, offset); + ASM::mov_stack32_reg64(buf, self.tmp_stack_offset, reg); - X86_64Assembler::mov_reg64_base32(buf, reg, offset + 8); - X86_64Assembler::mov_stack32_reg64(buf, self.tmp_stack_offset + 8, reg); + ASM::mov_reg64_base32(buf, reg, offset + 8); + ASM::mov_stack32_reg64(buf, self.tmp_stack_offset + 8, reg); self.tmp_stack_offset += 16; } } _ if layout_interner.stack_size(in_layout) == 0 => {} _ if layout_interner.stack_size(in_layout) > 16 => { - // for now, just copy onto the stack. - let stack_offset = self.tmp_stack_offset; + // Reference: https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170#parameter-passing + match Self::GENERAL_PARAM_REGS.get(self.general_i) { + Some(reg) => { + // if there is a general purpose register available, use it to store a pointer to the value + let (base_offset, _size) = storage_manager.stack_offset_and_size(&sym); - let size = copy_symbol_to_stack(buf, storage_manager, sym, tmp_reg, stack_offset); + ASM::add_reg64_reg64_imm32(buf, *reg, X86_64GeneralReg::RBP, base_offset); - self.tmp_stack_offset += size as i32; + self.general_i += 1; + } + None => { + // else, pass the value implicitly by copying to the stack (of the new frame) + let stack_offset = self.tmp_stack_offset; + + let size = copy_symbol_to_stack_offset( + buf, + storage_manager, + sym, + tmp_reg, + stack_offset, + ); + + self.tmp_stack_offset += size as i32; + } + } } LayoutRepr::LambdaSet(lambda_set) => self.store_arg( buf, @@ -813,14 +890,16 @@ impl X64_64WindowsFastCallStoreArgs { // for now, just also store this on the stack let stack_offset = self.tmp_stack_offset; - let size = copy_symbol_to_stack(buf, storage_manager, sym, tmp_reg, stack_offset); + let size = + copy_symbol_to_stack_offset(buf, storage_manager, sym, tmp_reg, stack_offset); self.tmp_stack_offset += size as i32; } LayoutRepr::Union(UnionLayout::NonRecursive(_)) => { let stack_offset = self.tmp_stack_offset; - let size = copy_symbol_to_stack(buf, storage_manager, sym, tmp_reg, stack_offset); + let size = + copy_symbol_to_stack_offset(buf, storage_manager, sym, tmp_reg, stack_offset); self.tmp_stack_offset += size as i32; } @@ -977,11 +1056,14 @@ struct X64_64WindowsFastCallLoadArgs { impl X64_64WindowsFastCallLoadArgs { fn load_arg<'a>( &mut self, + buf: &mut Vec<'a, u8>, storage_manager: &mut X86_64StorageManager<'a, '_, X86_64WindowsFastcall>, layout_interner: &mut STLayoutInterner<'a>, sym: Symbol, in_layout: InLayout<'a>, ) { + type ASM = X86_64Assembler; + let stack_size = layout_interner.stack_size(in_layout); match layout_interner.get_repr(in_layout) { single_register_integers!() => self.load_arg_general(storage_manager, sym), @@ -991,11 +1073,33 @@ impl X64_64WindowsFastCallLoadArgs { storage_manager.no_data(&sym); } _ if stack_size > 16 => { - // TODO: Double check this. - storage_manager.complex_stack_arg(&sym, self.argument_offset, stack_size); - self.argument_offset += stack_size as i32; + // Reference: https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170#parameter-passing + match X86_64WindowsFastcall::GENERAL_PARAM_REGS.get(self.general_i) { + Some(ptr_reg) => { + // if there is a general purpose register available, use it to store a pointer to the value + let base_offset = storage_manager.claim_stack_area(&sym, stack_size); + let tmp_reg = X86_64WindowsFastcall::GENERAL_RETURN_REGS[0]; + + copy_to_base_offset::<_, _, ASM>( + buf, + base_offset, + stack_size, + *ptr_reg, + tmp_reg, + 0, + ); + + self.general_i += 1; + } + None => { + // else, pass the value implicitly by copying to the stack (of the new frame) + storage_manager.complex_stack_arg(&sym, self.argument_offset, stack_size); + self.argument_offset += stack_size as i32; + } + } } LayoutRepr::LambdaSet(lambda_set) => self.load_arg( + buf, storage_manager, layout_interner, sym, @@ -1130,6 +1234,9 @@ impl CallConv for X86_64Windo ]; const SHADOW_SPACE_SIZE: u8 = 32; + // Refer https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170#callercallee-saved-registers + // > The x64 ABI considers registers RBX, RBP, RDI, RSI, RSP, R12, R13, R14, R15, and XMM6-XMM15 nonvolatile. + // > They must be saved and restored by a function that uses them. #[inline(always)] fn general_callee_saved(reg: &X86_64GeneralReg) -> bool { matches!( @@ -1146,16 +1253,23 @@ impl CallConv for X86_64Windo ) } + // Refer https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170#callercallee-saved-registers + // > The x64 ABI considers registers RBX, RBP, RDI, RSI, RSP, R12, R13, R14, R15, and XMM6-XMM15 nonvolatile. + // > They must be saved and restored by a function that uses them. #[inline(always)] fn float_callee_saved(reg: &X86_64FloatReg) -> bool { matches!( reg, - X86_64FloatReg::XMM0 - | X86_64FloatReg::XMM1 - | X86_64FloatReg::XMM2 - | X86_64FloatReg::XMM3 - | X86_64FloatReg::XMM4 - | X86_64FloatReg::XMM5 + X86_64FloatReg::XMM6 + | X86_64FloatReg::XMM7 + | X86_64FloatReg::XMM8 + | X86_64FloatReg::XMM9 + | X86_64FloatReg::XMM10 + | X86_64FloatReg::XMM11 + | X86_64FloatReg::XMM12 + | X86_64FloatReg::XMM13 + | X86_64FloatReg::XMM14 + | X86_64FloatReg::XMM15 ) } @@ -1195,7 +1309,7 @@ impl CallConv for X86_64Windo #[inline(always)] fn load_args<'a>( - _buf: &mut Vec<'a, u8>, + buf: &mut Vec<'a, u8>, storage_manager: &mut X86_64StorageManager<'a, '_, X86_64WindowsFastcall>, layout_interner: &mut STLayoutInterner<'a>, args: &'a [(InLayout<'a>, Symbol)], @@ -1216,7 +1330,7 @@ impl CallConv for X86_64Windo } for (in_layout, sym) in args.iter() { - state.load_arg(storage_manager, layout_interner, *sym, *in_layout); + state.load_arg(buf, storage_manager, layout_interner, *sym, *in_layout); } } @@ -1286,6 +1400,16 @@ impl CallConv for X86_64Windo single_register_layouts!() => { internal_error!("single register layouts are not complex symbols"); } + // For windows (and zig 0.9 changes in zig 0.10) we need to match what zig does, + // in this case uses RAX & RDX to return the value + LayoutRepr::I128 | LayoutRepr::U128 => { + let (base_offset, size) = storage_manager.stack_offset_and_size(sym); + debug_assert_eq!(base_offset % 8, 0); + debug_assert_eq!(size, 16); + + X86_64Assembler::mov_reg64_base32(buf, X86_64GeneralReg::RAX, base_offset); + X86_64Assembler::mov_reg64_base32(buf, X86_64GeneralReg::RDX, base_offset + 0x08); + } _ if layout_interner.stack_size(*layout) == 0 => {} _ if !Self::returns_via_arg_pointer(layout_interner, layout) => { let (base_offset, size) = storage_manager.stack_offset_and_size(sym); @@ -1333,6 +1457,14 @@ impl CallConv for X86_64Windo single_register_layouts!() => { internal_error!("single register layouts are not complex symbols"); } + // For windows (and zig 0.9 changes in zig 0.10) we need to match what zig does, + // in this case uses RAX & RDX to return the value + LayoutRepr::I128 | LayoutRepr::U128 => { + let size = layout_interner.stack_size(*layout); + let offset = storage_manager.claim_stack_area(sym, size); + X86_64Assembler::mov_base32_reg64(buf, offset, X86_64GeneralReg::RAX); + X86_64Assembler::mov_base32_reg64(buf, offset + 0x08, X86_64GeneralReg::RDX); + } _ if layout_interner.stack_size(*layout) == 0 => { storage_manager.no_data(sym); } @@ -1446,12 +1578,16 @@ impl CallConv for X86_64Windo type ASM = X86_64Assembler; // a *const RocStr - let roc_str_ptr = R11; - ASM::add_reg64_reg64_imm32(buf, roc_str_ptr, RSP, 16 + 24); // 24 is width of a rocstr + let roc_str_ptr = RCX; + debug_assert_eq!(roc_str_ptr, Self::GENERAL_PARAM_REGS[0]); // a 32-bit integer - let panic_tag = RCX; - debug_assert_eq!(panic_tag, Self::GENERAL_PARAM_REGS[0]); + let panic_tag = RDX; + debug_assert_eq!(panic_tag, Self::GENERAL_PARAM_REGS[1]); + + // move the crash tag into a temporary register. We add 1 to it because the 0 value + // is already used for "no crash occurred" + ASM::add_reg64_reg64_imm32(buf, R10, panic_tag, 0x01); // the setlongjmp_buffer let env = R8; @@ -1485,16 +1621,12 @@ impl CallConv for X86_64Windo ASM::mov_reg64_mem64_offset32(buf, result_pointer, env, 0x58); // a pointer to the error message - ASM::mov_reg64_imm64(buf, R10, 0x60); - ASM::add_reg64_reg64_reg64(buf, R10, R10, env); + ASM::add_reg64_reg64_imm32(buf, R11, env, 0x60); // write a pointer to the error message into result_pointer - ASM::mov_mem64_offset32_reg64(buf, result_pointer, 0x00, R10); + ASM::mov_mem64_offset32_reg64(buf, result_pointer, 0x00, R11); - // the panic_tag; 1 is added to differentiate from 0 (which indicates success) - ASM::add_reg64_reg64_imm32(buf, R10, panic_tag, 1); - - // write the panic tag into the result_pointer + // write the panic tag (now in R10) into the result_pointer ASM::mov_mem64_offset32_reg64(buf, result_pointer, 0x08, R10); jmp_reg64_offset8(buf, env, 0x50) @@ -1508,7 +1640,10 @@ impl X86_64WindowsFastcall { ) -> bool { // TODO: This is not fully correct there are some exceptions for "vector" types. // details here: https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-160#return-values - interner.stack_size(*ret_layout) > 8 + match *ret_layout { + Layout::I128 | Layout::U128 => false, + _ => interner.stack_size(*ret_layout) > 8, + } } } diff --git a/crates/compiler/gen_dev/src/lib.rs b/crates/compiler/gen_dev/src/lib.rs index 87a341d230..efd734864f 100644 --- a/crates/compiler/gen_dev/src/lib.rs +++ b/crates/compiler/gen_dev/src/lib.rs @@ -45,6 +45,13 @@ impl AssemblyBackendMode { AssemblyBackendMode::Test => true, } } + + fn generate_roc_panic(self) -> bool { + match self { + AssemblyBackendMode::Binary => false, + AssemblyBackendMode::Test => true, + } + } } pub struct Env<'a> { diff --git a/crates/compiler/gen_dev/src/object_builder.rs b/crates/compiler/gen_dev/src/object_builder.rs index 62acda1cb5..8b92fad67c 100644 --- a/crates/compiler/gen_dev/src/object_builder.rs +++ b/crates/compiler/gen_dev/src/object_builder.rs @@ -1,5 +1,5 @@ use crate::generic64::{aarch64, new_backend_64bit, x86_64}; -use crate::{Backend, Env, Relocation}; +use crate::{AssemblyBackendMode, Backend, Env, Relocation}; use bumpalo::collections::Vec; use object::write::{self, SectionId, SymbolId}; use object::write::{Object, StandardSection, StandardSegment, Symbol, SymbolSection}; @@ -312,11 +312,13 @@ fn build_object<'a, B: Backend<'a>>( ); */ - define_setlongjmp_buffer(&mut output); + if backend.env().mode.generate_roc_panic() { + define_setlongjmp_buffer(&mut output); - generate_roc_panic(&mut backend, &mut output); - generate_setjmp(&mut backend, &mut output); - generate_longjmp(&mut backend, &mut output); + generate_roc_panic(&mut backend, &mut output); + generate_setjmp(&mut backend, &mut output); + generate_longjmp(&mut backend, &mut output); + } if backend.env().mode.generate_allocators() { generate_wrapper( @@ -402,15 +404,17 @@ fn build_object<'a, B: Backend<'a>>( // println!("{}", test_helper.to_pretty(backend.interner(), 200, true)); - build_proc_symbol( - &mut output, - &mut layout_ids, - &mut procs, - &mut backend, - layout, - test_helper, - Exposed::TestMain, - ); + if let AssemblyBackendMode::Test = backend.env().mode { + build_proc_symbol( + &mut output, + &mut layout_ids, + &mut procs, + &mut backend, + layout, + test_helper, + Exposed::TestMain, + ); + } build_proc_symbol( &mut output, @@ -599,7 +603,6 @@ fn build_exposed_proc<'a, B: Backend<'a>>(backend: &mut B, proc: &Proc<'a>) -> P closure_data_layout: None, ret_layout: proc.ret_layout, is_self_recursive: roc_mono::ir::SelfRecursive::NotSelfRecursive, - host_exposed_layouts: roc_mono::ir::HostExposedLayouts::NotHostExposed, is_erased: proc.is_erased, } } @@ -681,7 +684,6 @@ fn build_exposed_generic_proc<'a, B: Backend<'a>>(backend: &mut B, proc: &Proc<' closure_data_layout: None, ret_layout: roc_mono::layout::Layout::UNIT, is_self_recursive: roc_mono::ir::SelfRecursive::NotSelfRecursive, - host_exposed_layouts: roc_mono::ir::HostExposedLayouts::NotHostExposed, is_erased: proc.is_erased, } } diff --git a/crates/compiler/gen_llvm/src/llvm/build.rs b/crates/compiler/gen_llvm/src/llvm/build.rs index 92649bc5a1..c840b5712f 100644 --- a/crates/compiler/gen_llvm/src/llvm/build.rs +++ b/crates/compiler/gen_llvm/src/llvm/build.rs @@ -43,7 +43,7 @@ use roc_error_macros::{internal_error, todo_lambda_erasure}; use roc_module::symbol::{Interns, Symbol}; use roc_mono::ir::{ BranchInfo, CallType, CrashTag, EntryPoint, GlueLayouts, HostExposedLambdaSet, - ListLiteralElement, ModifyRc, OptLevel, ProcLayout, SingleEntryPoint, + HostExposedLambdaSets, ListLiteralElement, ModifyRc, OptLevel, ProcLayout, SingleEntryPoint, }; use roc_mono::layout::{ Builtin, InLayout, LambdaName, LambdaSet, Layout, LayoutIds, LayoutInterner, LayoutRepr, Niche, @@ -4920,6 +4920,7 @@ pub fn build_procedures<'a>( layout_interner: &STLayoutInterner<'a>, opt_level: OptLevel, procedures: MutMap<(Symbol, ProcLayout<'a>), roc_mono::ir::Proc<'a>>, + host_exposed_lambda_sets: HostExposedLambdaSets<'a>, entry_point: EntryPoint<'a>, debug_output_file: Option<&Path>, glue_layouts: &GlueLayouts<'a>, @@ -4929,6 +4930,7 @@ pub fn build_procedures<'a>( layout_interner, opt_level, procedures, + host_exposed_lambda_sets, entry_point, debug_output_file, ); @@ -4982,6 +4984,7 @@ pub fn build_wasm_test_wrapper<'a, 'ctx>( layout_interner, opt_level, procedures, + vec![], EntryPoint::Single(entry_point), Some(&std::env::temp_dir().join("test.ll")), ); @@ -5000,6 +5003,7 @@ pub fn build_procedures_return_main<'a, 'ctx>( layout_interner: &STLayoutInterner<'a>, opt_level: OptLevel, procedures: MutMap<(Symbol, ProcLayout<'a>), roc_mono::ir::Proc<'a>>, + host_exposed_lambda_sets: HostExposedLambdaSets<'a>, entry_point: SingleEntryPoint<'a>, ) -> (&'static str, FunctionValue<'ctx>) { let mod_solutions = build_procedures_help( @@ -5007,6 +5011,7 @@ pub fn build_procedures_return_main<'a, 'ctx>( layout_interner, opt_level, procedures, + host_exposed_lambda_sets, EntryPoint::Single(entry_point), Some(&std::env::temp_dir().join("test.ll")), ); @@ -5034,6 +5039,7 @@ pub fn build_procedures_expose_expects<'a>( layout_interner, opt_level, procedures, + vec![], entry_point, Some(&std::env::temp_dir().join("test.ll")), ); @@ -5096,20 +5102,23 @@ fn build_procedures_help<'a>( layout_interner: &STLayoutInterner<'a>, opt_level: OptLevel, procedures: MutMap<(Symbol, ProcLayout<'a>), roc_mono::ir::Proc<'a>>, + host_exposed_lambda_sets: HostExposedLambdaSets<'a>, entry_point: EntryPoint<'a>, debug_output_file: Option<&Path>, ) -> &'a ModSolutions { let mut layout_ids = roc_mono::layout::LayoutIds::default(); let mut scope = Scope::default(); - let it = procedures.iter().map(|x| x.1); + let it1 = procedures.iter().map(|x| x.1); + let it2 = host_exposed_lambda_sets.iter().map(|(_, _, hels)| hels); let solutions = match roc_alias_analysis::spec_program( env.arena, layout_interner, opt_level, entry_point, - it, + it1, + it2, ) { Err(e) => panic!("Error in alias analysis: {e}"), Ok(solutions) => solutions, @@ -5147,7 +5156,6 @@ fn build_procedures_help<'a>( build_proc( env, layout_interner, - mod_solutions, &mut layout_ids, func_spec_solutions, scope.clone(), @@ -5192,6 +5200,26 @@ fn build_procedures_help<'a>( } } + use LlvmBackendMode::*; + match env.mode { + GenTest | WasmGenTest | CliTest => { /* no host, or exposing types is not supported */ } + Binary | BinaryDev | BinaryGlue => { + for (proc_name, alias_name, hels) in host_exposed_lambda_sets.iter() { + let ident_string = proc_name.name().as_str(&env.interns); + let fn_name: String = format!("{}_{}", ident_string, hels.id.0); + + expose_alias_to_host( + env, + layout_interner, + mod_solutions, + &fn_name, + *alias_name, + hels, + ) + } + } + } + mod_solutions } @@ -5558,43 +5586,12 @@ fn build_host_exposed_alias_size_help<'a, 'ctx>( fn build_proc<'a, 'ctx>( env: &Env<'a, 'ctx, '_>, layout_interner: &STLayoutInterner<'a>, - mod_solutions: &'a ModSolutions, layout_ids: &mut LayoutIds<'a>, func_spec_solutions: &FuncSpecSolutions, mut scope: Scope<'a, 'ctx>, proc: &roc_mono::ir::Proc<'a>, fn_val: FunctionValue<'ctx>, ) { - use roc_mono::ir::HostExposedLayouts; - - match &proc.host_exposed_layouts { - HostExposedLayouts::NotHostExposed => {} - HostExposedLayouts::HostExposed { aliases, .. } => { - use LlvmBackendMode::*; - - match env.mode { - GenTest | WasmGenTest | CliTest => { - /* no host, or exposing types is not supported */ - } - Binary | BinaryDev | BinaryGlue => { - for (alias_name, hels) in aliases.iter() { - let ident_string = proc.name.name().as_str(&env.interns); - let fn_name: String = format!("{}_{}", ident_string, hels.id.0); - - expose_alias_to_host( - env, - layout_interner, - mod_solutions, - &fn_name, - *alias_name, - hels, - ) - } - } - } - } - }; - let args = proc.args; let context = &env.context; diff --git a/crates/compiler/gen_wasm/src/backend.rs b/crates/compiler/gen_wasm/src/backend.rs index 1949a9bd0a..c19f374d2e 100644 --- a/crates/compiler/gen_wasm/src/backend.rs +++ b/crates/compiler/gen_wasm/src/backend.rs @@ -1160,8 +1160,13 @@ impl<'a, 'r> WasmBackend<'a, 'r> { *******************************************************************/ fn expr_literal(&mut self, lit: &Literal<'a>, storage: &StoredValue) { - let invalid_error = - || internal_error!("Literal value {:?} has invalid storage {:?}", lit, storage); + let invalid_error = || { + internal_error!( + "Literal value {:?} implements invalid storage {:?}", + lit, + storage + ) + }; match storage { StoredValue::VirtualMachineStack { value_type, .. } => { diff --git a/crates/compiler/load/build.rs b/crates/compiler/load/build.rs index 5119007da6..6655800ad3 100644 --- a/crates/compiler/load/build.rs +++ b/crates/compiler/load/build.rs @@ -25,6 +25,7 @@ const MODULES: &[(ModuleId, &str)] = &[ (ModuleId::ENCODE, "Encode.roc"), (ModuleId::DECODE, "Decode.roc"), (ModuleId::HASH, "Hash.roc"), + (ModuleId::INSPECT, "Inspect.roc"), (ModuleId::JSON, "TotallyNotJson.roc"), ]; diff --git a/crates/compiler/load/src/lib.rs b/crates/compiler/load/src/lib.rs index 0777b01f2a..3dc1ecc6a7 100644 --- a/crates/compiler/load/src/lib.rs +++ b/crates/compiler/load/src/lib.rs @@ -200,18 +200,27 @@ pub fn load_and_typecheck_str<'a>( } } +macro_rules! include_bytes_align_as { + ($align_ty:ty, $path:expr) => {{ + // const block expression to encapsulate the static + + #[repr(C)] + pub struct AlignedAs { + pub _align: [Align; 0], + pub bytes: Bytes, + } + + // this assignment is made possible by CoerceUnsized + static ALIGNED: &AlignedAs<$align_ty, [u8]> = &AlignedAs { + _align: [], + bytes: *include_bytes!($path), + }; + + &ALIGNED.bytes + }}; +} + // IFTTT: crates/compiler/load/build.rs -const BOOL: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/Bool.dat")) as &[_]; -const DICT: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/Dict.dat")) as &[_]; -const SET: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/Set.dat")) as &[_]; -const RESULT: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/Result.dat")) as &[_]; -const NUM: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/Num.dat")) as &[_]; -const LIST: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/List.dat")) as &[_]; -const STR: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/Str.dat")) as &[_]; -const BOX: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/Box.dat")) as &[_]; -const ENCODE: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/Encode.dat")) as &[_]; -const DECODE: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/Decode.dat")) as &[_]; -const HASH: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/Hash.dat")) as &[_]; fn deserialize_help(bytes: &[u8]) -> TypeState { let (state, _offset) = TypeState::deserialize(bytes); @@ -221,27 +230,41 @@ fn deserialize_help(bytes: &[u8]) -> TypeState { } fn read_cached_types() -> MutMap { + let mod_bool = include_bytes_align_as!(u128, concat!(env!("OUT_DIR"), "/Bool.dat")); + let mod_dict = include_bytes_align_as!(u128, concat!(env!("OUT_DIR"), "/Dict.dat")); + let mod_set = include_bytes_align_as!(u128, concat!(env!("OUT_DIR"), "/Set.dat")); + let mod_result = include_bytes_align_as!(u128, concat!(env!("OUT_DIR"), "/Result.dat")); + let mod_num = include_bytes_align_as!(u128, concat!(env!("OUT_DIR"), "/Num.dat")); + let mod_list = include_bytes_align_as!(u128, concat!(env!("OUT_DIR"), "/List.dat")); + let mod_str = include_bytes_align_as!(u128, concat!(env!("OUT_DIR"), "/Str.dat")); + let mod_box = include_bytes_align_as!(u128, concat!(env!("OUT_DIR"), "/Box.dat")); + let mod_encode = include_bytes_align_as!(u128, concat!(env!("OUT_DIR"), "/Encode.dat")); + let mod_decode = include_bytes_align_as!(u128, concat!(env!("OUT_DIR"), "/Decode.dat")); + let mod_hash = include_bytes_align_as!(u128, concat!(env!("OUT_DIR"), "/Hash.dat")); + let mod_inspect = include_bytes_align_as!(u128, concat!(env!("OUT_DIR"), "/Inspect.dat")); + let mut output = MutMap::default(); // Wasm seems to re-order definitions between build time and runtime, but only in release mode. // That is very strange, but we can solve it separately if !cfg!(target_family = "wasm") && !cfg!(windows) && !SKIP_SUBS_CACHE { - output.insert(ModuleId::BOOL, deserialize_help(BOOL)); + output.insert(ModuleId::BOOL, deserialize_help(mod_bool)); - output.insert(ModuleId::RESULT, deserialize_help(RESULT)); - output.insert(ModuleId::NUM, deserialize_help(NUM)); + output.insert(ModuleId::RESULT, deserialize_help(mod_result)); + output.insert(ModuleId::NUM, deserialize_help(mod_num)); - output.insert(ModuleId::LIST, deserialize_help(LIST)); - output.insert(ModuleId::STR, deserialize_help(STR)); - output.insert(ModuleId::BOX, deserialize_help(BOX)); + output.insert(ModuleId::LIST, deserialize_help(mod_list)); + output.insert(ModuleId::STR, deserialize_help(mod_str)); + output.insert(ModuleId::BOX, deserialize_help(mod_box)); - output.insert(ModuleId::DICT, deserialize_help(DICT)); - output.insert(ModuleId::SET, deserialize_help(SET)); + output.insert(ModuleId::DICT, deserialize_help(mod_dict)); + output.insert(ModuleId::SET, deserialize_help(mod_set)); - output.insert(ModuleId::ENCODE, deserialize_help(ENCODE)); - output.insert(ModuleId::DECODE, deserialize_help(DECODE)); + output.insert(ModuleId::ENCODE, deserialize_help(mod_encode)); + output.insert(ModuleId::DECODE, deserialize_help(mod_decode)); - output.insert(ModuleId::HASH, deserialize_help(HASH)); + output.insert(ModuleId::HASH, deserialize_help(mod_hash)); + output.insert(ModuleId::INSPECT, deserialize_help(mod_inspect)); } output diff --git a/crates/compiler/load_internal/src/docs.rs b/crates/compiler/load_internal/src/docs.rs index 27dee8c8a0..b84f701bf2 100644 --- a/crates/compiler/load_internal/src/docs.rs +++ b/crates/compiler/load_internal/src/docs.rs @@ -54,11 +54,30 @@ pub enum TypeAnnotation { fields: Vec, extension: Box, }, + Tuple { + elems: Vec, + extension: Box, + }, Ability { members: Vec, }, Wildcard, NoTypeAnn, + Where { + ann: Box, + implements: Vec, + }, + As { + ann: Box, + name: String, + vars: Vec, + }, +} + +#[derive(Debug, Clone)] +pub struct ImplementsClause { + pub name: String, + pub abilities: Vec, } #[derive(Debug, Clone)] @@ -450,7 +469,7 @@ fn contains_unexposed_type( false } Where(loc_ann, _loc_has_clauses) => { - // We assume all the abilities in the `has` clause are from exported modules. + // We assume all the abilities in the `implements` clause are from exported modules. // TODO don't assume this! Instead, look them up and verify. contains_unexposed_type(&loc_ann.value, exposed_module_ids, module_ids) } @@ -540,7 +559,57 @@ fn type_to_docs(in_func_type_ann: bool, type_annotation: ast::TypeAnnotation) -> } } ast::TypeAnnotation::Wildcard => TypeAnnotation::Wildcard, - _ => NoTypeAnn, + ast::TypeAnnotation::As(loc_ann, _comments, type_header) => TypeAnnotation::As { + ann: Box::new(type_to_docs(in_func_type_ann, loc_ann.value)), + name: type_header.name.value.to_string(), + vars: type_header + .vars + .iter() + .filter_map(|loc_pattern| match loc_pattern.value { + ast::Pattern::Identifier(ident) => Some(ident.to_string()), + _ => None, + }) + .collect(), + }, + ast::TypeAnnotation::Tuple { elems, ext } => { + let mut doc_elems = Vec::new(); + + for loc_ann in elems.items { + doc_elems.push(type_to_docs(in_func_type_ann, loc_ann.value)); + } + + let extension = match ext { + None => NoTypeAnn, + Some(ext_type_ann) => type_to_docs(in_func_type_ann, ext_type_ann.value), + }; + + TypeAnnotation::Tuple { + elems: doc_elems, + extension: Box::new(extension), + } + } + ast::TypeAnnotation::Where(loc_ann, implements) => TypeAnnotation::Where { + ann: Box::new(type_to_docs(in_func_type_ann, loc_ann.value)), + implements: implements + .iter() + .map(|clause| { + let abilities = clause + .value + .abilities + .iter() + .map(|ability| type_to_docs(in_func_type_ann, ability.value)) + .collect(); + + ImplementsClause { + name: clause.value.var.value.item().to_string(), + abilities, + } + }) + .collect(), + }, + ast::TypeAnnotation::Malformed(_) | ast::TypeAnnotation::Inferred => { + TypeAnnotation::NoTypeAnn + } } } @@ -553,7 +622,7 @@ fn ability_member_type_to_docs( let has_clauses = has_clauses .iter() .map(|hc| { - let ast::HasClause { var, abilities } = hc.value; + let ast::ImplementsClause { var, abilities } = hc.value; ( var.value.extract_spaces().item.to_string(), abilities diff --git a/crates/compiler/load_internal/src/file.rs b/crates/compiler/load_internal/src/file.rs index bf79445f92..e6d9678a18 100644 --- a/crates/compiler/load_internal/src/file.rs +++ b/crates/compiler/load_internal/src/file.rs @@ -38,10 +38,9 @@ use roc_module::symbol::{ PackageQualified, Symbol, }; use roc_mono::ir::{ - CapturedSymbols, ExternalSpecializations, GlueLayouts, PartialProc, Proc, ProcLayout, Procs, - ProcsBase, UpdateModeIds, UsageTrackingMap, + CapturedSymbols, ExternalSpecializations, GlueLayouts, HostExposedLambdaSets, PartialProc, + Proc, ProcLayout, Procs, ProcsBase, UpdateModeIds, UsageTrackingMap, }; -use roc_mono::layout::LayoutInterner; use roc_mono::layout::{ GlobalLayoutInterner, LambdaName, Layout, LayoutCache, LayoutProblem, Niche, STLayoutInterner, }; @@ -614,6 +613,7 @@ enum Msg<'a> { external_specializations_requested: BumpMap>, procs_base: ProcsBase<'a>, procedures: MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>, + host_exposed_lambda_sets: HostExposedLambdaSets<'a>, update_mode_ids: UpdateModeIds, module_timing: ModuleTiming, subs: Subs, @@ -709,6 +709,7 @@ struct State<'a> { pub module_cache: ModuleCache<'a>, pub dependencies: Dependencies<'a>, pub procedures: MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>, + pub host_exposed_lambda_sets: HostExposedLambdaSets<'a>, pub toplevel_expects: ToplevelExpects, pub exposed_to_host: ExposedToHost, @@ -789,6 +790,7 @@ impl<'a> State<'a> { module_cache: ModuleCache::default(), dependencies, procedures: MutMap::default(), + host_exposed_lambda_sets: std::vec::Vec::new(), toplevel_expects: ToplevelExpects::default(), exposed_to_host: ExposedToHost::default(), exposed_modules: &[], @@ -2288,6 +2290,7 @@ fn update<'a>( extend_header_with_builtin(header, ModuleId::ENCODE); extend_header_with_builtin(header, ModuleId::DECODE); extend_header_with_builtin(header, ModuleId::HASH); + extend_header_with_builtin(header, ModuleId::INSPECT); } state @@ -2650,6 +2653,7 @@ fn update<'a>( subs, procs_base, procedures, + host_exposed_lambda_sets, external_specializations_requested, module_timing, layout_cache, @@ -2667,6 +2671,9 @@ fn update<'a>( let _ = layout_cache; state.procedures.extend(procedures); + state + .host_exposed_lambda_sets + .extend(host_exposed_lambda_sets); state.module_cache.late_specializations.insert( module_id, LateSpecializationsModule { @@ -2863,7 +2870,7 @@ fn update<'a>( // # Default module // interface Default exposes [default, getDefault] // - // Default has default : {} -> a | a has Default + // Default implements default : {} -> a where a implements Default // // getDefault = \{} -> default {} // @@ -2982,8 +2989,8 @@ fn finish_specialization<'a>( arena: &'a Bump, state: State<'a>, subs: Subs, - mut layout_interner: STLayoutInterner<'a>, - mut exposed_to_host: ExposedToHost, + layout_interner: STLayoutInterner<'a>, + exposed_to_host: ExposedToHost, module_expectations: VecMap, ) -> Result, LoadingProblem<'a>> { if false { @@ -3082,6 +3089,7 @@ fn finish_specialization<'a>( let State { toplevel_expects, procedures, + host_exposed_lambda_sets, module_cache, output_path, platform_data, @@ -3101,53 +3109,6 @@ fn finish_specialization<'a>( .collect(); let module_id = state.root_id; - let mut glue_getters = Vec::new(); - - // the REPL does not have any platform data - if let ( - EntryPoint::Executable { - exposed_to_host: exposed_top_levels, - .. - }, - Some(platform_data), - ) = (&entry_point, platform_data.as_ref()) - { - // Expose glue for the platform, not for the app module! - let module_id = platform_data.module_id; - - for (_name, proc_layout) in exposed_top_levels.iter() { - let ret = &proc_layout.result; - for in_layout in proc_layout.arguments.iter().chain([ret]) { - let layout = layout_interner.get(*in_layout); - let ident_ids = interns.all_ident_ids.get_mut(&module_id).unwrap(); - let all_glue_procs = roc_mono::ir::generate_glue_procs( - module_id, - ident_ids, - arena, - &mut layout_interner, - arena.alloc(layout), - ); - - let lambda_set_names = all_glue_procs - .legacy_layout_based_extern_names - .iter() - .map(|(lambda_set_id, _)| (*_name, *lambda_set_id)); - exposed_to_host.lambda_sets.extend(lambda_set_names); - - let getter_names = all_glue_procs - .getters - .iter() - .flat_map(|(_, glue_procs)| glue_procs.iter().map(|glue_proc| glue_proc.name)); - exposed_to_host.getters.extend(getter_names); - - glue_getters.extend(all_glue_procs.getters.iter().flat_map(|(_, glue_procs)| { - glue_procs - .iter() - .map(|glue_proc| (glue_proc.name, glue_proc.proc_layout)) - })); - } - } - } let output_path = match output_path { Some(path_str) => Path::new(path_str).into(), @@ -3172,13 +3133,12 @@ fn finish_specialization<'a>( interns, layout_interner, procedures, + host_exposed_lambda_sets, entry_point, sources, timings: state.timings, toplevel_expects, - glue_layouts: GlueLayouts { - getters: glue_getters, - }, + glue_layouts: GlueLayouts { getters: vec![] }, uses_prebuilt_platform, }) } @@ -3535,6 +3495,7 @@ fn load_module<'a>( "Encode", ModuleId::ENCODE "Decode", ModuleId::DECODE "Hash", ModuleId::HASH + "Inspect", ModuleId::INSPECT "TotallyNotJson", ModuleId::JSON } @@ -4326,7 +4287,7 @@ fn build_header<'a>( // created an IdentId for this, when it was imported exposed // in a dependent module. // - // For example, if module A has [B.{ foo }], then + // For example, if module A implements [B.{ foo }], then // when we get here for B, `foo` will already have // an IdentId. We must reuse that! let ident_id = ident_ids.get_or_insert(loc_exposed.value.as_str()); @@ -4350,7 +4311,7 @@ fn build_header<'a>( // created an IdentId for this, when it was imported exposed // in a dependent module. // - // For example, if module A has [B.{ foo }], then + // For example, if module A implements [B.{ foo }], then // when we get here for B, `foo` will already have // an IdentId. We must reuse that! let ident_id = ident_ids.get_or_insert(loc_name.value.as_str()); @@ -5298,6 +5259,7 @@ fn canonicalize_and_constrain<'a>( | ModuleId::DICT | ModuleId::SET | ModuleId::HASH + | ModuleId::INSPECT ); if !name.is_builtin() || should_include_builtin { @@ -5563,7 +5525,8 @@ fn make_specializations<'a>( ); let external_specializations_requested = procs.externals_we_need.clone(); - let (procedures, restored_procs_base) = procs.get_specialized_procs_without_rc(); + let (procedures, host_exposed_lambda_sets, restored_procs_base) = + procs.get_specialized_procs_without_rc(); // Turn `Bytes.Decode.IdentId(238)` into `Bytes.Decode.238`, we rely on this in mono tests mono_env.home.register_debug_idents(mono_env.ident_ids); @@ -5579,6 +5542,7 @@ fn make_specializations<'a>( layout_cache, procs_base: restored_procs_base, procedures, + host_exposed_lambda_sets, update_mode_ids, subs, expectations, diff --git a/crates/compiler/load_internal/src/lib.rs b/crates/compiler/load_internal/src/lib.rs index 6bdb0cabbd..24226d4c6b 100644 --- a/crates/compiler/load_internal/src/lib.rs +++ b/crates/compiler/load_internal/src/lib.rs @@ -25,5 +25,6 @@ pub const BUILTIN_MODULES: &[(ModuleId, &str)] = &[ (ModuleId::ENCODE, "Encode"), (ModuleId::DECODE, "Decode"), (ModuleId::HASH, "Hash"), + (ModuleId::INSPECT, "Inspect"), (ModuleId::JSON, "TotallyNotJson"), ]; diff --git a/crates/compiler/load_internal/src/module.rs b/crates/compiler/load_internal/src/module.rs index a84b60cb29..089c22a409 100644 --- a/crates/compiler/load_internal/src/module.rs +++ b/crates/compiler/load_internal/src/module.rs @@ -11,7 +11,7 @@ use roc_module::ident::Ident; use roc_module::symbol::{ IdentIds, IdentIdsByModule, Interns, ModuleId, PQModuleName, PackageQualified, Symbol, }; -use roc_mono::ir::{GlueLayouts, LambdaSetId, Proc, ProcLayout, ProcsBase}; +use roc_mono::ir::{GlueLayouts, HostExposedLambdaSets, LambdaSetId, Proc, ProcLayout, ProcsBase}; use roc_mono::layout::{LayoutCache, STLayoutInterner}; use roc_parse::ast::{CommentOrNewline, Defs, TypeAnnotation, ValueDef}; use roc_parse::header::{HeaderType, PackageName}; @@ -167,6 +167,7 @@ pub struct MonomorphizedModule<'a> { pub can_problems: MutMap>, pub type_problems: MutMap>, pub procedures: MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>, + pub host_exposed_lambda_sets: HostExposedLambdaSets<'a>, pub toplevel_expects: ToplevelExpects, pub entry_point: EntryPoint<'a>, pub exposed_to_host: ExposedToHost, diff --git a/crates/compiler/load_internal/src/module_cache.rs b/crates/compiler/load_internal/src/module_cache.rs index ec2bea79f7..299528bf66 100644 --- a/crates/compiler/load_internal/src/module_cache.rs +++ b/crates/compiler/load_internal/src/module_cache.rs @@ -85,6 +85,7 @@ impl Default for ModuleCache<'_> { ENCODE, DECODE, HASH, + INSPECT, JSON, } diff --git a/crates/compiler/load_internal/tests/fixtures/build/interface_with_deps/AStar.roc b/crates/compiler/load_internal/tests/fixtures/build/interface_with_deps/AStar.roc index 6cfa12bbb8..b9b44ddbd6 100644 --- a/crates/compiler/load_internal/tests/fixtures/build/interface_with_deps/AStar.roc +++ b/crates/compiler/load_internal/tests/fixtures/build/interface_with_deps/AStar.roc @@ -13,7 +13,7 @@ Model position : } -initialModel : position -> Model position | position has Hash & Eq +initialModel : position -> Model position where position implements Hash & Eq initialModel = \start -> { evaluated : Set.empty {} , openSet : Set.single start @@ -22,7 +22,7 @@ initialModel = \start -> } -cheapestOpen : (position -> F64), Model position -> Result position [KeyNotFound] | position has Hash & Eq +cheapestOpen : (position -> F64), Model position -> Result position [KeyNotFound] where position implements Hash & Eq cheapestOpen = \costFunction, model -> folder = \resSmallestSoFar, position -> @@ -47,7 +47,7 @@ cheapestOpen = \costFunction, model -> -reconstructPath : Dict position position, position -> List position | position has Hash & Eq +reconstructPath : Dict position position, position -> List position where position implements Hash & Eq reconstructPath = \cameFrom, goal -> when Dict.get cameFrom goal is Err KeyNotFound -> @@ -56,7 +56,7 @@ reconstructPath = \cameFrom, goal -> Ok next -> List.append (reconstructPath cameFrom next) goal -updateCost : position, position, Model position -> Model position | position has Hash & Eq +updateCost : position, position, Model position -> Model position where position implements Hash & Eq updateCost = \current, neighbour, model -> newCameFrom = Dict.insert model.cameFrom neighbour current @@ -80,12 +80,12 @@ updateCost = \current, neighbour, model -> model -findPath : { costFunction: (position, position -> F64), moveFunction: (position -> Set position), start : position, end : position } -> Result (List position) [KeyNotFound] | position has Hash & Eq +findPath : { costFunction: (position, position -> F64), moveFunction: (position -> Set position), start : position, end : position } -> Result (List position) [KeyNotFound] where position implements Hash & Eq findPath = \{ costFunction, moveFunction, start, end } -> astar costFunction moveFunction end (initialModel start) -astar : (position, position -> F64), (position -> Set position), position, Model position -> [Err [KeyNotFound], Ok (List position)] | position has Hash & Eq +astar : (position, position -> F64), (position -> Set position), position, Model position -> [Err [KeyNotFound], Ok (List position)] where position implements Hash & Eq astar = \costFn, moveFn, goal, model -> when cheapestOpen (\position -> costFn goal position) model is Err _ -> diff --git a/crates/compiler/load_internal/tests/test_load.rs b/crates/compiler/load_internal/tests/test_load.rs index c52ee7a674..79fd91e950 100644 --- a/crates/compiler/load_internal/tests/test_load.rs +++ b/crates/compiler/load_internal/tests/test_load.rs @@ -514,12 +514,12 @@ fn load_astar() { expect_types( loaded_module, hashmap! { - "findPath" => "{ costFunction : position, position -> F64, end : position, moveFunction : position -> Set position, start : position } -> Result (List position) [KeyNotFound] | position has Hash & Eq", - "initialModel" => "position -> Model position | position has Hash & Eq", - "reconstructPath" => "Dict position position, position -> List position | position has Hash & Eq", - "updateCost" => "position, position, Model position -> Model position | position has Hash & Eq", - "cheapestOpen" => "(position -> F64), Model position -> Result position [KeyNotFound] | position has Hash & Eq", - "astar" => "(position, position -> F64), (position -> Set position), position, Model position -> [Err [KeyNotFound], Ok (List position)] | position has Hash & Eq", + "findPath" => "{ costFunction : position, position -> F64, end : position, moveFunction : position -> Set position, start : position } -> Result (List position) [KeyNotFound] where position implements Hash & Eq", + "initialModel" => "position -> Model position where position implements Hash & Eq", + "reconstructPath" => "Dict position position, position -> List position where position implements Hash & Eq", + "updateCost" => "position, position, Model position -> Model position where position implements Hash & Eq", + "cheapestOpen" => "(position -> F64), Model position -> Result position [KeyNotFound] where position implements Hash & Eq", + "astar" => "(position, position -> F64), (position -> Set position), position, Model position -> [Err [KeyNotFound], Ok (List position)] where position implements Hash & Eq", }, ); } @@ -940,8 +940,8 @@ fn issue_2863_module_type_does_not_exist() { Did you mean one of these? Decoding - Result Dict + Result DecodeError " ) diff --git a/crates/compiler/module/src/ident.rs b/crates/compiler/module/src/ident.rs index 6265698b22..558846915b 100644 --- a/crates/compiler/module/src/ident.rs +++ b/crates/compiler/module/src/ident.rs @@ -113,6 +113,7 @@ impl ModuleName { pub const ENCODE: &'static str = "Encode"; pub const DECODE: &'static str = "Decode"; pub const HASH: &'static str = "Hash"; + pub const INSPECT: &'static str = "Inspect"; pub const JSON: &'static str = "TotallyNotJson"; pub fn as_str(&self) -> &str { diff --git a/crates/compiler/module/src/symbol.rs b/crates/compiler/module/src/symbol.rs index 868a7fb7f2..bf147bc0b3 100644 --- a/crates/compiler/module/src/symbol.rs +++ b/crates/compiler/module/src/symbol.rs @@ -1431,6 +1431,7 @@ define_builtins! { 80 LIST_ITER_HELP: "iterHelp" 81 LIST_RELEASE_EXCESS_CAPACITY: "releaseExcessCapacity" 82 LIST_UPDATE: "update" + 83 LIST_WALK_WITH_INDEX: "walkWithIndex" } 7 RESULT: "Result" => { 0 RESULT_RESULT: "Result" exposed_type=true // the Result.Result type alias @@ -1588,9 +1589,49 @@ define_builtins! { 20 HASH_HASH_LIST: "hashList" 21 HASH_HASH_UNORDERED: "hashUnordered" } - 14 JSON: "TotallyNotJson" => { + 14 INSPECT: "Inspect" => { + 0 INSPECT_INSPECT_ABILITY: "Inspect" exposed_type=true + 1 INSPECT_INSPECTOR: "Inspector" exposed_type=true + 2 INSPECT_INSPECT_FORMATTER: "InspectFormatter" exposed_type=true + 3 INSPECT_ELEM_WALKER: "ElemWalker" exposed_type=true + 4 INSPECT_KEY_VAL_WALKER: "KeyValWalker" exposed_type=true + 5 INSPECT_INSPECT: "inspect" + 6 INSPECT_INIT: "init" + 7 INSPECT_LIST: "list" + 8 INSPECT_SET: "set" + 9 INSPECT_DICT: "dict" + 10 INSPECT_TAG: "tag" + 11 INSPECT_TUPLE: "tuple" + 12 INSPECT_RECORD: "record" + 13 INSPECT_BOOL: "bool" + 14 INSPECT_STR: "str" + 15 INSPECT_OPAQUE: "opaque" + 16 INSPECT_U8: "u8" + 17 INSPECT_I8: "i8" + 18 INSPECT_U16: "u16" + 19 INSPECT_I16: "i16" + 20 INSPECT_U32: "u32" + 21 INSPECT_I32: "i32" + 22 INSPECT_U64: "u64" + 23 INSPECT_I64: "i64" + 24 INSPECT_U128: "u128" + 25 INSPECT_I128: "i128" + 26 INSPECT_F32: "f32" + 27 INSPECT_F64: "f64" + 28 INSPECT_DEC: "dec" + 29 INSPECT_CUSTOM: "custom" + 30 INSPECT_APPLY: "apply" + 31 INSPECT_TO_INSPECTOR: "toInspector" + } + 15 JSON: "TotallyNotJson" => { 0 JSON_JSON: "TotallyNotJson" + 1 JSON_FIELD_NAME_MAPPING: "FieldNameMapping" + 2 JSON_NUMBER_STATE: "NumberState" + 3 JSON_STRING_STATE: "StringState" + 4 JSON_ARRAY_OPENING_STATE: "ArrayOpeningState" + 5 JSON_ARRAY_CLOSING_STATE: "ArrayClosingState" + 6 JSON_OBJECT_STATE: "ObjectState" } - num_modules: 15 // Keep this count up to date by hand! (TODO: see the mut_map! macro for how we could determine this count correctly in the macro) + num_modules: 16 // Keep this count up to date by hand! (TODO: see the mut_map! macro for how we could determine this count correctly in the macro) } diff --git a/crates/compiler/mono/src/code_gen_help/mod.rs b/crates/compiler/mono/src/code_gen_help/mod.rs index f0587fa70d..9e29a126c0 100644 --- a/crates/compiler/mono/src/code_gen_help/mod.rs +++ b/crates/compiler/mono/src/code_gen_help/mod.rs @@ -6,8 +6,8 @@ use roc_module::symbol::{IdentIds, ModuleId, Symbol}; use roc_target::TargetInfo; use crate::ir::{ - BranchInfo, Call, CallSpecId, CallType, Expr, HostExposedLayouts, JoinPointId, Literal, - ModifyRc, PassedFunction, Proc, ProcLayout, SelfRecursive, Stmt, UpdateModeId, + BranchInfo, Call, CallSpecId, CallType, Expr, JoinPointId, Literal, ModifyRc, PassedFunction, + Proc, ProcLayout, SelfRecursive, Stmt, UpdateModeId, }; use crate::layout::{ Builtin, InLayout, LambdaName, Layout, LayoutInterner, LayoutRepr, LayoutWrapper, Niche, @@ -452,7 +452,6 @@ impl<'a> CodeGenHelp<'a> { closure_data_layout: None, ret_layout, is_self_recursive: SelfRecursive::NotSelfRecursive, - host_exposed_layouts: HostExposedLayouts::NotHostExposed, is_erased: false, }); @@ -772,7 +771,6 @@ impl<'a> CallerProc<'a> { closure_data_layout: None, ret_layout: Layout::UNIT, is_self_recursive: SelfRecursive::NotSelfRecursive, - host_exposed_layouts: HostExposedLayouts::NotHostExposed, is_erased: false, }; @@ -888,10 +886,6 @@ pub fn test_helper<'a>( closure_data_layout: None, ret_layout: output_layout, is_self_recursive: main_proc.is_self_recursive, - host_exposed_layouts: HostExposedLayouts::HostExposed { - rigids: Default::default(), - aliases: Default::default(), - }, is_erased: false, } } diff --git a/crates/compiler/mono/src/ir.rs b/crates/compiler/mono/src/ir.rs index 284dd2d588..4d4bfdb2a3 100644 --- a/crates/compiler/mono/src/ir.rs +++ b/crates/compiler/mono/src/ir.rs @@ -307,7 +307,6 @@ pub struct Proc<'a> { pub closure_data_layout: Option>, pub ret_layout: InLayout<'a>, pub is_self_recursive: SelfRecursive, - pub host_exposed_layouts: HostExposedLayouts<'a>, pub is_erased: bool, } @@ -320,15 +319,6 @@ pub struct HostExposedLambdaSet<'a> { pub raw_function_layout: RawFunctionLayout<'a>, } -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum HostExposedLayouts<'a> { - NotHostExposed, - HostExposed { - rigids: BumpMap>, - aliases: BumpMap>, - }, -} - #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum SelfRecursive { NotSelfRecursive, @@ -905,12 +895,16 @@ impl<'a> SpecializationStack<'a> { } } +pub type HostExposedLambdaSets<'a> = + std::vec::Vec<(LambdaName<'a>, Symbol, HostExposedLambdaSet<'a>)>; + #[derive(Clone, Debug)] pub struct Procs<'a> { pub partial_procs: PartialProcs<'a>, ability_member_aliases: AbilityAliases, pending_specializations: PendingSpecializations<'a>, specialized: Specialized<'a>, + host_exposed_lambda_sets: HostExposedLambdaSets<'a>, pub runtime_errors: BumpMap, pub externals_we_need: BumpMap>, symbol_specializations: SymbolSpecializations<'a>, @@ -930,6 +924,7 @@ impl<'a> Procs<'a> { specialized: Specialized::default(), runtime_errors: BumpMap::new_in(arena), externals_we_need: BumpMap::new_in(arena), + host_exposed_lambda_sets: std::vec::Vec::new(), symbol_specializations: Default::default(), specialization_stack: SpecializationStack(Vec::with_capacity_in(16, arena)), @@ -995,7 +990,11 @@ impl<'a> Procs<'a> { pub fn get_specialized_procs_without_rc( self, - ) -> (MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>, ProcsBase<'a>) { + ) -> ( + MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>, + HostExposedLambdaSets<'a>, + ProcsBase<'a>, + ) { let mut specialized_procs = MutMap::with_capacity_and_hasher(self.specialized.len(), default_hasher()); @@ -1013,7 +1012,11 @@ impl<'a> Procs<'a> { imported_module_thunks: self.imported_module_thunks, }; - (specialized_procs, restored_procs_base) + ( + specialized_procs, + self.host_exposed_lambda_sets, + restored_procs_base, + ) } // TODO trim these down @@ -3062,16 +3065,14 @@ fn specialize_host_specializations<'a>( let offset_variable = StorageSubs::merge_into(store, env.subs); - for (symbol, from_app, opt_from_platform) in it { + for (lambda_name, from_app, opt_from_platform) in it { let from_app = offset_variable(from_app); - let index = specialize_external_help(env, procs, layout_cache, symbol, from_app); + let index = specialize_external_help(env, procs, layout_cache, lambda_name, from_app); let Some(from_platform) = opt_from_platform else { continue }; // now run the lambda set numbering scheme - let mut layout_env = - layout::Env::from_components(layout_cache, env.subs, env.arena, env.target_info); - let hels = find_lambda_sets(&mut layout_env, from_platform); + let hels = find_lambda_sets(env.arena, env.subs, from_platform); // now unify let mut unify_env = roc_unify::Env::new( @@ -3097,12 +3098,18 @@ fn specialize_host_specializations<'a>( } } - let mut aliases = BumpMap::default(); - - for (id, _, raw_function_layout) in hels { + for (var, id) in hels { let symbol = env.unique_symbol(); let lambda_name = LambdaName::no_niche(symbol); + let mut layout_env = + layout::Env::from_components(layout_cache, env.subs, env.arena, env.target_info); + let lambda_set = env.subs.get_lambda_set(var); + let raw_function_layout = + RawFunctionLayout::from_var(&mut layout_env, lambda_set.ambient_function) + .value() + .unwrap(); + let (key, (top_level, proc)) = generate_host_exposed_function( env, procs, @@ -3122,20 +3129,10 @@ fn specialize_host_specializations<'a>( raw_function_layout, }; - aliases.insert(key, hels); - } + let in_progress = &mut procs.specialized.procedures[index.0]; + let InProgressProc::Done(proc) = in_progress else { unreachable!() }; - let in_progress = &mut procs.specialized.procedures[index.0]; - let InProgressProc::Done(proc) = in_progress else { unreachable!() }; - - match &mut proc.host_exposed_layouts { - HostExposedLayouts::HostExposed { aliases: old, .. } => old.extend(aliases), - hep @ HostExposedLayouts::NotHostExposed => { - *hep = HostExposedLayouts::HostExposed { - aliases, - rigids: Default::default(), - }; - } + procs.host_exposed_lambda_sets.push((proc.name, key, hels)); } } } @@ -3302,7 +3299,6 @@ fn generate_runtime_error_function<'a>( closure_data_layout: None, ret_layout, is_self_recursive: SelfRecursive::NotSelfRecursive, - host_exposed_layouts: HostExposedLayouts::NotHostExposed, is_erased, } } @@ -3398,7 +3394,6 @@ fn generate_host_exposed_function<'a>( closure_data_layout: None, ret_layout: result, is_self_recursive: SelfRecursive::NotSelfRecursive, - host_exposed_layouts: HostExposedLayouts::NotHostExposed, is_erased: false, }; @@ -3463,7 +3458,6 @@ fn generate_host_exposed_lambda_set<'a>( closure_data_layout: None, ret_layout: return_layout, is_self_recursive: SelfRecursive::NotSelfRecursive, - host_exposed_layouts: HostExposedLayouts::NotHostExposed, is_erased: false, }; @@ -3527,9 +3521,6 @@ fn specialize_proc_help<'a>( let body = partial_proc.body.clone(); let body_var = partial_proc.body_var; - // host-exposed functions are tagged on later - let host_exposed_layouts = HostExposedLayouts::NotHostExposed; - let mut specialized_body = from_can(env, body_var, body, procs, layout_cache); let specialized_proc = match specialized { @@ -3561,7 +3552,6 @@ fn specialize_proc_help<'a>( closure_data_layout: Some(closure_data_layout), ret_layout, is_self_recursive: recursivity, - host_exposed_layouts, is_erased, } } @@ -3764,7 +3754,6 @@ fn specialize_proc_help<'a>( closure_data_layout, ret_layout, is_self_recursive: recursivity, - host_exposed_layouts, is_erased, } } @@ -3976,7 +3965,7 @@ fn build_specialized_proc<'a>( } } Ordering::Less => panic!( - "more argument symbols than arguments (according to the layout) for {proc_name:?}" + "more argument symbols than arguments (according to the layout) for {proc_name:?}. Pattern symbols: {:?}\n\nPattern layouts: {:?}", pattern_symbols, pattern_layouts_len, ), } } @@ -10001,16 +9990,17 @@ impl LambdaSetId { } } -fn find_lambda_sets<'a>( - env: &mut crate::layout::Env<'a, '_>, +pub fn find_lambda_sets( + arena: &Bump, + subs: &Subs, initial: Variable, -) -> Vec<'a, (LambdaSetId, Variable, RawFunctionLayout<'a>)> { - let mut stack = bumpalo::collections::Vec::new_in(env.arena); +) -> MutMap { + let mut stack = bumpalo::collections::Vec::new_in(arena); // ignore the lambda set of top-level functions - match env.subs.get_without_compacting(initial).content { + match subs.get_without_compacting(initial).content { Content::Structure(FlatType::Func(arguments, _, result)) => { - let arguments = &env.subs.variables[arguments.indices()]; + let arguments = &subs.variables[arguments.indices()]; stack.extend(arguments.iter().copied()); stack.push(result); @@ -10020,24 +10010,10 @@ fn find_lambda_sets<'a>( } } - let lambda_set_variables = find_lambda_sets_help(env.subs, stack); - let mut answer = - bumpalo::collections::Vec::with_capacity_in(lambda_set_variables.len(), env.arena); - - for (variable, lambda_set_id) in lambda_set_variables { - let lambda_set = env.subs.get_lambda_set(variable); - let raw_function_layout = RawFunctionLayout::from_var(env, lambda_set.ambient_function) - .value() - .unwrap(); - - let key = (lambda_set_id, variable, raw_function_layout); - answer.push(key); - } - - answer + find_lambda_sets_help(subs, stack) } -pub fn find_lambda_sets_help( +fn find_lambda_sets_help( subs: &Subs, mut stack: Vec<'_, Variable>, ) -> MutMap { @@ -10337,7 +10313,6 @@ where closure_data_layout: None, ret_layout: *field, is_self_recursive: SelfRecursive::NotSelfRecursive, - host_exposed_layouts: HostExposedLayouts::NotHostExposed, is_erased: false, }; @@ -10433,7 +10408,6 @@ where closure_data_layout: None, ret_layout: *field, is_self_recursive: SelfRecursive::NotSelfRecursive, - host_exposed_layouts: HostExposedLayouts::NotHostExposed, is_erased: false, }; diff --git a/crates/compiler/mono/src/layout.rs b/crates/compiler/mono/src/layout.rs index a1a31a0e94..ba76bff506 100644 --- a/crates/compiler/mono/src/layout.rs +++ b/crates/compiler/mono/src/layout.rs @@ -580,7 +580,9 @@ impl<'a> RawFunctionLayout<'a> { cacheable(Ok(Self::ZeroArgumentThunk(Layout::usize(env.target_info)))) } - Alias(symbol, _, _, _) if symbol.is_builtin() => { + Alias(Symbol::INSPECT_ELEM_WALKER | Symbol::INSPECT_KEY_VAL_WALKER, _, var, _) => Self::from_var(env, var), + + Alias(symbol, _, var, _) if symbol.is_builtin() => { Layout::new_help(env, var, content).then(Self::ZeroArgumentThunk) } diff --git a/crates/compiler/mono/src/tail_recursion.rs b/crates/compiler/mono/src/tail_recursion.rs index cd3346401e..bd419d02c5 100644 --- a/crates/compiler/mono/src/tail_recursion.rs +++ b/crates/compiler/mono/src/tail_recursion.rs @@ -802,7 +802,6 @@ impl<'a> TrmcEnv<'a> { closure_data_layout: proc.closure_data_layout, ret_layout: proc.ret_layout, is_self_recursive: SelfRecursive::NotSelfRecursive, - host_exposed_layouts: proc.host_exposed_layouts.clone(), is_erased: proc.is_erased, } } diff --git a/crates/compiler/parse/src/ast.rs b/crates/compiler/parse/src/ast.rs index f1d6729c33..2cafc3522a 100644 --- a/crates/compiler/parse/src/ast.rs +++ b/crates/compiler/parse/src/ast.rs @@ -38,6 +38,13 @@ impl<'a, T> Spaced<'a, T> { } } } + + pub fn item(&self) -> &T { + match self { + Spaced::Item(answer) => answer, + Spaced::SpaceBefore(next, _spaces) | Spaced::SpaceAfter(next, _spaces) => next.item(), + } + } } impl<'a, T: Debug> Debug for Spaced<'a, T> { @@ -357,15 +364,15 @@ impl<'a> TypeHeader<'a> { } } -/// The `has` keyword associated with ability definitions. +/// The `implements` keyword associated with ability definitions. #[derive(Debug, Clone, Copy, PartialEq)] -pub enum Has<'a> { - Has, - SpaceBefore(&'a Has<'a>, &'a [CommentOrNewline<'a>]), - SpaceAfter(&'a Has<'a>, &'a [CommentOrNewline<'a>]), +pub enum Implements<'a> { + Implements, + SpaceBefore(&'a Implements<'a>, &'a [CommentOrNewline<'a>]), + SpaceAfter(&'a Implements<'a>, &'a [CommentOrNewline<'a>]), } -/// An ability demand is a value defining the ability; for example `hash : a -> U64 | a has Hash` +/// An ability demand is a value defining the ability; for example `hash : a -> U64 where a implements Hash` /// for a `Hash` ability. #[derive(Debug, Clone, Copy, PartialEq)] pub struct AbilityMember<'a> { @@ -394,15 +401,15 @@ pub enum TypeDef<'a> { Opaque { header: TypeHeader<'a>, typ: Loc>, - derived: Option>>, + derived: Option>>, }, /// An ability definition. E.g. - /// Hash has - /// hash : a -> U64 | a has Hash + /// Hash implements + /// hash : a -> U64 where a implements Hash Ability { header: TypeHeader<'a>, - loc_has: Loc>, + loc_implements: Loc>, members: &'a [AbilityMember<'a>], }, } @@ -538,54 +545,54 @@ impl<'a> Defs<'a> { pub type AbilityName<'a> = Loc>; #[derive(Debug, Copy, Clone, PartialEq)] -pub struct HasClause<'a> { +pub struct ImplementsClause<'a> { pub var: Loc>, pub abilities: &'a [AbilityName<'a>], } #[derive(Debug, Copy, Clone, PartialEq)] -pub enum HasImpls<'a> { +pub enum AbilityImpls<'a> { // `{ eq: myEq }` - HasImpls(Collection<'a, Loc>>>), + AbilityImpls(Collection<'a, Loc>>>), // We preserve this for the formatter; canonicalization ignores it. - SpaceBefore(&'a HasImpls<'a>, &'a [CommentOrNewline<'a>]), - SpaceAfter(&'a HasImpls<'a>, &'a [CommentOrNewline<'a>]), + SpaceBefore(&'a AbilityImpls<'a>, &'a [CommentOrNewline<'a>]), + SpaceAfter(&'a AbilityImpls<'a>, &'a [CommentOrNewline<'a>]), } /// `Eq` or `Eq { eq: myEq }` #[derive(Debug, Copy, Clone, PartialEq)] -pub enum HasAbility<'a> { - HasAbility { +pub enum ImplementsAbility<'a> { + ImplementsAbility { /// Should be a zero-argument `Apply` or an error; we'll check this in canonicalization ability: Loc>, - impls: Option>>, + impls: Option>>, }, // We preserve this for the formatter; canonicalization ignores it. - SpaceBefore(&'a HasAbility<'a>, &'a [CommentOrNewline<'a>]), - SpaceAfter(&'a HasAbility<'a>, &'a [CommentOrNewline<'a>]), + SpaceBefore(&'a ImplementsAbility<'a>, &'a [CommentOrNewline<'a>]), + SpaceAfter(&'a ImplementsAbility<'a>, &'a [CommentOrNewline<'a>]), } #[derive(Debug, Copy, Clone, PartialEq)] -pub enum HasAbilities<'a> { - /// `has [Eq { eq: myEq }, Hash]` - Has(Collection<'a, Loc>>), +pub enum ImplementsAbilities<'a> { + /// `implements [Eq { eq: myEq }, Hash]` + Implements(Collection<'a, Loc>>), // We preserve this for the formatter; canonicalization ignores it. - SpaceBefore(&'a HasAbilities<'a>, &'a [CommentOrNewline<'a>]), - SpaceAfter(&'a HasAbilities<'a>, &'a [CommentOrNewline<'a>]), + SpaceBefore(&'a ImplementsAbilities<'a>, &'a [CommentOrNewline<'a>]), + SpaceAfter(&'a ImplementsAbilities<'a>, &'a [CommentOrNewline<'a>]), } -impl HasAbilities<'_> { - pub fn collection(&self) -> &Collection> { +impl ImplementsAbilities<'_> { + pub fn collection(&self) -> &Collection> { let mut it = self; loop { match it { Self::SpaceBefore(inner, _) | Self::SpaceAfter(inner, _) => { it = inner; } - Self::Has(collection) => return collection, + Self::Implements(collection) => return collection, } } } @@ -641,8 +648,8 @@ pub enum TypeAnnotation<'a> { /// The `*` type variable, e.g. in (List *) Wildcard, - /// A "where" clause demanding abilities designated by a `|`, e.g. `a -> U64 | a has Hash` - Where(&'a Loc>, &'a [Loc>]), + /// A "where" clause demanding abilities designated by a `where`, e.g. `a -> U64 where a implements Hash` + Where(&'a Loc>, &'a [Loc>]), // We preserve this for the formatter; canonicalization ignores it. SpaceBefore(&'a TypeAnnotation<'a>, &'a [CommentOrNewline<'a>]), @@ -1245,39 +1252,39 @@ impl<'a> Spaceable<'a> for Tag<'a> { } } -impl<'a> Spaceable<'a> for Has<'a> { +impl<'a> Spaceable<'a> for Implements<'a> { fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { - Has::SpaceBefore(self, spaces) + Implements::SpaceBefore(self, spaces) } fn after(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { - Has::SpaceAfter(self, spaces) + Implements::SpaceAfter(self, spaces) } } -impl<'a> Spaceable<'a> for HasImpls<'a> { +impl<'a> Spaceable<'a> for AbilityImpls<'a> { fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { - HasImpls::SpaceBefore(self, spaces) + AbilityImpls::SpaceBefore(self, spaces) } fn after(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { - HasImpls::SpaceAfter(self, spaces) + AbilityImpls::SpaceAfter(self, spaces) } } -impl<'a> Spaceable<'a> for HasAbility<'a> { +impl<'a> Spaceable<'a> for ImplementsAbility<'a> { fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { - HasAbility::SpaceBefore(self, spaces) + ImplementsAbility::SpaceBefore(self, spaces) } fn after(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { - HasAbility::SpaceAfter(self, spaces) + ImplementsAbility::SpaceAfter(self, spaces) } } -impl<'a> Spaceable<'a> for HasAbilities<'a> { +impl<'a> Spaceable<'a> for ImplementsAbilities<'a> { fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { - HasAbilities::SpaceBefore(self, spaces) + ImplementsAbilities::SpaceBefore(self, spaces) } fn after(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { - HasAbilities::SpaceAfter(self, spaces) + ImplementsAbilities::SpaceAfter(self, spaces) } } @@ -1368,7 +1375,7 @@ impl_extract_spaces!(Pattern); impl_extract_spaces!(Tag); impl_extract_spaces!(AssignedField); impl_extract_spaces!(TypeAnnotation); -impl_extract_spaces!(HasAbility); +impl_extract_spaces!(ImplementsAbility); impl<'a, T: Copy> ExtractSpaces<'a> for Spaced<'a, T> { type Item = T; @@ -1422,43 +1429,43 @@ impl<'a, T: Copy> ExtractSpaces<'a> for Spaced<'a, T> { } } -impl<'a> ExtractSpaces<'a> for HasImpls<'a> { +impl<'a> ExtractSpaces<'a> for AbilityImpls<'a> { type Item = Collection<'a, Loc>>>; fn extract_spaces(&self) -> Spaces<'a, Self::Item> { match self { - HasImpls::HasImpls(inner) => Spaces { + AbilityImpls::AbilityImpls(inner) => Spaces { before: &[], item: *inner, after: &[], }, - HasImpls::SpaceBefore(item, before) => match item { - HasImpls::HasImpls(inner) => Spaces { + AbilityImpls::SpaceBefore(item, before) => match item { + AbilityImpls::AbilityImpls(inner) => Spaces { before, item: *inner, after: &[], }, - HasImpls::SpaceBefore(_, _) => todo!(), - HasImpls::SpaceAfter(HasImpls::HasImpls(inner), after) => Spaces { + AbilityImpls::SpaceBefore(_, _) => todo!(), + AbilityImpls::SpaceAfter(AbilityImpls::AbilityImpls(inner), after) => Spaces { before, item: *inner, after, }, - HasImpls::SpaceAfter(_, _) => todo!(), + AbilityImpls::SpaceAfter(_, _) => todo!(), }, - HasImpls::SpaceAfter(item, after) => match item { - HasImpls::HasImpls(inner) => Spaces { + AbilityImpls::SpaceAfter(item, after) => match item { + AbilityImpls::AbilityImpls(inner) => Spaces { before: &[], item: *inner, after, }, - HasImpls::SpaceBefore(HasImpls::HasImpls(inner), before) => Spaces { + AbilityImpls::SpaceBefore(AbilityImpls::AbilityImpls(inner), before) => Spaces { before, item: *inner, after, }, - HasImpls::SpaceBefore(_, _) => todo!(), - HasImpls::SpaceAfter(_, _) => todo!(), + AbilityImpls::SpaceBefore(_, _) => todo!(), + AbilityImpls::SpaceAfter(_, _) => todo!(), }, } } @@ -1681,11 +1688,11 @@ impl<'a> Malformed for TypeDef<'a> { } => header.is_malformed() || typ.is_malformed() || derived.is_malformed(), TypeDef::Ability { header, - loc_has, + loc_implements, members, } => { header.is_malformed() - || loc_has.is_malformed() + || loc_implements.is_malformed() || members.iter().any(|member| member.is_malformed()) } } @@ -1698,42 +1705,48 @@ impl<'a> Malformed for AbilityMember<'a> { } } -impl<'a> Malformed for Has<'a> { +impl<'a> Malformed for Implements<'a> { fn is_malformed(&self) -> bool { match self { - Has::Has => false, - Has::SpaceBefore(has, _) | Has::SpaceAfter(has, _) => has.is_malformed(), + Implements::Implements => false, + Implements::SpaceBefore(has, _) | Implements::SpaceAfter(has, _) => has.is_malformed(), } } } -impl<'a> Malformed for HasAbility<'a> { +impl<'a> Malformed for ImplementsAbility<'a> { fn is_malformed(&self) -> bool { match self { - HasAbility::HasAbility { ability, impls } => { + ImplementsAbility::ImplementsAbility { ability, impls } => { ability.is_malformed() || impls.iter().any(|impl_| impl_.is_malformed()) } - HasAbility::SpaceBefore(has, _) | HasAbility::SpaceAfter(has, _) => has.is_malformed(), - } - } -} - -impl<'a> Malformed for HasAbilities<'a> { - fn is_malformed(&self) -> bool { - match self { - HasAbilities::Has(abilities) => abilities.iter().any(|ability| ability.is_malformed()), - HasAbilities::SpaceBefore(has, _) | HasAbilities::SpaceAfter(has, _) => { + ImplementsAbility::SpaceBefore(has, _) | ImplementsAbility::SpaceAfter(has, _) => { has.is_malformed() } } } } -impl<'a> Malformed for HasImpls<'a> { +impl<'a> Malformed for ImplementsAbilities<'a> { fn is_malformed(&self) -> bool { match self { - HasImpls::HasImpls(impls) => impls.iter().any(|ability| ability.is_malformed()), - HasImpls::SpaceBefore(has, _) | HasImpls::SpaceAfter(has, _) => has.is_malformed(), + ImplementsAbilities::Implements(abilities) => { + abilities.iter().any(|ability| ability.is_malformed()) + } + ImplementsAbilities::SpaceBefore(has, _) | ImplementsAbilities::SpaceAfter(has, _) => { + has.is_malformed() + } + } + } +} + +impl<'a> Malformed for AbilityImpls<'a> { + fn is_malformed(&self) -> bool { + match self { + AbilityImpls::AbilityImpls(impls) => impls.iter().any(|ability| ability.is_malformed()), + AbilityImpls::SpaceBefore(has, _) | AbilityImpls::SpaceAfter(has, _) => { + has.is_malformed() + } } } } @@ -1823,7 +1836,7 @@ impl<'a> Malformed for Tag<'a> { } } -impl<'a> Malformed for HasClause<'a> { +impl<'a> Malformed for ImplementsClause<'a> { fn is_malformed(&self) -> bool { self.abilities.iter().any(|ability| ability.is_malformed()) } diff --git a/crates/compiler/parse/src/expr.rs b/crates/compiler/parse/src/expr.rs index e77bd8a216..ed216452e3 100644 --- a/crates/compiler/parse/src/expr.rs +++ b/crates/compiler/parse/src/expr.rs @@ -1,6 +1,7 @@ use crate::ast::{ - AssignedField, Collection, CommentOrNewline, Defs, Expr, ExtractSpaces, Has, HasAbilities, - Pattern, RecordBuilderField, Spaceable, Spaces, TypeAnnotation, TypeDef, TypeHeader, ValueDef, + AssignedField, Collection, CommentOrNewline, Defs, Expr, ExtractSpaces, Implements, + ImplementsAbilities, Pattern, RecordBuilderField, Spaceable, Spaces, TypeAnnotation, TypeDef, + TypeHeader, ValueDef, }; use crate::blankspace::{ space0_after_e, space0_around_e_no_after_indent_check, space0_around_ee, space0_before_e, @@ -14,7 +15,7 @@ use crate::parser::{ word2, EClosure, EExpect, EExpr, EIf, EInParens, EList, ENumber, EPattern, ERecord, EString, EType, EWhen, Either, ParseResult, Parser, }; -use crate::pattern::{closure_param, loc_has_parser}; +use crate::pattern::{closure_param, loc_implements_parser}; use crate::state::State; use crate::string_literal::StrLikeLiteral; use crate::type_annotation; @@ -616,14 +617,14 @@ pub fn parse_single_def<'a>( }; if let Some((name, name_region, args)) = opt_tag_and_args { - if let Ok((_, loc_has, state)) = - loc_has_parser().parse(arena, state.clone(), min_indent) + if let Ok((_, loc_implements, state)) = + loc_implements_parser().parse(arena, state.clone(), min_indent) { let (_, (type_def, def_region), state) = finish_parsing_ability_def_help( min_indent, Loc::at(name_region, name), args, - loc_has, + loc_implements, arena, state, )?; @@ -1063,8 +1064,14 @@ fn alias_signature_with_space_before<'a>() -> impl Parser<'a, Loc( -) -> impl Parser<'a, (Loc>, Option>>), EExpr<'a>> { +fn opaque_signature_with_space_before<'a>() -> impl Parser< + 'a, + ( + Loc>, + Option>>, + ), + EExpr<'a>, +> { and!( specialize( EExpr::Type, @@ -1075,7 +1082,7 @@ fn opaque_signature_with_space_before<'a>( ), optional(backtrackable(specialize( EExpr::Type, - space0_before_e(type_annotation::has_abilities(), EType::TIndentStart,), + space0_before_e(type_annotation::implements_abilities(), EType::TIndentStart,), ))) ) } @@ -1279,7 +1286,7 @@ mod ability { Exact(u32), } - /// Parses an ability demand like `hash : a -> U64 | a has Hash`, in the context of a larger + /// Parses an ability demand like `hash : a -> U64 where a implements Hash`, in the context of a larger /// ability definition. /// This is basically the same as parsing a free-floating annotation, but with stricter rules. pub fn parse_demand<'a>( @@ -1363,7 +1370,7 @@ fn finish_parsing_ability_def_help<'a>( start_column: u32, name: Loc<&'a str>, args: &'a [Loc>], - loc_has: Loc>, + loc_implements: Loc>, arena: &'a Bump, state: State<'a>, ) -> ParseResult<'a, (TypeDef<'a>, Region), EExpr<'a>> { @@ -1401,7 +1408,7 @@ fn finish_parsing_ability_def_help<'a>( let def_region = Region::span_across(&name.region, &demands.last().unwrap().typ.region); let type_def = TypeDef::Ability { header: TypeHeader { name, vars: args }, - loc_has, + loc_implements, members: demands.into_bump_slice(), }; @@ -1634,13 +1641,13 @@ fn parse_expr_end<'a>( value: Expr::Var { module_name: "", - ident: "has", + ident: crate::keyword::IMPLEMENTS, }, .. }, state, )) if matches!(expr_state.expr.value, Expr::Tag(..)) => { - // This is an ability definition, `Ability arg1 ... has ...`. + // This is an ability definition, `Ability arg1 ... implements ...`. let name = expr_state.expr.map_owned(|e| match e { Expr::Tag(name) => name, @@ -1661,13 +1668,13 @@ fn parse_expr_end<'a>( } } - // Attach any spaces to the `has` keyword + // Attach any spaces to the `implements` keyword let has = if !expr_state.spaces_after.is_empty() { arena - .alloc(Has::Has) + .alloc(Implements::Implements) .with_spaces_before(expr_state.spaces_after, has.region) } else { - Loc::at(has.region, Has::Has) + Loc::at(has.region, Implements::Implements) }; let args = arguments.into_bump_slice(); diff --git a/crates/compiler/parse/src/keyword.rs b/crates/compiler/parse/src/keyword.rs index e20ce81870..102fd43a7c 100644 --- a/crates/compiler/parse/src/keyword.rs +++ b/crates/compiler/parse/src/keyword.rs @@ -1,3 +1,4 @@ +// These keywords are valid in expressions pub const IF: &str = "if"; pub const THEN: &str = "then"; pub const ELSE: &str = "else"; @@ -9,4 +10,10 @@ pub const EXPECT: &str = "expect"; pub const EXPECT_FX: &str = "expect-fx"; pub const CRASH: &str = "crash"; -pub const KEYWORDS: [&str; 10] = [IF, THEN, ELSE, WHEN, AS, IS, DBG, EXPECT, EXPECT_FX, CRASH]; +// These keywords are valid in types +pub const IMPLEMENTS: &str = "implements"; +pub const WHERE: &str = "where"; + +pub const KEYWORDS: [&str; 11] = [ + IF, THEN, ELSE, WHEN, AS, IS, DBG, EXPECT, EXPECT_FX, CRASH, WHERE, +]; diff --git a/crates/compiler/parse/src/parser.rs b/crates/compiler/parse/src/parser.rs index 385dea9f40..1caef42867 100644 --- a/crates/compiler/parse/src/parser.rs +++ b/crates/compiler/parse/src/parser.rs @@ -599,7 +599,7 @@ pub enum EType<'a> { TEnd(Position), TFunctionArgument(Position), TWhereBar(Position), - THasClause(Position), + TImplementsClause(Position), TAbilityImpl(ETypeAbilityImpl<'a>, Position), /// TIndentStart(Position), @@ -1524,6 +1524,23 @@ where } } +pub fn word<'a, ToError, E>(word: &'static str, to_error: ToError) -> impl Parser<'a, (), E> +where + ToError: Fn(Position) -> E, + E: 'a, +{ + debug_assert!(!word.contains('\n')); + + move |_arena: &'a Bump, state: State<'a>, _min_indent: u32| { + if state.bytes().starts_with(word.as_bytes()) { + let state = state.advance(word.len()); + Ok((MadeProgress, (), state)) + } else { + Err((NoProgress, to_error(state.pos()))) + } + } +} + pub fn word1<'a, ToError, E>(word: u8, to_error: ToError) -> impl Parser<'a, (), E> where ToError: Fn(Position) -> E, diff --git a/crates/compiler/parse/src/pattern.rs b/crates/compiler/parse/src/pattern.rs index 0854eb04be..19afb719b9 100644 --- a/crates/compiler/parse/src/pattern.rs +++ b/crates/compiler/parse/src/pattern.rs @@ -1,4 +1,4 @@ -use crate::ast::{Has, Pattern, PatternAs, Spaceable}; +use crate::ast::{Implements, Pattern, PatternAs, Spaceable}; use crate::blankspace::{space0_e, spaces, spaces_before}; use crate::ident::{lowercase_ident, parse_ident, Accessor, Ident}; use crate::keyword; @@ -116,7 +116,7 @@ fn loc_tag_pattern_args_help<'a>() -> impl Parser<'a, Vec<'a, Loc>>, zero_or_more!(loc_tag_pattern_arg(false)) } -/// Like `loc_tag_pattern_args_help`, but stops if a "has" keyword is seen (indicating an ability). +/// Like `loc_tag_pattern_args_help`, but stops if a "implements" keyword is seen (indicating an ability). fn loc_type_def_tag_pattern_args_help<'a>( ) -> impl Parser<'a, Vec<'a, Loc>>, EPattern<'a>> { zero_or_more!(loc_tag_pattern_arg(true)) @@ -138,7 +138,7 @@ fn loc_tag_pattern_arg<'a>( let Loc { region, value } = loc_pat; - if stop_on_has_kw && matches!(value, Pattern::Identifier("has")) { + if stop_on_has_kw && matches!(value, Pattern::Identifier(crate::keyword::IMPLEMENTS)) { Err((NoProgress, EPattern::End(original_state.pos()))) } else { Ok(( @@ -154,12 +154,19 @@ fn loc_tag_pattern_arg<'a>( } } -pub fn loc_has_parser<'a>() -> impl Parser<'a, Loc>, EPattern<'a>> { +pub fn loc_implements_parser<'a>() -> impl Parser<'a, Loc>, EPattern<'a>> { then( loc_tag_pattern_arg(false), |_arena, state, progress, pattern| { - if matches!(pattern.value, Pattern::Identifier("has")) { - Ok((progress, Loc::at(pattern.region, Has::Has), state)) + if matches!( + pattern.value, + Pattern::Identifier(crate::keyword::IMPLEMENTS) + ) { + Ok(( + progress, + Loc::at(pattern.region, Implements::Implements), + state, + )) } else { Err((progress, EPattern::End(state.pos()))) } diff --git a/crates/compiler/parse/src/type_annotation.rs b/crates/compiler/parse/src/type_annotation.rs index e2fe0e78d5..7f5d85205b 100644 --- a/crates/compiler/parse/src/type_annotation.rs +++ b/crates/compiler/parse/src/type_annotation.rs @@ -1,6 +1,6 @@ use crate::ast::{ - AssignedField, CommentOrNewline, Expr, HasAbilities, HasAbility, HasClause, HasImpls, Pattern, - Spaceable, Spaced, Tag, TypeAnnotation, TypeHeader, + AbilityImpls, AssignedField, CommentOrNewline, Expr, ImplementsAbilities, ImplementsAbility, + ImplementsClause, Pattern, Spaceable, Spaced, Tag, TypeAnnotation, TypeHeader, }; use crate::blankspace::{ space0_around_ee, space0_before_e, space0_before_optional_after, space0_e, @@ -12,7 +12,7 @@ use crate::parser::{ absolute_column_min_indent, increment_min_indent, then, ERecord, ETypeAbilityImpl, }; use crate::parser::{ - allocated, backtrackable, fail, optional, specialize, specialize_ref, word1, word2, word3, + allocated, backtrackable, fail, optional, specialize, specialize_ref, word, word1, word2, EType, ETypeApply, ETypeInParens, ETypeInlineAlias, ETypeRecord, ETypeTagUnion, Parser, Progress::{self, *}, }; @@ -426,7 +426,7 @@ fn ability_chain<'a>() -> impl Parser<'a, Vec<'a, Loc>>, ETyp EType::TIndentEnd, ), zero_or_more!(skip_first!( - word1(b'&', EType::THasClause), + word1(b'&', EType::TImplementsClause), space0_before_optional_after( specialize(EType::TApply, loc!(concrete_type())), EType::TIndentStart, @@ -444,9 +444,9 @@ fn ability_chain<'a>() -> impl Parser<'a, Vec<'a, Loc>>, ETyp ) } -fn has_clause<'a>() -> impl Parser<'a, Loc>, EType<'a>> { +fn implements_clause<'a>() -> impl Parser<'a, Loc>, EType<'a>> { map!( - // Suppose we are trying to parse "a has Hash" + // Suppose we are trying to parse "a implements Hash" and!( space0_around_ee( // Parse "a", with appropriate spaces @@ -458,8 +458,8 @@ fn has_clause<'a>() -> impl Parser<'a, Loc>, EType<'a>> { EType::TIndentEnd ), skip_first!( - // Parse "has"; we don't care about this keyword - word3(b'h', b'a', b's', EType::THasClause), + // Parse "implements"; we don't care about this keyword + word(crate::keyword::IMPLEMENTS, EType::TImplementsClause), // Parse "Hash & ..."; this may be qualified from another module like "Hash.Hash" absolute_column_min_indent(ability_chain()) ) @@ -470,30 +470,34 @@ fn has_clause<'a>() -> impl Parser<'a, Loc>, EType<'a>> { &abilities.last().unwrap().region, ); let region = Region::span_across(&var.region, &abilities_region); - let has_clause = HasClause { + let implements_clause = ImplementsClause { var, abilities: abilities.into_bump_slice(), }; - Loc::at(region, has_clause) + Loc::at(region, implements_clause) } ) } -/// Parse a chain of `has` clauses, e.g. " | a has Hash, b has Eq". -/// Returns the clauses and spaces before the starting "|", if there were any. -fn has_clause_chain<'a>( -) -> impl Parser<'a, (&'a [CommentOrNewline<'a>], &'a [Loc>]), EType<'a>> { +/// Parse a chain of `implements` clauses, e.g. " where a implements Hash, b implements Eq". +/// Returns the clauses and spaces before the starting "where", if there were any. +fn implements_clause_chain<'a>( +) -> impl Parser<'a, (&'a [CommentOrNewline<'a>], &'a [Loc>]), EType<'a>> { move |arena, state: State<'a>, min_indent: u32| { - let (_, (spaces_before, ()), state) = - and!(space0_e(EType::TIndentStart), word1(b'|', EType::TWhereBar)) - .parse(arena, state, min_indent)?; + let (_, (spaces_before, ()), state) = and!( + space0_e(EType::TIndentStart), + word(crate::keyword::WHERE, EType::TWhereBar) + ) + .parse(arena, state, min_indent)?; // Parse the first clause (there must be one), then the rest - let (_, first_clause, state) = has_clause().parse(arena, state, min_indent)?; + let (_, first_clause, state) = implements_clause().parse(arena, state, min_indent)?; - let (_, mut clauses, state) = - zero_or_more!(skip_first!(word1(b',', EType::THasClause), has_clause())) - .parse(arena, state, min_indent)?; + let (_, mut clauses, state) = zero_or_more!(skip_first!( + word1(b',', EType::TImplementsClause), + implements_clause() + )) + .parse(arena, state, min_indent)?; // Usually the number of clauses shouldn't be too large, so this is okay clauses.insert(0, first_clause); @@ -506,30 +510,30 @@ fn has_clause_chain<'a>( } } -/// Parse a has-abilities clause, e.g. `has [Eq, Hash]`. -pub fn has_abilities<'a>() -> impl Parser<'a, Loc>, EType<'a>> { +/// Parse a implements-abilities clause, e.g. `implements [Eq, Hash]`. +pub fn implements_abilities<'a>() -> impl Parser<'a, Loc>, EType<'a>> { increment_min_indent(skip_first!( - // Parse "has"; we don't care about this keyword - word3(b'h', b'a', b's', EType::THasClause), + // Parse "implements"; we don't care about this keyword + word(crate::keyword::IMPLEMENTS, EType::TImplementsClause), // Parse "Hash"; this may be qualified from another module like "Hash.Hash" space0_before_e( loc!(map!( collection_trailing_sep_e!( word1(b'[', EType::TStart), - loc!(parse_has_ability()), + loc!(parse_implements_ability()), word1(b',', EType::TEnd), word1(b']', EType::TEnd), - HasAbility::SpaceBefore + ImplementsAbility::SpaceBefore ), - HasAbilities::Has + ImplementsAbilities::Implements )), EType::TIndentEnd, ) )) } -fn parse_has_ability<'a>() -> impl Parser<'a, HasAbility<'a>, EType<'a>> { - increment_min_indent(record!(HasAbility::HasAbility { +fn parse_implements_ability<'a>() -> impl Parser<'a, ImplementsAbility<'a>, EType<'a>> { + increment_min_indent(record!(ImplementsAbility::ImplementsAbility { ability: loc!(specialize(EType::TApply, concrete_type())), impls: optional(backtrackable(space0_before_e( loc!(map!( @@ -543,7 +547,7 @@ fn parse_has_ability<'a>() -> impl Parser<'a, HasAbility<'a>, EType<'a>> { AssignedField::SpaceBefore ) ), - HasImpls::HasImpls + AbilityImpls::AbilityImpls )), EType::TIndentEnd ))) @@ -642,12 +646,13 @@ fn expression<'a>( // Finally, try to parse a where clause if there is one. // The where clause must be at least as deep as where the type annotation started. - match has_clause_chain().parse(arena, state.clone(), min_indent) { - Ok((where_progress, (spaces_before, has_chain), state)) => { - let region = Region::span_across(&annot.region, &has_chain.last().unwrap().region); + match implements_clause_chain().parse(arena, state.clone(), min_indent) { + Ok((where_progress, (spaces_before, implements_chain), state)) => { + let region = + Region::span_across(&annot.region, &implements_chain.last().unwrap().region); let type_annot = if !spaces_before.is_empty() { - // We're transforming the spaces_before the '|' - // into spaces_after the thing before the '|' + // We're transforming the spaces_before the 'where' + // into spaces_after the thing before the 'where' let spaced = arena .alloc(annot.value) .with_spaces_after(spaces_before, annot.region); @@ -655,7 +660,7 @@ fn expression<'a>( } else { &*arena.alloc(annot) }; - let where_annot = TypeAnnotation::Where(type_annot, has_chain); + let where_annot = TypeAnnotation::Where(type_annot, implements_chain); Ok(( where_progress.or(progress), Loc::at(region, where_annot), @@ -724,7 +729,7 @@ fn parse_type_variable<'a>( min_indent, ) { Ok((_, name, state)) => { - if name == "has" && stop_at_surface_has { + if name == crate::keyword::IMPLEMENTS && stop_at_surface_has { Err((NoProgress, EType::TEnd(state.pos()))) } else { let answer = TypeAnnotation::BoundVariable(name); diff --git a/crates/compiler/problem/src/can.rs b/crates/compiler/problem/src/can.rs index 2a9d97f31c..e6904133e5 100644 --- a/crates/compiler/problem/src/can.rs +++ b/crates/compiler/problem/src/can.rs @@ -117,17 +117,17 @@ pub enum Problem { name: Symbol, variables_region: Region, }, - HasClauseIsNotAbility { + ImplementsClauseIsNotAbility { region: Region, }, - IllegalHasClause { + IllegalImplementsClause { region: Region, }, - DuplicateHasAbility { + DuplicateImplementsAbility { ability: Symbol, region: Region, }, - AbilityMemberMissingHasClause { + AbilityMemberMissingImplementsClause { member: Symbol, ability: Symbol, region: Region, @@ -135,7 +135,7 @@ pub enum Problem { AbilityMemberMultipleBoundVars { member: Symbol, ability: Symbol, - span_has_clauses: Region, + span_implements_clauses: Region, bound_var_names: Vec, }, AbilityNotOnToplevel { @@ -245,10 +245,10 @@ impl Problem { Problem::NestedDatatype { .. } => RuntimeError, Problem::InvalidExtensionType { .. } => RuntimeError, Problem::AbilityHasTypeVariables { .. } => RuntimeError, - Problem::HasClauseIsNotAbility { .. } => RuntimeError, - Problem::IllegalHasClause { .. } => RuntimeError, - Problem::DuplicateHasAbility { .. } => Warning, - Problem::AbilityMemberMissingHasClause { .. } => RuntimeError, + Problem::ImplementsClauseIsNotAbility { .. } => RuntimeError, + Problem::IllegalImplementsClause { .. } => RuntimeError, + Problem::DuplicateImplementsAbility { .. } => Warning, + Problem::AbilityMemberMissingImplementsClause { .. } => RuntimeError, Problem::AbilityMemberMultipleBoundVars { .. } => RuntimeError, Problem::AbilityNotOnToplevel { .. } => RuntimeError, // Ideally, could be compiled Problem::AbilityUsedAsType(_, _, _) => RuntimeError, @@ -379,12 +379,12 @@ impl Problem { variables_region: region, .. } - | Problem::HasClauseIsNotAbility { region } - | Problem::IllegalHasClause { region } - | Problem::DuplicateHasAbility { region, .. } - | Problem::AbilityMemberMissingHasClause { region, .. } + | Problem::ImplementsClauseIsNotAbility { region } + | Problem::IllegalImplementsClause { region } + | Problem::DuplicateImplementsAbility { region, .. } + | Problem::AbilityMemberMissingImplementsClause { region, .. } | Problem::AbilityMemberMultipleBoundVars { - span_has_clauses: region, + span_implements_clauses: region, .. } | Problem::AbilityNotOnToplevel { region } diff --git a/crates/compiler/solve/src/ability.rs b/crates/compiler/solve/src/ability.rs index 05294440bc..83272ccd0f 100644 --- a/crates/compiler/solve/src/ability.rs +++ b/crates/compiler/solve/src/ability.rs @@ -741,7 +741,7 @@ trait DerivableVisitor { ) { // TODO: currently, just we suppose the presence of a flex var may // include more or less things which we can derive. But, we should - // instead recurse here, and add a `t ~ u | u has Decode` constraint as needed. + // instead recurse here, and add a `t ~ u where u implements Decode` constraint as needed. stack.push(ext); } } diff --git a/crates/compiler/solve/src/to_var.rs b/crates/compiler/solve/src/to_var.rs index 102aa63dac..86e4dc9cfa 100644 --- a/crates/compiler/solve/src/to_var.rs +++ b/crates/compiler/solve/src/to_var.rs @@ -142,8 +142,7 @@ impl RegisterVariable { TypeTag::EmptyTagUnion => Direct(Variable::EMPTY_TAG_UNION), TypeTag::DelayedAlias { shared } | TypeTag::StructuralAlias { shared, .. } - | TypeTag::OpaqueAlias { shared, .. } - | TypeTag::HostExposedAlias { shared, .. } => { + | TypeTag::OpaqueAlias { shared, .. } => { let AliasShared { symbol, .. } = types[shared]; if let Some(reserved) = Variable::get_reserved(symbol) { let direct_var = if rank.is_generalized() { @@ -752,92 +751,6 @@ pub(crate) fn type_to_var_help( env.register_with_known_var(destination, rank, content) } - HostExposedAlias { - shared, - actual_type: alias_type, - actual_variable: actual_var, - } => { - let AliasShared { - symbol, - type_argument_abilities: _, - type_argument_regions: _, - lambda_set_variables, - infer_ext_in_output_variables: _, // TODO - } = types[shared]; - - let type_arguments = types.get_type_arguments(typ_index); - - let alias_variables = { - let length = type_arguments.len() + lambda_set_variables.len(); - let new_variables = VariableSubsSlice::reserve_into_subs(env.subs, length); - - for (target_index, arg_type) in - (new_variables.indices()).zip(type_arguments.into_iter()) - { - let copy_var = helper!(arg_type); - env.subs.variables[target_index] = copy_var; - } - let it = (new_variables.indices().skip(type_arguments.len())) - .zip(lambda_set_variables.into_iter()); - for (target_index, ls) in it { - // We MUST do this now, otherwise when linking the ambient function during - // instantiation of the real var, there will be nothing to link against. - let copy_var = type_to_var_help( - env, - rank, - problems, - abilities_store, - obligation_cache, - arena, - aliases, - types, - ls, - true, - ); - env.subs.variables[target_index] = copy_var; - } - - AliasVariables { - variables_start: new_variables.start, - type_variables_len: type_arguments.len() as _, - lambda_set_variables_len: lambda_set_variables.len() as _, - all_variables_len: length as _, - } - }; - - // cannot use helper! here because this variable may be involved in unification below - let alias_variable = type_to_var_help( - env, - rank, - problems, - abilities_store, - obligation_cache, - arena, - aliases, - types, - alias_type, - false, - ); - // TODO(opaques): I think host-exposed aliases should always be structural - // (when does it make sense to give a host an opaque type?) - let content = Content::Alias( - symbol, - alias_variables, - alias_variable, - AliasKind::Structural, - ); - let result = env.register_with_known_var(destination, rank, content); - - // We only want to unify the actual_var with the alias once - // if it's already redirected (and therefore, redundant) - // don't do it again - if !env.subs.redundant(actual_var) { - let descriptor = env.subs.get(result); - env.subs.union(result, actual_var, descriptor); - } - - result - } Error => { let content = Content::Error; diff --git a/crates/compiler/solve/tests/solve_expr.rs b/crates/compiler/solve/tests/solve_expr.rs index f24a78c6c4..bc80f81be4 100644 --- a/crates/compiler/solve/tests/solve_expr.rs +++ b/crates/compiler/solve/tests/solve_expr.rs @@ -3146,7 +3146,7 @@ mod solve_expr { Dict.insert "# ), - "Dict k v, k, v -> Dict k v | k has Hash & Eq", + "Dict k v, k, v -> Dict k v where k implements Hash & Eq", ); } @@ -3407,7 +3407,7 @@ mod solve_expr { infer_eq_without_problem( indoc!( r#" - reconstructPath : Dict position position, position -> List position | position has Hash & Eq + reconstructPath : Dict position position, position -> List position where position implements Hash & Eq reconstructPath = \cameFrom, goal -> when Dict.get cameFrom goal is Err KeyNotFound -> @@ -3419,7 +3419,7 @@ mod solve_expr { reconstructPath "# ), - "Dict position position, position -> List position | position has Hash & Eq", + "Dict position position, position -> List position where position implements Hash & Eq", ); } @@ -3454,7 +3454,7 @@ mod solve_expr { Model position : { openSet : Set position } - cheapestOpen : Model position -> Result position [KeyNotFound] | position has Hash & Eq + cheapestOpen : Model position -> Result position [KeyNotFound] where position implements Hash & Eq cheapestOpen = \model -> folder = \resSmallestSoFar, position -> @@ -3469,14 +3469,14 @@ mod solve_expr { Set.walk model.openSet (Ok { position: boom {}, cost: 0.0 }) folder |> Result.map (\x -> x.position) - astar : Model position -> Result position [KeyNotFound] | position has Hash & Eq + astar : Model position -> Result position [KeyNotFound] where position implements Hash & Eq astar = \model -> cheapestOpen model main = astar "# ), - "Model position -> Result position [KeyNotFound] | position has Hash & Eq", + "Model position -> Result position [KeyNotFound] where position implements Hash & Eq", ); } @@ -4118,7 +4118,7 @@ mod solve_expr { Key k : Num k - removeHelpEQGT : Key k, RBTree (Key k) v -> RBTree (Key k) v | k has Hash & Eq + removeHelpEQGT : Key k, RBTree (Key k) v -> RBTree (Key k) v where k implements Hash & Eq removeHelpEQGT = \targetKey, dict -> when dict is Node color key value left right -> @@ -4232,7 +4232,7 @@ mod solve_expr { _ -> Empty - removeHelp : Key k, RBTree (Key k) v -> RBTree (Key k) v | k has Hash & Eq + removeHelp : Key k, RBTree (Key k) v -> RBTree (Key k) v where k implements Hash & Eq removeHelp = \targetKey, dict -> when dict is Empty -> @@ -4320,7 +4320,7 @@ mod solve_expr { RBTree k v : [Node NodeColor k v (RBTree k v) (RBTree k v), Empty] - removeHelp : Num k, RBTree (Num k) v -> RBTree (Num k) v | k has Hash & Eq + removeHelp : Num k, RBTree (Num k) v -> RBTree (Num k) v where k implements Hash & Eq removeHelp = \targetKey, dict -> when dict is Empty -> @@ -4355,7 +4355,7 @@ mod solve_expr { removeHelpPrepEQGT : Key k, RBTree (Key k) v, NodeColor, (Key k), v, RBTree (Key k) v, RBTree (Key k) v -> RBTree (Key k) v - removeHelpEQGT : Key k, RBTree (Key k) v -> RBTree (Key k) v | k has Hash & Eq + removeHelpEQGT : Key k, RBTree (Key k) v -> RBTree (Key k) v where k implements Hash & Eq removeHelpEQGT = \targetKey, dict -> when dict is Node color key value left right -> diff --git a/crates/compiler/test_derive/src/decoding.rs b/crates/compiler/test_derive/src/decoding.rs index 14fe23abd1..edba290303 100644 --- a/crates/compiler/test_derive/src/decoding.rs +++ b/crates/compiler/test_derive/src/decoding.rs @@ -87,7 +87,7 @@ fn derivable_record_ext_flex_var() { fn derivable_record_ext_flex_able_var() { check_derivable( Decoder, - v!({ a: v!(STR), }a has Symbol::DECODE_DECODER ), + v!({ a: v!(STR), }a implements Symbol::DECODE_DECODER ), DeriveKey::Decoder(FlatDecodableKey::Record(vec!["a".into()])), ); } @@ -106,8 +106,8 @@ fn list() { derive_test(Decoder, v!(Symbol::LIST_LIST v!(STR)), |golden| { assert_snapshot!(golden, @r###" # derived for List Str - # Decoder (List val) fmt | fmt has DecoderFormatting, val has Decoding - # List U8, fmt -[[custom(3)]]-> { rest : List U8, result : [Err [TooShort], Ok (List val)] } | fmt has DecoderFormatting, val has Decoding + # Decoder (List val) fmt where fmt implements DecoderFormatting, val implements Decoding + # List U8, fmt -[[custom(3)]]-> { rest : List U8, result : [Err [TooShort], Ok (List val)] } where fmt implements DecoderFormatting, val implements Decoding # Specialization lambda sets: # @<1>: [[custom(3)]] #Derived.decoder_list = @@ -124,8 +124,8 @@ fn record_2_fields() { derive_test(Decoder, v!({first: v!(STR), second: v!(STR),}), |golden| { assert_snapshot!(golden, @r###" # derived for { first : Str, second : Str } - # Decoder { first : val, second : val1 } fmt | fmt has DecoderFormatting, val has Decoding, val1 has Decoding - # List U8, fmt -[[custom(22)]]-> { rest : List U8, result : [Err [TooShort], Ok { first : val, second : val1 }] } | fmt has DecoderFormatting, val has Decoding, val1 has Decoding + # Decoder { first : val, second : val1 } fmt where fmt implements DecoderFormatting, val implements Decoding, val1 implements Decoding + # List U8, fmt -[[custom(22)]]-> { rest : List U8, result : [Err [TooShort], Ok { first : val, second : val1 }] } where fmt implements DecoderFormatting, val implements Decoding, val1 implements Decoding # Specialization lambda sets: # @<1>: [[custom(22)]] #Derived.decoder_{first,second} = @@ -181,8 +181,8 @@ fn tuple_2_fields() { derive_test(Decoder, v!((v!(STR), v!(U8),)), |golden| { assert_snapshot!(golden, @r###" # derived for ( Str, U8 )* - # Decoder ( val, val1 )* fmt | fmt has DecoderFormatting, val has Decoding, val1 has Decoding - # List U8, fmt -[[custom(22)]]-> { rest : List U8, result : [Err [TooShort], Ok ( val, val1 )a] } | fmt has DecoderFormatting, val has Decoding, val1 has Decoding + # Decoder ( val, val1 )* fmt where fmt implements DecoderFormatting, val implements Decoding, val1 implements Decoding + # List U8, fmt -[[custom(22)]]-> { rest : List U8, result : [Err [TooShort], Ok ( val, val1 )a] } where fmt implements DecoderFormatting, val implements Decoding, val1 implements Decoding # Specialization lambda sets: # @<1>: [[custom(22)]] #Derived.decoder_(arity:2) = diff --git a/crates/compiler/test_derive/src/encoding.rs b/crates/compiler/test_derive/src/encoding.rs index ab45eb7751..8274062059 100644 --- a/crates/compiler/test_derive/src/encoding.rs +++ b/crates/compiler/test_derive/src/encoding.rs @@ -139,7 +139,7 @@ fn derivable_record_ext_flex_var() { fn derivable_record_ext_flex_able_var() { check_derivable( ToEncoder, - v!({ a: v!(STR), }a has Symbol::ENCODE_TO_ENCODER), + v!({ a: v!(STR), }a implements Symbol::ENCODE_TO_ENCODER), DeriveKey::ToEncoder(FlatEncodableKey::Record(vec!["a".into()])), ); } @@ -166,7 +166,7 @@ fn derivable_tag_ext_flex_var() { fn derivable_tag_ext_flex_able_var() { check_derivable( ToEncoder, - v!([ A v!(STR) ]a has Symbol::ENCODE_TO_ENCODER), + v!([ A v!(STR) ]a implements Symbol::ENCODE_TO_ENCODER), DeriveKey::ToEncoder(FlatEncodableKey::TagUnion(vec![("A".into(), 1)])), ); } @@ -188,8 +188,8 @@ fn empty_record() { derive_test(ToEncoder, v!(EMPTY_RECORD), |golden| { assert_snapshot!(golden, @r###" # derived for {} - # {} -[[toEncoder_{}(0)]]-> Encoder fmt | fmt has EncoderFormatting - # {} -[[toEncoder_{}(0)]]-> (List U8, fmt -[[custom(2) {}]]-> List U8) | fmt has EncoderFormatting + # {} -[[toEncoder_{}(0)]]-> Encoder fmt where fmt implements EncoderFormatting + # {} -[[toEncoder_{}(0)]]-> (List U8, fmt -[[custom(2) {}]]-> List U8) where fmt implements EncoderFormatting # Specialization lambda sets: # @<1>: [[toEncoder_{}(0)]] # @<2>: [[custom(2) {}]] @@ -208,8 +208,8 @@ fn zero_field_record() { derive_test(ToEncoder, v!({}), |golden| { assert_snapshot!(golden, @r###" # derived for {} - # {} -[[toEncoder_{}(0)]]-> Encoder fmt | fmt has EncoderFormatting - # {} -[[toEncoder_{}(0)]]-> (List U8, fmt -[[custom(2) {}]]-> List U8) | fmt has EncoderFormatting + # {} -[[toEncoder_{}(0)]]-> Encoder fmt where fmt implements EncoderFormatting + # {} -[[toEncoder_{}(0)]]-> (List U8, fmt -[[custom(2) {}]]-> List U8) where fmt implements EncoderFormatting # Specialization lambda sets: # @<1>: [[toEncoder_{}(0)]] # @<2>: [[custom(2) {}]] @@ -228,11 +228,11 @@ fn one_field_record() { derive_test(ToEncoder, v!({ a: v!(U8), }), |golden| { assert_snapshot!(golden, @r###" # derived for { a : U8 } - # { a : val } -[[toEncoder_{a}(0)]]-> Encoder fmt | fmt has EncoderFormatting, val has Encoding - # { a : val } -[[toEncoder_{a}(0)]]-> (List U8, fmt -[[custom(2) { a : val }]]-> List U8) | fmt has EncoderFormatting, val has Encoding + # { a : val } -[[toEncoder_{a}(0)]]-> Encoder fmt where fmt implements EncoderFormatting, val implements Encoding + # { a : val } -[[toEncoder_{a}(0)]]-> (List U8, fmt -[[custom(2) { a : val }]]-> List U8) where fmt implements EncoderFormatting, val implements Encoding # Specialization lambda sets: # @<1>: [[toEncoder_{a}(0)]] - # @<2>: [[custom(2) { a : val }]] | val has Encoding + # @<2>: [[custom(2) { a : val }]] where val implements Encoding #Derived.toEncoder_{a} = \#Derived.rcd -> custom @@ -251,11 +251,11 @@ fn two_field_record() { derive_test(ToEncoder, v!({ a: v!(U8), b: v!(STR), }), |golden| { assert_snapshot!(golden, @r###" # derived for { a : U8, b : Str } - # { a : val, b : val1 } -[[toEncoder_{a,b}(0)]]-> Encoder fmt | fmt has EncoderFormatting, val has Encoding, val1 has Encoding - # { a : val, b : val1 } -[[toEncoder_{a,b}(0)]]-> (List U8, fmt -[[custom(2) { a : val, b : val1 }]]-> List U8) | fmt has EncoderFormatting, val has Encoding, val1 has Encoding + # { a : val, b : val1 } -[[toEncoder_{a,b}(0)]]-> Encoder fmt where fmt implements EncoderFormatting, val implements Encoding, val1 implements Encoding + # { a : val, b : val1 } -[[toEncoder_{a,b}(0)]]-> (List U8, fmt -[[custom(2) { a : val, b : val1 }]]-> List U8) where fmt implements EncoderFormatting, val implements Encoding, val1 implements Encoding # Specialization lambda sets: # @<1>: [[toEncoder_{a,b}(0)]] - # @<2>: [[custom(2) { a : val, b : val1 }]] | val has Encoding, val1 has Encoding + # @<2>: [[custom(2) { a : val, b : val1 }]] where val implements Encoding, val1 implements Encoding #Derived.toEncoder_{a,b} = \#Derived.rcd -> custom @@ -278,11 +278,11 @@ fn two_field_tuple() { derive_test(ToEncoder, v!((v!(U8), v!(STR),)), |golden| { assert_snapshot!(golden, @r###" # derived for ( U8, Str )* - # ( val, val1 )* -[[toEncoder_(arity:2)(0)]]-> Encoder fmt | fmt has EncoderFormatting, val has Encoding, val1 has Encoding - # ( val, val1 )a -[[toEncoder_(arity:2)(0)]]-> (List U8, fmt -[[custom(2) ( val, val1 )a]]-> List U8) | fmt has EncoderFormatting, val has Encoding, val1 has Encoding + # ( val, val1 )* -[[toEncoder_(arity:2)(0)]]-> Encoder fmt where fmt implements EncoderFormatting, val implements Encoding, val1 implements Encoding + # ( val, val1 )a -[[toEncoder_(arity:2)(0)]]-> (List U8, fmt -[[custom(2) ( val, val1 )a]]-> List U8) where fmt implements EncoderFormatting, val implements Encoding, val1 implements Encoding # Specialization lambda sets: # @<1>: [[toEncoder_(arity:2)(0)]] - # @<2>: [[custom(2) ( val, val1 )*]] | val has Encoding, val1 has Encoding + # @<2>: [[custom(2) ( val, val1 )*]] where val implements Encoding, val1 implements Encoding #Derived.toEncoder_(arity:2) = \#Derived.tup -> custom @@ -314,8 +314,8 @@ fn tag_one_label_zero_args() { derive_test(ToEncoder, v!([A]), |golden| { assert_snapshot!(golden, @r###" # derived for [A] - # [A] -[[toEncoder_[A 0](0)]]-> Encoder fmt | fmt has EncoderFormatting - # [A] -[[toEncoder_[A 0](0)]]-> (List U8, fmt -[[custom(2) [A]]]-> List U8) | fmt has EncoderFormatting + # [A] -[[toEncoder_[A 0](0)]]-> Encoder fmt where fmt implements EncoderFormatting + # [A] -[[toEncoder_[A 0](0)]]-> (List U8, fmt -[[custom(2) [A]]]-> List U8) where fmt implements EncoderFormatting # Specialization lambda sets: # @<1>: [[toEncoder_[A 0](0)]] # @<2>: [[custom(2) [A]]] @@ -338,11 +338,11 @@ fn tag_one_label_two_args() { derive_test(ToEncoder, v!([A v!(U8) v!(STR)]), |golden| { assert_snapshot!(golden, @r###" # derived for [A U8 Str] - # [A val val1] -[[toEncoder_[A 2](0)]]-> Encoder fmt | fmt has EncoderFormatting, val has Encoding, val1 has Encoding - # [A val val1] -[[toEncoder_[A 2](0)]]-> (List U8, fmt -[[custom(4) [A val val1]]]-> List U8) | fmt has EncoderFormatting, val has Encoding, val1 has Encoding + # [A val val1] -[[toEncoder_[A 2](0)]]-> Encoder fmt where fmt implements EncoderFormatting, val implements Encoding, val1 implements Encoding + # [A val val1] -[[toEncoder_[A 2](0)]]-> (List U8, fmt -[[custom(4) [A val val1]]]-> List U8) where fmt implements EncoderFormatting, val implements Encoding, val1 implements Encoding # Specialization lambda sets: # @<1>: [[toEncoder_[A 2](0)]] - # @<2>: [[custom(4) [A val val1]]] | val has Encoding, val1 has Encoding + # @<2>: [[custom(4) [A val val1]]] where val implements Encoding, val1 implements Encoding #Derived.toEncoder_[A 2] = \#Derived.tag -> custom @@ -366,11 +366,11 @@ fn tag_two_labels() { |golden| { assert_snapshot!(golden, @r###" # derived for [A U8 Str U16, B Str] - # [A val val1 val1, B val1] -[[toEncoder_[A 3,B 1](0)]]-> Encoder fmt | fmt has EncoderFormatting, val has Encoding, val1 has Encoding - # [A val val1 val1, B val1] -[[toEncoder_[A 3,B 1](0)]]-> (List U8, fmt -[[custom(6) [A val val1 val1, B val1]]]-> List U8) | fmt has EncoderFormatting, val has Encoding, val1 has Encoding + # [A val val1 val1, B val1] -[[toEncoder_[A 3,B 1](0)]]-> Encoder fmt where fmt implements EncoderFormatting, val implements Encoding, val1 implements Encoding + # [A val val1 val1, B val1] -[[toEncoder_[A 3,B 1](0)]]-> (List U8, fmt -[[custom(6) [A val val1 val1, B val1]]]-> List U8) where fmt implements EncoderFormatting, val implements Encoding, val1 implements Encoding # Specialization lambda sets: # @<1>: [[toEncoder_[A 3,B 1](0)]] - # @<2>: [[custom(6) [A val val1 val1, B val1]]] | val has Encoding, val1 has Encoding + # @<2>: [[custom(6) [A val val1 val1, B val1]]] where val implements Encoding, val1 implements Encoding #Derived.toEncoder_[A 3,B 1] = \#Derived.tag -> custom @@ -402,11 +402,11 @@ fn recursive_tag_union() { |golden| { assert_snapshot!(golden, @r###" # derived for [Cons U8 $rec, Nil] as $rec - # [Cons val val1, Nil] -[[toEncoder_[Cons 2,Nil 0](0)]]-> Encoder fmt | fmt has EncoderFormatting, val has Encoding, val1 has Encoding - # [Cons val val1, Nil] -[[toEncoder_[Cons 2,Nil 0](0)]]-> (List U8, fmt -[[custom(4) [Cons val val1, Nil]]]-> List U8) | fmt has EncoderFormatting, val has Encoding, val1 has Encoding + # [Cons val val1, Nil] -[[toEncoder_[Cons 2,Nil 0](0)]]-> Encoder fmt where fmt implements EncoderFormatting, val implements Encoding, val1 implements Encoding + # [Cons val val1, Nil] -[[toEncoder_[Cons 2,Nil 0](0)]]-> (List U8, fmt -[[custom(4) [Cons val val1, Nil]]]-> List U8) where fmt implements EncoderFormatting, val implements Encoding, val1 implements Encoding # Specialization lambda sets: # @<1>: [[toEncoder_[Cons 2,Nil 0](0)]] - # @<2>: [[custom(4) [Cons val val1, Nil]]] | val has Encoding, val1 has Encoding + # @<2>: [[custom(4) [Cons val val1, Nil]]] where val implements Encoding, val1 implements Encoding #Derived.toEncoder_[Cons 2,Nil 0] = \#Derived.tag -> custom @@ -429,11 +429,11 @@ fn list() { derive_test(ToEncoder, v!(Symbol::LIST_LIST v!(STR)), |golden| { assert_snapshot!(golden, @r###" # derived for List Str - # List val -[[toEncoder_list(0)]]-> Encoder fmt | fmt has EncoderFormatting, val has Encoding - # List val -[[toEncoder_list(0)]]-> (List U8, fmt -[[custom(4) (List val)]]-> List U8) | fmt has EncoderFormatting, val has Encoding + # List val -[[toEncoder_list(0)]]-> Encoder fmt where fmt implements EncoderFormatting, val implements Encoding + # List val -[[toEncoder_list(0)]]-> (List U8, fmt -[[custom(4) (List val)]]-> List U8) where fmt implements EncoderFormatting, val implements Encoding # Specialization lambda sets: # @<1>: [[toEncoder_list(0)]] - # @<2>: [[custom(4) (List val)]] | val has Encoding + # @<2>: [[custom(4) (List val)]] where val implements Encoding #Derived.toEncoder_list = \#Derived.lst -> custom diff --git a/crates/compiler/test_derive/src/hash.rs b/crates/compiler/test_derive/src/hash.rs index 4847f1044e..96a119199e 100644 --- a/crates/compiler/test_derive/src/hash.rs +++ b/crates/compiler/test_derive/src/hash.rs @@ -102,7 +102,7 @@ fn derivable_record_ext_flex_var() { fn derivable_record_ext_flex_able_var() { check_derivable( Hash, - v!({ a: v!(STR), }a has Symbol::DECODE_DECODER ), + v!({ a: v!(STR), }a implements Symbol::DECODE_DECODER ), DeriveKey::Hash(FlatHashKey::Record(vec!["a".into()])), ); } @@ -129,7 +129,7 @@ fn derivable_tag_ext_flex_var() { fn derivable_tag_ext_flex_able_var() { check_derivable( Hash, - v!([ A v!(STR) ]a has Symbol::ENCODE_TO_ENCODER), + v!([ A v!(STR) ]a implements Symbol::ENCODE_TO_ENCODER), DeriveKey::Hash(FlatHashKey::TagUnion(vec![("A".into(), 1)])), ); } @@ -151,8 +151,8 @@ fn empty_record() { derive_test(Hash, v!(EMPTY_RECORD), |golden| { assert_snapshot!(golden, @r###" # derived for {} - # hasher, {} -[[hash_{}(0)]]-> hasher | hasher has Hasher - # hasher, {} -[[hash_{}(0)]]-> hasher | hasher has Hasher + # hasher, {} -[[hash_{}(0)]]-> hasher where hasher implements Hasher + # hasher, {} -[[hash_{}(0)]]-> hasher where hasher implements Hasher # Specialization lambda sets: # @<1>: [[hash_{}(0)]] #Derived.hash_{} = \#Derived.hasher, #Derived.rcd -> #Derived.hasher @@ -166,8 +166,8 @@ fn zero_field_record() { derive_test(Hash, v!({}), |golden| { assert_snapshot!(golden, @r###" # derived for {} - # hasher, {} -[[hash_{}(0)]]-> hasher | hasher has Hasher - # hasher, {} -[[hash_{}(0)]]-> hasher | hasher has Hasher + # hasher, {} -[[hash_{}(0)]]-> hasher where hasher implements Hasher + # hasher, {} -[[hash_{}(0)]]-> hasher where hasher implements Hasher # Specialization lambda sets: # @<1>: [[hash_{}(0)]] #Derived.hash_{} = \#Derived.hasher, #Derived.rcd -> #Derived.hasher @@ -181,8 +181,8 @@ fn one_field_record() { derive_test(Hash, v!({ a: v!(U8), }), |golden| { assert_snapshot!(golden, @r###" # derived for { a : U8 } - # hasher, { a : a } -[[hash_{a}(0)]]-> hasher | a has Hash, hasher has Hasher - # hasher, { a : a } -[[hash_{a}(0)]]-> hasher | a has Hash, hasher has Hasher + # hasher, { a : a } -[[hash_{a}(0)]]-> hasher where a implements Hash, hasher implements Hasher + # hasher, { a : a } -[[hash_{a}(0)]]-> hasher where a implements Hash, hasher implements Hasher # Specialization lambda sets: # @<1>: [[hash_{a}(0)]] #Derived.hash_{a} = @@ -197,8 +197,8 @@ fn two_field_record() { derive_test(Hash, v!({ a: v!(U8), b: v!(STR), }), |golden| { assert_snapshot!(golden, @r###" # derived for { a : U8, b : Str } - # hasher, { a : a, b : a1 } -[[hash_{a,b}(0)]]-> hasher | a has Hash, a1 has Hash, hasher has Hasher - # hasher, { a : a, b : a1 } -[[hash_{a,b}(0)]]-> hasher | a has Hash, a1 has Hash, hasher has Hasher + # hasher, { a : a, b : a1 } -[[hash_{a,b}(0)]]-> hasher where a implements Hash, a1 implements Hash, hasher implements Hasher + # hasher, { a : a, b : a1 } -[[hash_{a,b}(0)]]-> hasher where a implements Hash, a1 implements Hash, hasher implements Hasher # Specialization lambda sets: # @<1>: [[hash_{a,b}(0)]] #Derived.hash_{a,b} = @@ -214,8 +214,8 @@ fn two_element_tuple() { derive_test(Hash, v!((v!(U8), v!(STR),)), |golden| { assert_snapshot!(golden, @r###" # derived for ( U8, Str )* - # hasher, ( a, a1 )* -[[hash_(arity:2)(0)]]-> hasher | a has Hash, a1 has Hash, hasher has Hasher - # hasher, ( a, a1 )* -[[hash_(arity:2)(0)]]-> hasher | a has Hash, a1 has Hash, hasher has Hasher + # hasher, ( a, a1 )* -[[hash_(arity:2)(0)]]-> hasher where a implements Hash, a1 implements Hash, hasher implements Hasher + # hasher, ( a, a1 )* -[[hash_(arity:2)(0)]]-> hasher where a implements Hash, a1 implements Hash, hasher implements Hasher # Specialization lambda sets: # @<1>: [[hash_(arity:2)(0)]] #Derived.hash_(arity:2) = @@ -231,8 +231,8 @@ fn tag_one_label_no_payloads() { derive_test(Hash, v!([A]), |golden| { assert_snapshot!(golden, @r###" # derived for [A] - # hasher, [A] -[[hash_[A 0](0)]]-> hasher | hasher has Hasher - # hasher, [A] -[[hash_[A 0](0)]]-> hasher | hasher has Hasher + # hasher, [A] -[[hash_[A 0](0)]]-> hasher where hasher implements Hasher + # hasher, [A] -[[hash_[A 0](0)]]-> hasher where hasher implements Hasher # Specialization lambda sets: # @<1>: [[hash_[A 0](0)]] #Derived.hash_[A 0] = \#Derived.hasher, A -> #Derived.hasher @@ -246,8 +246,8 @@ fn tag_one_label_newtype() { derive_test(Hash, v!([A v!(U8) v!(STR)]), |golden| { assert_snapshot!(golden, @r###" # derived for [A U8 Str] - # hasher, [A a a1] -[[hash_[A 2](0)]]-> hasher | a has Hash, a1 has Hash, hasher has Hasher - # hasher, [A a a1] -[[hash_[A 2](0)]]-> hasher | a has Hash, a1 has Hash, hasher has Hasher + # hasher, [A a a1] -[[hash_[A 2](0)]]-> hasher where a implements Hash, a1 implements Hash, hasher implements Hasher + # hasher, [A a a1] -[[hash_[A 2](0)]]-> hasher where a implements Hash, a1 implements Hash, hasher implements Hasher # Specialization lambda sets: # @<1>: [[hash_[A 2](0)]] #Derived.hash_[A 2] = @@ -263,8 +263,8 @@ fn tag_two_labels() { derive_test(Hash, v!([A v!(U8) v!(STR) v!(U16), B v!(STR)]), |golden| { assert_snapshot!(golden, @r###" # derived for [A U8 Str U16, B Str] - # a, [A a1 a2 a3, B a3] -[[hash_[A 3,B 1](0)]]-> a | a has Hasher, a1 has Hash, a2 has Hash, a3 has Hash - # a, [A a1 a2 a3, B a3] -[[hash_[A 3,B 1](0)]]-> a | a has Hasher, a1 has Hash, a2 has Hash, a3 has Hash + # a, [A a1 a2 a3, B a3] -[[hash_[A 3,B 1](0)]]-> a where a implements Hasher, a1 implements Hash, a2 implements Hash, a3 implements Hash + # a, [A a1 a2 a3, B a3] -[[hash_[A 3,B 1](0)]]-> a where a implements Hasher, a1 implements Hash, a2 implements Hash, a3 implements Hash # Specialization lambda sets: # @<1>: [[hash_[A 3,B 1](0)]] #Derived.hash_[A 3,B 1] = @@ -285,8 +285,8 @@ fn tag_two_labels_no_payloads() { derive_test(Hash, v!([A, B]), |golden| { assert_snapshot!(golden, @r###" # derived for [A, B] - # a, [A, B] -[[hash_[A 0,B 0](0)]]-> a | a has Hasher - # a, [A, B] -[[hash_[A 0,B 0](0)]]-> a | a has Hasher + # a, [A, B] -[[hash_[A 0,B 0](0)]]-> a where a implements Hasher + # a, [A, B] -[[hash_[A 0,B 0](0)]]-> a where a implements Hasher # Specialization lambda sets: # @<1>: [[hash_[A 0,B 0](0)]] #Derived.hash_[A 0,B 0] = @@ -304,8 +304,8 @@ fn recursive_tag_union() { derive_test(Hash, v!([Nil, Cons v!(U8) v!(^lst) ] as lst), |golden| { assert_snapshot!(golden, @r###" # derived for [Cons U8 $rec, Nil] as $rec - # a, [Cons a1 a2, Nil] -[[hash_[Cons 2,Nil 0](0)]]-> a | a has Hasher, a1 has Hash, a2 has Hash - # a, [Cons a1 a2, Nil] -[[hash_[Cons 2,Nil 0](0)]]-> a | a has Hasher, a1 has Hash, a2 has Hash + # a, [Cons a1 a2, Nil] -[[hash_[Cons 2,Nil 0](0)]]-> a where a implements Hasher, a1 implements Hash, a2 implements Hash + # a, [Cons a1 a2, Nil] -[[hash_[Cons 2,Nil 0](0)]]-> a where a implements Hasher, a1 implements Hash, a2 implements Hash # Specialization lambda sets: # @<1>: [[hash_[Cons 2,Nil 0](0)]] #Derived.hash_[Cons 2,Nil 0] = diff --git a/crates/compiler/test_derive/src/util.rs b/crates/compiler/test_derive/src/util.rs index 9e92557577..bb5d7bb6dc 100644 --- a/crates/compiler/test_derive/src/util.rs +++ b/crates/compiler/test_derive/src/util.rs @@ -187,7 +187,7 @@ macro_rules! v { use roc_types::subs::{Subs, Content}; |subs: &mut Subs| { roc_derive::synth_var(subs, Content::FlexVar(None)) } }}; - ($name:ident has $ability:path) => {{ + ($name:ident implements $ability:path) => {{ use roc_types::subs::{Subs, SubsIndex, SubsSlice, Content}; |subs: &mut Subs| { let name_index = diff --git a/crates/compiler/test_gen/Cargo.toml b/crates/compiler/test_gen/Cargo.toml index 3abd9974b1..cc323c814b 100644 --- a/crates/compiler/test_gen/Cargo.toml +++ b/crates/compiler/test_gen/Cargo.toml @@ -18,7 +18,13 @@ wasi_libc_sys = { path = "../../wasi-libc-sys" } tempfile.workspace = true +[dependencies] +roc_gen_llvm = { path = "../gen_llvm", optional = true } +inkwell = { workspace = true, optional = true } + [dev-dependencies] +roc_gen_dev = { path = "../gen_dev" } +roc_gen_wasm = { path = "../gen_wasm" } roc_bitcode = { path = "../builtins/bitcode" } roc_build = { path = "../build", features = ["target-aarch64", "target-x86_64", "target-wasm32"] } roc_builtins = { path = "../builtins" } @@ -28,9 +34,6 @@ roc_command_utils = { path = "../../utils/command" } roc_constrain = { path = "../constrain" } roc_debug_flags = { path = "../debug_flags" } roc_error_macros = { path = "../../error_macros" } -roc_gen_dev = { path = "../gen_dev" } -roc_gen_llvm = { path = "../gen_llvm" } -roc_gen_wasm = { path = "../gen_wasm" } roc_load = { path = "../load" } roc_module = { path = "../module" } roc_mono = { path = "../mono" } @@ -50,8 +53,6 @@ roc_wasm_module = { path = "../../wasm_module" } bumpalo.workspace = true criterion.workspace = true indoc.workspace = true -inkwell.workspace = true -lazy_static.workspace = true libc.workspace = true libloading.workspace = true target-lexicon.workspace = true @@ -61,7 +62,7 @@ tempfile.workspace = true [features] default = ["gen-llvm"] gen-dev = [] -gen-llvm = [] +gen-llvm = ["roc_gen_llvm", "inkwell"] gen-llvm-wasm = ["gen-llvm"] gen-wasm = [] diff --git a/crates/compiler/test_gen/benches/list_map.rs b/crates/compiler/test_gen/benches/list_map.rs index 877957322b..2aa8243bfd 100644 --- a/crates/compiler/test_gen/benches/list_map.rs +++ b/crates/compiler/test_gen/benches/list_map.rs @@ -62,8 +62,13 @@ fn roc_function<'a, 'b>( }; let context = inkwell::context::Context::create(); - let (main_fn_name, errors, lib) = - helpers::llvm::helper(arena, config, source, arena.alloc(context)); + let (main_fn_name, errors, lib) = helpers::llvm::helper( + arena, + config, + source, + arena.alloc(context), + roc_load::FunctionKind::LambdaSet, + ); assert!(errors.is_empty(), "Encountered errors:\n{errors}"); diff --git a/crates/compiler/test_gen/benches/quicksort.rs b/crates/compiler/test_gen/benches/quicksort.rs index 2c02646b49..2b786ac8dd 100644 --- a/crates/compiler/test_gen/benches/quicksort.rs +++ b/crates/compiler/test_gen/benches/quicksort.rs @@ -91,8 +91,13 @@ fn roc_function<'a>( }; let context = inkwell::context::Context::create(); - let (main_fn_name, errors, lib) = - helpers::llvm::helper(arena, config, source, arena.alloc(context)); + let (main_fn_name, errors, lib) = helpers::llvm::helper( + arena, + config, + source, + arena.alloc(context), + roc_load::FunctionKind::LambdaSet, + ); assert!(errors.is_empty(), "Encountered errors:\n{errors}"); diff --git a/crates/compiler/test_gen/src/gen_abilities.rs b/crates/compiler/test_gen/src/gen_abilities.rs index cf87114472..e4b393d406 100644 --- a/crates/compiler/test_gen/src/gen_abilities.rs +++ b/crates/compiler/test_gen/src/gen_abilities.rs @@ -22,10 +22,10 @@ fn hash_specialization() { r#" app "test" provides [main] to "./platform" - MHash has - hash : a -> U64 | a has MHash + MHash implements + hash : a -> U64 where a implements MHash - Id := U64 has [MHash {hash}] + Id := U64 implements [MHash {hash}] hash = \@Id n -> n @@ -45,14 +45,14 @@ fn hash_specialization_multiple_add() { r#" app "test" provides [main] to "./platform" - MHash has - hash : a -> U64 | a has MHash + MHash implements + hash : a -> U64 where a implements MHash - Id := U64 has [ MHash {hash: hashId} ] + Id := U64 implements [ MHash {hash: hashId} ] hashId = \@Id n -> n - One := {} has [ MHash {hash: hashOne} ] + One := {} implements [ MHash {hash: hashOne} ] hashOne = \@One _ -> 1 @@ -72,10 +72,10 @@ fn alias_member_specialization() { r#" app "test" provides [main] to "./platform" - MHash has - hash : a -> U64 | a has MHash + MHash implements + hash : a -> U64 where a implements MHash - Id := U64 has [MHash {hash}] + Id := U64 implements [MHash {hash}] hash = \@Id n -> n @@ -97,13 +97,13 @@ fn ability_constrained_in_non_member_usage() { r#" app "test" provides [result] to "./platform" - MHash has - hash : a -> U64 | a has MHash + MHash implements + hash : a -> U64 where a implements MHash - mulMHashes : a, a -> U64 | a has MHash + mulMHashes : a, a -> U64 where a implements MHash mulMHashes = \x, y -> hash x * hash y - Id := U64 has [MHash {hash}] + Id := U64 implements [MHash {hash}] hash = \@Id n -> n result = mulMHashes (@Id 5) (@Id 7) @@ -122,12 +122,12 @@ fn ability_constrained_in_non_member_usage_inferred() { r#" app "test" provides [result] to "./platform" - MHash has - hash : a -> U64 | a has MHash + MHash implements + hash : a -> U64 where a implements MHash mulMHashes = \x, y -> hash x * hash y - Id := U64 has [MHash {hash}] + Id := U64 implements [MHash {hash}] hash = \@Id n -> n result = mulMHashes (@Id 5) (@Id 7) @@ -146,16 +146,16 @@ fn ability_constrained_in_non_member_multiple_specializations() { r#" app "test" provides [result] to "./platform" - MHash has - hash : a -> U64 | a has MHash + MHash implements + hash : a -> U64 where a implements MHash - mulMHashes : a, b -> U64 | a has MHash, b has MHash + mulMHashes : a, b -> U64 where a implements MHash, b implements MHash mulMHashes = \x, y -> hash x * hash y - Id := U64 has [MHash { hash: hashId }] + Id := U64 implements [MHash { hash: hashId }] hashId = \@Id n -> n - Three := {} has [MHash { hash: hashThree }] + Three := {} implements [MHash { hash: hashThree }] hashThree = \@Three _ -> 3 result = mulMHashes (@Id 100) (@Three {}) @@ -174,15 +174,15 @@ fn ability_constrained_in_non_member_multiple_specializations_inferred() { r#" app "test" provides [result] to "./platform" - MHash has - hash : a -> U64 | a has MHash + MHash implements + hash : a -> U64 where a implements MHash mulMHashes = \x, y -> hash x * hash y - Id := U64 has [MHash { hash: hashId }] + Id := U64 implements [MHash { hash: hashId }] hashId = \@Id n -> n - Three := {} has [MHash { hash: hashThree }] + Three := {} implements [MHash { hash: hashThree }] hashThree = \@Three _ -> 3 result = mulMHashes (@Id 100) (@Three {}) @@ -201,16 +201,16 @@ fn ability_used_as_type_still_compiles() { r#" app "test" provides [result] to "./platform" - MHash has - hash : a -> U64 | a has MHash + MHash implements + hash : a -> U64 where a implements MHash mulMHashes : MHash, MHash -> U64 mulMHashes = \x, y -> hash x * hash y - Id := U64 has [MHash { hash: hashId }] + Id := U64 implements [MHash { hash: hashId }] hashId = \@Id n -> n - Three := {} has [MHash { hash: hashThree }] + Three := {} implements [MHash { hash: hashThree }] hashThree = \@Three _ -> 3 result = mulMHashes (@Id 100) (@Three {}) @@ -229,15 +229,15 @@ fn bounds_to_multiple_abilities() { r#" app "test" provides [main] to "./platform" - Idempot has idempot : a -> a | a has Idempot - Consume has consume : a -> Str | a has Consume + Idempot implements idempot : a -> a where a implements Idempot + Consume implements consume : a -> Str where a implements Consume - Hello := Str has [Idempot { idempot: idempotHello }, Consume { consume: consumeHello }] + Hello := Str implements [Idempot { idempot: idempotHello }, Consume { consume: consumeHello }] idempotHello = \@Hello msg -> @Hello msg consumeHello = \@Hello msg -> msg - lifecycle : a -> Str | a has Idempot & Consume + lifecycle : a -> Str where a implements Idempot & Consume lifecycle = \x -> idempot x |> consume main = lifecycle (@Hello "hello world") @@ -256,26 +256,26 @@ fn encode() { r#" app "test" provides [myU8Bytes] to "./platform" - MEncoder fmt := List U8, fmt -> List U8 | fmt has Format + MEncoder fmt := List U8, fmt -> List U8 where fmt implements Format - MEncoding has - toEncoder : val -> MEncoder fmt | val has MEncoding, fmt has Format + MEncoding implements + toEncoder : val -> MEncoder fmt where val implements MEncoding, fmt implements Format - Format has - u8 : U8 -> MEncoder fmt | fmt has Format + Format implements + u8 : U8 -> MEncoder fmt where fmt implements Format - appendWith : List U8, MEncoder fmt, fmt -> List U8 | fmt has Format + appendWith : List U8, MEncoder fmt, fmt -> List U8 where fmt implements Format appendWith = \lst, (@MEncoder doFormat), fmt -> doFormat lst fmt - toBytes : val, fmt -> List U8 | val has MEncoding, fmt has Format + toBytes : val, fmt -> List U8 where val implements MEncoding, fmt implements Format toBytes = \val, fmt -> appendWith [] (toEncoder val) fmt - Linear := {} has [Format {u8}] + Linear := {} implements [Format {u8}] u8 = \n -> @MEncoder (\lst, @Linear {} -> List.append lst n) - Rgba := { r : U8, g : U8, b : U8, a : U8 } has [MEncoding {toEncoder}] + Rgba := { r : U8, g : U8, b : U8, a : U8 } implements [MEncoding {toEncoder}] toEncoder = \@Rgba {r, g, b, a} -> @MEncoder \lst, fmt -> lst @@ -303,19 +303,19 @@ fn decode() { MDecodeError : [TooShort, Leftover (List U8)] - MDecoder val fmt := List U8, fmt -> { result: Result val MDecodeError, rest: List U8 } | fmt has MDecoderFormatting + MDecoder val fmt := List U8, fmt -> { result: Result val MDecodeError, rest: List U8 } where fmt implements MDecoderFormatting - MDecoding has - decoder : MDecoder val fmt | val has MDecoding, fmt has MDecoderFormatting + MDecoding implements + decoder : MDecoder val fmt where val implements MDecoding, fmt implements MDecoderFormatting - MDecoderFormatting has - u8 : MDecoder U8 fmt | fmt has MDecoderFormatting + MDecoderFormatting implements + u8 : MDecoder U8 fmt where fmt implements MDecoderFormatting - decodeWith : List U8, MDecoder val fmt, fmt -> { result: Result val MDecodeError, rest: List U8 } | fmt has MDecoderFormatting + decodeWith : List U8, MDecoder val fmt, fmt -> { result: Result val MDecodeError, rest: List U8 } where fmt implements MDecoderFormatting decodeWith = \lst, (@MDecoder doDecode), fmt -> doDecode lst fmt fromBytes : List U8, fmt -> Result val MDecodeError - | fmt has MDecoderFormatting, val has MDecoding + where fmt implements MDecoderFormatting, val implements MDecoding fromBytes = \lst, fmt -> when decodeWith lst decoder fmt is { result, rest } -> @@ -325,14 +325,14 @@ fn decode() { else Err (Leftover rest) - Linear := {} has [MDecoderFormatting {u8}] + Linear := {} implements [MDecoderFormatting {u8}] u8 = @MDecoder \lst, @Linear {} -> when List.first lst is Ok n -> { result: Ok n, rest: List.dropFirst lst } Err _ -> { result: Err TooShort, rest: [] } - MyU8 := U8 has [MDecoding {decoder}] + MyU8 := U8 implements [MDecoding {decoder}] # impl MDecoding for MyU8 decoder = @MDecoder \lst, fmt -> @@ -360,7 +360,7 @@ fn encode_use_stdlib() { imports [Encode, TotallyNotJson] provides [main] to "./platform" - HelloWorld := {} has [Encoding {toEncoder}] + HelloWorld := {} implements [Encoding {toEncoder}] toEncoder = \@HelloWorld {} -> Encode.custom \bytes, fmt -> bytes @@ -388,7 +388,7 @@ fn encode_use_stdlib_without_wrapping_custom() { imports [Encode, TotallyNotJson] provides [main] to "./platform" - HelloWorld := {} has [Encoding {toEncoder}] + HelloWorld := {} implements [Encoding {toEncoder}] toEncoder = \@HelloWorld {} -> Encode.string "Hello, World!\n" main = @@ -414,7 +414,7 @@ fn encode_derive_to_encoder_for_opaque() { imports [TotallyNotJson] provides [main] to "./platform" - HelloWorld := { a: Str } has [Encoding] + HelloWorld := { a: Str } implements [Encoding] main = result = Str.fromUtf8 (Encode.toBytes (@HelloWorld { a: "Hello, World!" }) TotallyNotJson.json) @@ -438,7 +438,7 @@ fn to_encoder_encode_custom_has_capture() { imports [Encode, TotallyNotJson] provides [main] to "./platform" - HelloWorld := Str has [Encoding {toEncoder}] + HelloWorld := Str implements [Encoding {toEncoder}] toEncoder = \@HelloWorld s1 -> Encode.custom \bytes, fmt -> bytes @@ -891,7 +891,7 @@ fn encode_derived_generic_record_with_different_field_types() { imports [Encode, TotallyNotJson] provides [main] to "./platform" - Q a b := {a: a, b: b} has [Encoding] + Q a b := {a: a, b: b} implements [Encoding] q = @Q {a: 10u32, b: "fieldb"} @@ -917,7 +917,7 @@ fn encode_derived_generic_tag_with_different_field_types() { imports [Encode, TotallyNotJson] provides [main] to "./platform" - Q a b := [A a, B b] has [Encoding] + Q a b := [A a, B b] implements [Encoding] q : Q Str U32 q = @Q (B 67) @@ -969,7 +969,7 @@ fn decode_use_stdlib() { imports [TotallyNotJson] provides [main] to "./platform" - MyNum := U8 has [Decoding {decoder: myDecoder}] + MyNum := U8 implements [Decoding {decoder: myDecoder}] myDecoder = Decode.custom \bytes, fmt -> @@ -1003,7 +1003,7 @@ fn decode_derive_decoder_for_opaque() { imports [TotallyNotJson] provides [main] to "./platform" - HelloWorld := { a: Str } has [Decoding] + HelloWorld := { a: Str } implements [Decoding] main = when Str.toUtf8 """{"a":"Hello, World!"}""" |> Decode.fromBytes TotallyNotJson.json is @@ -1026,7 +1026,7 @@ fn decode_use_stdlib_json_list() { imports [TotallyNotJson] provides [main] to "./platform" - MyNumList := List U8 has [Decoding {decoder: myDecoder}] + MyNumList := List U8 implements [Decoding {decoder: myDecoder}] myDecoder = Decode.custom \bytes, fmt -> @@ -1459,7 +1459,7 @@ mod hash { const TEST_HASHER: &str = indoc!( r#" - THasher := List U8 has [Hasher { + THasher := List U8 implements [Hasher { addBytes: tAddBytes, addU8: tAddU8, addU16: tAddU16, @@ -2002,7 +2002,7 @@ mod hash { {} - Q := {{ a: U8, b: U8, c: U8 }} has [Hash] + Q := {{ a: U8, b: U8, c: U8 }} implements [Hash] q = @Q {{ a: 15, b: 27, c: 31 }} @@ -2055,7 +2055,7 @@ mod eq { r#" app "test" provides [main] to "./platform" - LyingEq := U8 has [Eq {isEq}] + LyingEq := U8 implements [Eq {isEq}] isEq = \@LyingEq m, @LyingEq n -> m != n @@ -2081,7 +2081,7 @@ mod eq { r#" app "test" provides [main] to "./platform" - Q := ({} -> Str) has [Eq {isEq: isEqQ}] + Q := ({} -> Str) implements [Eq {isEq: isEqQ}] isEqQ = \@Q _, @Q _ -> Bool.true @@ -2101,7 +2101,7 @@ mod eq { r#" app "test" provides [main] to "./platform" - Q := ({} -> Str) has [Eq {isEq: isEqQ}] + Q := ({} -> Str) implements [Eq {isEq: isEqQ}] isEqQ = \@Q f1, @Q f2 -> (f1 {} == f2 {}) @@ -2135,7 +2135,7 @@ mod eq { r#" app "test" provides [main] to "./platform" - Q := U8 has [Eq] + Q := U8 implements [Eq] main = (@Q 15) == (@Q 15) "# diff --git a/crates/compiler/test_gen/src/gen_list.rs b/crates/compiler/test_gen/src/gen_list.rs index af7ededf09..25f89869b7 100644 --- a/crates/compiler/test_gen/src/gen_list.rs +++ b/crates/compiler/test_gen/src/gen_list.rs @@ -959,7 +959,7 @@ fn list_walk_implements_position() { r#" Option a : [Some a, None] - find : List a, a -> Option Nat | a has Eq + find : List a, a -> Option Nat where a implements Eq find = \list, needle -> findHelp list needle |> .v @@ -3692,7 +3692,7 @@ fn list_walk_backwards_implements_position() { r#" Option a : [Some a, None] - find : List a, a -> Option Nat | a has Eq + find : List a, a -> Option Nat where a implements Eq find = \list, needle -> findHelp list needle |> .v @@ -3810,6 +3810,9 @@ fn list_range_length_overflow() { #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] mod pattern_match { + #[allow(unused_imports)] + use crate::helpers::with_larger_debug_stack; + #[cfg(feature = "gen-llvm")] use crate::helpers::llvm::assert_evals_to; @@ -3819,8 +3822,6 @@ mod pattern_match { #[cfg(feature = "gen-dev")] use crate::helpers::dev::assert_evals_to; - use crate::helpers::with_larger_debug_stack; - use super::RocList; #[test] diff --git a/crates/compiler/test_gen/src/gen_num.rs b/crates/compiler/test_gen/src/gen_num.rs index 4c026f14c6..14846d009e 100644 --- a/crates/compiler/test_gen/src/gen_num.rs +++ b/crates/compiler/test_gen/src/gen_num.rs @@ -891,7 +891,7 @@ fn gen_wrap_int_neq() { assert_evals_to!( indoc!( r#" - wrappedNotEq : a, a -> Bool | a has Eq + wrappedNotEq : a, a -> Bool where a implements Eq wrappedNotEq = \num1, num2 -> num1 != num2 diff --git a/crates/compiler/test_gen/src/gen_tags.rs b/crates/compiler/test_gen/src/gen_tags.rs index 749bc5d185..8f5b0783c3 100644 --- a/crates/compiler/test_gen/src/gen_tags.rs +++ b/crates/compiler/test_gen/src/gen_tags.rs @@ -1,3 +1,6 @@ +#[allow(unused_imports)] +use crate::helpers::with_larger_debug_stack; + #[cfg(feature = "gen-llvm")] use crate::helpers::llvm::assert_evals_to; @@ -14,8 +17,6 @@ use roc_mono::layout::{LayoutRepr, STLayoutInterner}; #[cfg(test)] use roc_std::{RocList, RocStr, U128}; -use crate::helpers::with_larger_debug_stack; - #[test] fn width_and_alignment_u8_u8() { use roc_mono::layout::Layout; @@ -2254,15 +2255,15 @@ fn recursive_tag_id_in_allocation_basic() { main = when x is - A _ -> "A" - B _ -> "B" - C _ -> "C" - D _ -> "D" - E _ -> "E" - F _ -> "F" - G _ -> "G" - H _ -> "H" - I _ -> "I" + A _ -> "A" + B _ -> "B" + C _ -> "C" + D _ -> "D" + E _ -> "E" + F _ -> "F" + G _ -> "G" + H _ -> "H" + I _ -> "I" "### ), RocStr::from("H"), diff --git a/crates/compiler/test_gen/src/helpers/dev.rs b/crates/compiler/test_gen/src/helpers/dev.rs index e2238b2703..8cd7046888 100644 --- a/crates/compiler/test_gen/src/helpers/dev.rs +++ b/crates/compiler/test_gen/src/helpers/dev.rs @@ -215,9 +215,10 @@ pub fn helper( let builtins_host_tempfile = roc_bitcode::host_tempfile().expect("failed to write host builtins object to tempfile"); - // TODO make this an envrionment variable + // TODO make this an environment variable if false { let file_path = std::env::temp_dir().join("app.o"); + println!("gen-test object file written to {}", file_path.display()); std::fs::copy(&app_o_file, file_path).unwrap(); } diff --git a/crates/compiler/test_gen/src/helpers/llvm.rs b/crates/compiler/test_gen/src/helpers/llvm.rs index ba5e129c04..34bc8dc9fc 100644 --- a/crates/compiler/test_gen/src/helpers/llvm.rs +++ b/crates/compiler/test_gen/src/helpers/llvm.rs @@ -1,5 +1,6 @@ use std::mem::MaybeUninit; use std::path::PathBuf; +use std::sync::OnceLock; use inkwell::module::Module; use libloading::Library; @@ -101,6 +102,7 @@ fn create_llvm_module<'a>( use roc_load::MonomorphizedModule; let MonomorphizedModule { procedures, + host_exposed_lambda_sets, interns, layout_interner, .. @@ -270,6 +272,7 @@ fn create_llvm_module<'a>( &layout_interner, config.opt_level, procedures, + host_exposed_lambda_sets, entry_point, ), }; @@ -414,10 +417,6 @@ fn write_final_wasm() -> bool { false } -lazy_static::lazy_static! { - static ref TEMP_DIR: tempfile::TempDir = tempfile::tempdir().unwrap(); -} - #[allow(dead_code)] fn compile_to_wasm_bytes<'a>( arena: &'a bumpalo::Bump, @@ -426,13 +425,17 @@ fn compile_to_wasm_bytes<'a>( context: &'a inkwell::context::Context, function_kind: FunctionKind, ) -> Vec { + // globally cache the temporary directory + static TEMP_DIR: OnceLock = OnceLock::new(); + let temp_dir = TEMP_DIR.get_or_init(|| tempfile::tempdir().unwrap()); + let target = wasm32_target_tripple(); let (_main_fn_name, _delayed_errors, llvm_module) = create_llvm_module(arena, src, config, context, &target, function_kind); let content_hash = crate::helpers::src_hash(src); - let wasm_file = llvm_module_to_wasm_file(&TEMP_DIR, content_hash, llvm_module); + let wasm_file = llvm_module_to_wasm_file(temp_dir, content_hash, llvm_module); let compiled_bytes = std::fs::read(wasm_file).unwrap(); if write_final_wasm() { diff --git a/crates/compiler/test_gen/src/wasm_linking.rs b/crates/compiler/test_gen/src/wasm_linking.rs index fd6597cd9e..97b1688a99 100644 --- a/crates/compiler/test_gen/src/wasm_linking.rs +++ b/crates/compiler/test_gen/src/wasm_linking.rs @@ -14,8 +14,7 @@ use roc_module::symbol::{ Symbol, }; use roc_mono::ir::{ - Call, CallType, Expr, HostExposedLayouts, Literal, Proc, ProcLayout, SelfRecursive, Stmt, - UpdateModeId, + Call, CallType, Expr, Literal, Proc, ProcLayout, SelfRecursive, Stmt, UpdateModeId, }; use roc_mono::layout::{LambdaName, Layout, Niche, STLayoutInterner}; use roc_wasm_interp::{wasi, ImportDispatcher, Instance, WasiDispatcher}; @@ -116,7 +115,6 @@ fn build_app_mono<'a>( closure_data_layout: None, ret_layout: int_layout, is_self_recursive: SelfRecursive::NotSelfRecursive, - host_exposed_layouts: HostExposedLayouts::NotHostExposed, is_erased: false, }; diff --git a/crates/compiler/test_mono/generated/anonymous_closure_in_polymorphic_expression_issue_4717.txt b/crates/compiler/test_mono/generated/anonymous_closure_in_polymorphic_expression_issue_4717.txt index f3eca0d0aa..a4c40a4e26 100644 --- a/crates/compiler/test_mono/generated/anonymous_closure_in_polymorphic_expression_issue_4717.txt +++ b/crates/compiler/test_mono/generated/anonymous_closure_in_polymorphic_expression_issue_4717.txt @@ -2,97 +2,97 @@ procedure Bool.11 (#Attr.2, #Attr.3): let Bool.24 : Int1 = lowlevel Eq #Attr.2 #Attr.3; ret Bool.24; -procedure List.26 (List.159, List.160, List.161): - let List.536 : [C U64, C U64] = CallByName List.93 List.159 List.160 List.161; - let List.539 : U8 = 1i64; - let List.540 : U8 = GetTagId List.536; - let List.541 : Int1 = lowlevel Eq List.539 List.540; - if List.541 then - let List.162 : U64 = UnionAtIndex (Id 1) (Index 0) List.536; - ret List.162; +procedure List.26 (List.172, List.173, List.174): + let List.550 : [C U64, C U64] = CallByName List.96 List.172 List.173 List.174; + let List.553 : U8 = 1i64; + let List.554 : U8 = GetTagId List.550; + let List.555 : Int1 = lowlevel Eq List.553 List.554; + if List.555 then + let List.175 : U64 = UnionAtIndex (Id 1) (Index 0) List.550; + ret List.175; else - let List.163 : U64 = UnionAtIndex (Id 0) (Index 0) List.536; - ret List.163; + let List.176 : U64 = UnionAtIndex (Id 0) (Index 0) List.550; + ret List.176; -procedure List.29 (List.304, List.305): - let List.535 : U64 = CallByName List.6 List.304; - let List.306 : U64 = CallByName Num.77 List.535 List.305; - let List.521 : List U8 = CallByName List.43 List.304 List.306; - ret List.521; +procedure List.29 (List.317, List.318): + let List.549 : U64 = CallByName List.6 List.317; + let List.319 : U64 = CallByName Num.77 List.549 List.318; + let List.535 : List U8 = CallByName List.43 List.317 List.319; + ret List.535; -procedure List.43 (List.302, List.303): - let List.533 : U64 = CallByName List.6 List.302; - let List.532 : U64 = CallByName Num.77 List.533 List.303; - let List.523 : {U64, U64} = Struct {List.303, List.532}; - let List.522 : List U8 = CallByName List.49 List.302 List.523; - ret List.522; +procedure List.43 (List.315, List.316): + let List.547 : U64 = CallByName List.6 List.315; + let List.546 : U64 = CallByName Num.77 List.547 List.316; + let List.537 : {U64, U64} = Struct {List.316, List.546}; + let List.536 : List U8 = CallByName List.49 List.315 List.537; + ret List.536; -procedure List.49 (List.376, List.377): - let List.530 : U64 = StructAtIndex 0 List.377; - let List.531 : U64 = 0i64; - let List.528 : Int1 = CallByName Bool.11 List.530 List.531; - if List.528 then - dec List.376; - let List.529 : List U8 = Array []; - ret List.529; +procedure List.49 (List.390, List.391): + let List.544 : U64 = StructAtIndex 0 List.391; + let List.545 : U64 = 0i64; + let List.542 : Int1 = CallByName Bool.11 List.544 List.545; + if List.542 then + dec List.390; + let List.543 : List U8 = Array []; + ret List.543; else - let List.525 : U64 = StructAtIndex 1 List.377; - let List.526 : U64 = StructAtIndex 0 List.377; - let List.524 : List U8 = CallByName List.72 List.376 List.525 List.526; - ret List.524; + let List.539 : U64 = StructAtIndex 1 List.391; + let List.540 : U64 = StructAtIndex 0 List.391; + let List.538 : List U8 = CallByName List.72 List.390 List.539 List.540; + ret List.538; procedure List.6 (#Attr.2): - let List.534 : U64 = lowlevel ListLen #Attr.2; - ret List.534; + let List.548 : U64 = lowlevel ListLen #Attr.2; + ret List.548; procedure List.66 (#Attr.2, #Attr.3): - let List.557 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.557; + let List.571 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.571; procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.527 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.527; + let List.541 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.541; procedure List.80 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4): - joinpoint List.545 List.439 List.440 List.441 List.442 List.443: - let List.547 : Int1 = CallByName Num.22 List.442 List.443; - if List.547 then - let List.556 : U8 = CallByName List.66 List.439 List.442; - let List.548 : [C U64, C U64] = CallByName Test.4 List.440 List.556; - let List.553 : U8 = 1i64; - let List.554 : U8 = GetTagId List.548; - let List.555 : Int1 = lowlevel Eq List.553 List.554; - if List.555 then - let List.444 : U64 = UnionAtIndex (Id 1) (Index 0) List.548; - let List.551 : U64 = 1i64; - let List.550 : U64 = CallByName Num.19 List.442 List.551; - jump List.545 List.439 List.444 List.441 List.550 List.443; + joinpoint List.559 List.453 List.454 List.455 List.456 List.457: + let List.561 : Int1 = CallByName Num.22 List.456 List.457; + if List.561 then + let List.570 : U8 = CallByName List.66 List.453 List.456; + let List.562 : [C U64, C U64] = CallByName Test.4 List.454 List.570; + let List.567 : U8 = 1i64; + let List.568 : U8 = GetTagId List.562; + let List.569 : Int1 = lowlevel Eq List.567 List.568; + if List.569 then + let List.458 : U64 = UnionAtIndex (Id 1) (Index 0) List.562; + let List.565 : U64 = 1i64; + let List.564 : U64 = CallByName Num.51 List.456 List.565; + jump List.559 List.453 List.458 List.455 List.564 List.457; else - dec List.439; - let List.445 : U64 = UnionAtIndex (Id 0) (Index 0) List.548; - let List.552 : [C U64, C U64] = TagId(0) List.445; - ret List.552; + dec List.453; + let List.459 : U64 = UnionAtIndex (Id 0) (Index 0) List.562; + let List.566 : [C U64, C U64] = TagId(0) List.459; + ret List.566; else - dec List.439; - let List.546 : [C U64, C U64] = TagId(1) List.440; - ret List.546; + dec List.453; + let List.560 : [C U64, C U64] = TagId(1) List.454; + ret List.560; in - jump List.545 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; + jump List.559 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; -procedure List.93 (List.436, List.437, List.438): - let List.543 : U64 = 0i64; - let List.544 : U64 = CallByName List.6 List.436; - let List.542 : [C U64, C U64] = CallByName List.80 List.436 List.437 List.438 List.543 List.544; - ret List.542; - -procedure Num.19 (#Attr.2, #Attr.3): - let Num.294 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.294; +procedure List.96 (List.450, List.451, List.452): + let List.557 : U64 = 0i64; + let List.558 : U64 = CallByName List.6 List.450; + let List.556 : [C U64, C U64] = CallByName List.80 List.450 List.451 List.452 List.557 List.558; + ret List.556; procedure Num.22 (#Attr.2, #Attr.3): let Num.295 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; ret Num.295; +procedure Num.51 (#Attr.2, #Attr.3): + let Num.294 : U64 = lowlevel NumAddWrap #Attr.2 #Attr.3; + ret Num.294; + procedure Num.77 (#Attr.2, #Attr.3): let Num.293 : U64 = lowlevel NumSubSaturated #Attr.2 #Attr.3; ret Num.293; diff --git a/crates/compiler/test_mono/generated/call_function_in_empty_list.txt b/crates/compiler/test_mono/generated/call_function_in_empty_list.txt index 49843c03dd..37a77978b7 100644 --- a/crates/compiler/test_mono/generated/call_function_in_empty_list.txt +++ b/crates/compiler/test_mono/generated/call_function_in_empty_list.txt @@ -1,7 +1,7 @@ procedure List.5 (#Attr.2, #Attr.3): - let List.521 : List {} = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.2 #Attr.3; + let List.535 : List {} = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.2 #Attr.3; decref #Attr.2; - ret List.521; + ret List.535; procedure Test.2 (Test.3): let Test.7 : {} = Struct {}; diff --git a/crates/compiler/test_mono/generated/call_function_in_empty_list_unbound.txt b/crates/compiler/test_mono/generated/call_function_in_empty_list_unbound.txt index ce2dbde965..8028068b67 100644 --- a/crates/compiler/test_mono/generated/call_function_in_empty_list_unbound.txt +++ b/crates/compiler/test_mono/generated/call_function_in_empty_list_unbound.txt @@ -1,7 +1,7 @@ procedure List.5 (#Attr.2, #Attr.3): - let List.521 : List [] = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.2 #Attr.3; + let List.535 : List [] = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.2 #Attr.3; decref #Attr.2; - ret List.521; + ret List.535; procedure Test.2 (Test.3): let Test.7 : {} = Struct {}; diff --git a/crates/compiler/test_mono/generated/capture_void_layout_task.txt b/crates/compiler/test_mono/generated/capture_void_layout_task.txt index a1ccd5b8d3..873a7e73dd 100644 --- a/crates/compiler/test_mono/generated/capture_void_layout_task.txt +++ b/crates/compiler/test_mono/generated/capture_void_layout_task.txt @@ -1,52 +1,44 @@ -procedure List.145 (List.146, List.147, List.144): - let List.540 : [C {}, C *self {{}, []}] = CallByName Test.29 List.146 List.147 List.144; - ret List.540; - -procedure List.18 (List.142, List.143, List.144): - let List.521 : [C {}, C *self {{}, []}] = CallByName List.93 List.142 List.143 List.144; - ret List.521; +procedure List.18 (List.145, List.146, List.147): + let List.536 : U64 = 0i64; + let List.537 : U64 = CallByName List.6 List.145; + let List.535 : [C {}, C *self {{}, []}] = CallByName List.86 List.145 List.146 List.147 List.536 List.537; + ret List.535; procedure List.6 (#Attr.2): - let List.538 : U64 = lowlevel ListLen #Attr.2; - ret List.538; + let List.546 : U64 = lowlevel ListLen #Attr.2; + ret List.546; procedure List.66 (#Attr.2, #Attr.3): - let List.537 : [] = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.537; + let List.545 : [] = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.545; -procedure List.80 (#Derived_gen.11, #Derived_gen.12, #Derived_gen.13, #Derived_gen.14, #Derived_gen.15): - joinpoint List.527 List.439 List.440 List.441 List.442 List.443: - let List.529 : Int1 = CallByName Num.22 List.442 List.443; - if List.529 then - let List.536 : [] = CallByName List.66 List.439 List.442; - let List.530 : [C {}, C *self {{}, []}] = CallByName List.145 List.440 List.536 List.441; - let List.533 : U64 = 1i64; - let List.532 : U64 = CallByName Num.19 List.442 List.533; - jump List.527 List.439 List.530 List.441 List.532 List.443; +procedure List.86 (#Derived_gen.13, #Derived_gen.14, #Derived_gen.15, #Derived_gen.16, #Derived_gen.17): + joinpoint List.538 List.148 List.149 List.150 List.151 List.152: + let List.540 : Int1 = CallByName Num.22 List.151 List.152; + if List.540 then + let List.544 : [] = CallByName List.66 List.148 List.151; + let List.153 : [C {}, C *self {{}, []}] = CallByName Test.29 List.149 List.544 List.150; + let List.543 : U64 = 1i64; + let List.542 : U64 = CallByName Num.51 List.151 List.543; + jump List.538 List.148 List.153 List.150 List.542 List.152; else - dec List.439; - ret List.440; + dec List.148; + ret List.149; in - jump List.527 #Derived_gen.11 #Derived_gen.12 #Derived_gen.13 #Derived_gen.14 #Derived_gen.15; - -procedure List.93 (List.436, List.437, List.438): - let List.525 : U64 = 0i64; - let List.526 : U64 = CallByName List.6 List.436; - let List.524 : [C {}, C *self {{}, []}] = CallByName List.80 List.436 List.437 List.438 List.525 List.526; - ret List.524; - -procedure Num.19 (#Attr.2, #Attr.3): - let Num.292 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.292; + jump List.538 #Derived_gen.13 #Derived_gen.14 #Derived_gen.15 #Derived_gen.16 #Derived_gen.17; procedure Num.22 (#Attr.2, #Attr.3): let Num.293 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; ret Num.293; +procedure Num.51 (#Attr.2, #Attr.3): + let Num.292 : U64 = lowlevel NumAddWrap #Attr.2 #Attr.3; + ret Num.292; + procedure Test.10 (Test.66, #Attr.12): let Test.9 : {} = UnionAtIndex (Id 0) (Index 0) #Attr.12; - let #Derived_gen.18 : Int1 = lowlevel RefCountIsUnique #Attr.12; - if #Derived_gen.18 then + let #Derived_gen.20 : Int1 = lowlevel RefCountIsUnique #Attr.12; + if #Derived_gen.20 then free #Attr.12; ret Test.9; else @@ -60,7 +52,7 @@ procedure Test.10 (Test.66, #Attr.12): procedure Test.14 (Test.45, #Attr.12): let Test.13 : {{}, []} = UnionAtIndex (Id 1) (Index 1) #Attr.12; let Test.12 : [C {}, C *self {{}, []}] = UnionAtIndex (Id 1) (Index 0) #Attr.12; - joinpoint #Derived_gen.19: + joinpoint #Derived_gen.18: let Test.50 : {} = Struct {}; let Test.51 : U8 = GetTagId Test.12; joinpoint Test.52 Test.15: @@ -87,14 +79,14 @@ procedure Test.14 (Test.45, #Attr.12): jump Test.52 Test.53; in - let #Derived_gen.20 : Int1 = lowlevel RefCountIsUnique #Attr.12; - if #Derived_gen.20 then + let #Derived_gen.19 : Int1 = lowlevel RefCountIsUnique #Attr.12; + if #Derived_gen.19 then free #Attr.12; - jump #Derived_gen.19; + jump #Derived_gen.18; else inc Test.12; decref #Attr.12; - jump #Derived_gen.19; + jump #Derived_gen.18; procedure Test.20 (Test.21, Test.18): let Test.23 : [C {}, C []] = CallByName Test.32 Test.21 Test.18; @@ -156,8 +148,16 @@ procedure Test.80 (Test.81): ret Test.83; procedure Test.84 (Test.86, #Attr.12): - let Test.87 : Str = "a Lambda Set is empty. Most likely there is a type error in your program."; - Crash Test.87 + let Test.87 : U8 = GetTagId #Attr.12; + switch Test.87: + case 0: + let Test.85 : {} = CallByName Test.10 Test.86 #Attr.12; + ret Test.85; + + default: + let Test.85 : {} = CallByName Test.14 Test.86 #Attr.12; + ret Test.85; + procedure Test.0 (): let Test.35 : List [] = Array []; diff --git a/crates/compiler/test_mono/generated/choose_correct_recursion_var_under_record.txt b/crates/compiler/test_mono/generated/choose_correct_recursion_var_under_record.txt index b52e46a91d..787d6a4b7d 100644 --- a/crates/compiler/test_mono/generated/choose_correct_recursion_var_under_record.txt +++ b/crates/compiler/test_mono/generated/choose_correct_recursion_var_under_record.txt @@ -2,49 +2,49 @@ procedure Bool.1 (): let Bool.24 : Int1 = false; ret Bool.24; -procedure List.2 (List.97, List.98): - let List.535 : U64 = CallByName List.6 List.97; - let List.531 : Int1 = CallByName Num.22 List.98 List.535; - if List.531 then - let List.533 : Str = CallByName List.66 List.97 List.98; - inc List.533; - dec List.97; - let List.532 : [C {}, C Str] = TagId(1) List.533; - ret List.532; +procedure List.2 (List.100, List.101): + let List.549 : U64 = CallByName List.6 List.100; + let List.545 : Int1 = CallByName Num.22 List.101 List.549; + if List.545 then + let List.547 : Str = CallByName List.66 List.100 List.101; + inc List.547; + dec List.100; + let List.546 : [C {}, C Str] = TagId(1) List.547; + ret List.546; else - dec List.97; - let List.530 : {} = Struct {}; - let List.529 : [C {}, C Str] = TagId(0) List.530; - ret List.529; + dec List.100; + let List.544 : {} = Struct {}; + let List.543 : [C {}, C Str] = TagId(0) List.544; + ret List.543; procedure List.5 (#Attr.2, #Attr.3): - let List.537 : List Str = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.10 #Attr.3; + let List.551 : List Str = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.10 #Attr.3; decref #Attr.2; - ret List.537; + ret List.551; procedure List.6 (#Attr.2): - let List.536 : U64 = lowlevel ListLen #Attr.2; - ret List.536; + let List.550 : U64 = lowlevel ListLen #Attr.2; + ret List.550; procedure List.66 (#Attr.2, #Attr.3): - let List.534 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.534; + let List.548 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.548; -procedure List.9 (List.293): - let List.528 : U64 = 0i64; - let List.521 : [C {}, C Str] = CallByName List.2 List.293 List.528; - let List.525 : U8 = 1i64; - let List.526 : U8 = GetTagId List.521; - let List.527 : Int1 = lowlevel Eq List.525 List.526; - if List.527 then - let List.294 : Str = UnionAtIndex (Id 1) (Index 0) List.521; - let List.522 : [C {}, C Str] = TagId(1) List.294; - ret List.522; +procedure List.9 (List.306): + let List.542 : U64 = 0i64; + let List.535 : [C {}, C Str] = CallByName List.2 List.306 List.542; + let List.539 : U8 = 1i64; + let List.540 : U8 = GetTagId List.535; + let List.541 : Int1 = lowlevel Eq List.539 List.540; + if List.541 then + let List.307 : Str = UnionAtIndex (Id 1) (Index 0) List.535; + let List.536 : [C {}, C Str] = TagId(1) List.307; + ret List.536; else - dec List.521; - let List.524 : {} = Struct {}; - let List.523 : [C {}, C Str] = TagId(0) List.524; - ret List.523; + dec List.535; + let List.538 : {} = Struct {}; + let List.537 : [C {}, C Str] = TagId(0) List.538; + ret List.537; procedure Num.22 (#Attr.2, #Attr.3): let Num.292 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; diff --git a/crates/compiler/test_mono/generated/closure_in_list.txt b/crates/compiler/test_mono/generated/closure_in_list.txt index 5550ea1fda..41cd34065e 100644 --- a/crates/compiler/test_mono/generated/closure_in_list.txt +++ b/crates/compiler/test_mono/generated/closure_in_list.txt @@ -1,6 +1,6 @@ procedure List.6 (#Attr.2): - let List.521 : U64 = lowlevel ListLen #Attr.2; - ret List.521; + let List.535 : U64 = lowlevel ListLen #Attr.2; + ret List.535; procedure Test.1 (Test.5): let Test.2 : I64 = 41i64; diff --git a/crates/compiler/test_mono/generated/compose_recursive_lambda_set_productive_nullable_wrapped.txt b/crates/compiler/test_mono/generated/compose_recursive_lambda_set_productive_nullable_wrapped.txt index cbd51527e7..6883e5e0b6 100644 --- a/crates/compiler/test_mono/generated/compose_recursive_lambda_set_productive_nullable_wrapped.txt +++ b/crates/compiler/test_mono/generated/compose_recursive_lambda_set_productive_nullable_wrapped.txt @@ -2,51 +2,43 @@ procedure Bool.2 (): let Bool.23 : Int1 = true; ret Bool.23; -procedure List.145 (List.146, List.147, List.144): - let List.540 : [, C *self Int1, C *self Int1] = CallByName Test.6 List.146 List.147 List.144; - ret List.540; - -procedure List.18 (List.142, List.143, List.144): - let List.521 : [, C *self Int1, C *self Int1] = CallByName List.93 List.142 List.143 List.144; - ret List.521; +procedure List.18 (List.145, List.146, List.147): + let List.536 : U64 = 0i64; + let List.537 : U64 = CallByName List.6 List.145; + let List.535 : [, C *self Int1, C *self Int1] = CallByName List.86 List.145 List.146 List.147 List.536 List.537; + ret List.535; procedure List.6 (#Attr.2): - let List.538 : U64 = lowlevel ListLen #Attr.2; - ret List.538; + let List.546 : U64 = lowlevel ListLen #Attr.2; + ret List.546; procedure List.66 (#Attr.2, #Attr.3): - let List.537 : Int1 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.537; + let List.545 : Int1 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.545; -procedure List.80 (#Derived_gen.3, #Derived_gen.4, #Derived_gen.5, #Derived_gen.6, #Derived_gen.7): - joinpoint List.527 List.439 List.440 List.441 List.442 List.443: - let List.529 : Int1 = CallByName Num.22 List.442 List.443; - if List.529 then - let List.536 : Int1 = CallByName List.66 List.439 List.442; - let List.530 : [, C *self Int1, C *self Int1] = CallByName List.145 List.440 List.536 List.441; - let List.533 : U64 = 1i64; - let List.532 : U64 = CallByName Num.19 List.442 List.533; - jump List.527 List.439 List.530 List.441 List.532 List.443; +procedure List.86 (#Derived_gen.3, #Derived_gen.4, #Derived_gen.5, #Derived_gen.6, #Derived_gen.7): + joinpoint List.538 List.148 List.149 List.150 List.151 List.152: + let List.540 : Int1 = CallByName Num.22 List.151 List.152; + if List.540 then + let List.544 : Int1 = CallByName List.66 List.148 List.151; + let List.153 : [, C *self Int1, C *self Int1] = CallByName Test.6 List.149 List.544 List.150; + let List.543 : U64 = 1i64; + let List.542 : U64 = CallByName Num.51 List.151 List.543; + jump List.538 List.148 List.153 List.150 List.542 List.152; else - dec List.439; - ret List.440; + dec List.148; + ret List.149; in - jump List.527 #Derived_gen.3 #Derived_gen.4 #Derived_gen.5 #Derived_gen.6 #Derived_gen.7; - -procedure List.93 (List.436, List.437, List.438): - let List.525 : U64 = 0i64; - let List.526 : U64 = CallByName List.6 List.436; - let List.524 : [, C *self Int1, C *self Int1] = CallByName List.80 List.436 List.437 List.438 List.525 List.526; - ret List.524; - -procedure Num.19 (#Attr.2, #Attr.3): - let Num.292 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.292; + jump List.538 #Derived_gen.3 #Derived_gen.4 #Derived_gen.5 #Derived_gen.6 #Derived_gen.7; procedure Num.22 (#Attr.2, #Attr.3): let Num.293 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; ret Num.293; +procedure Num.51 (#Attr.2, #Attr.3): + let Num.292 : U64 = lowlevel NumAddWrap #Attr.2 #Attr.3; + ret Num.292; + procedure Str.3 (#Attr.2, #Attr.3): let Str.291 : Str = lowlevel StrConcat #Attr.2 #Attr.3; ret Str.291; @@ -54,11 +46,11 @@ procedure Str.3 (#Attr.2, #Attr.3): procedure Test.1 (Test.5): ret Test.5; -procedure Test.11 (#Derived_gen.10, #Derived_gen.11): +procedure Test.11 (#Derived_gen.8, #Derived_gen.9): joinpoint Test.27 Test.12 #Attr.12: let Test.8 : Int1 = UnionAtIndex (Id 2) (Index 1) #Attr.12; let Test.7 : [, C *self Int1, C *self Int1] = UnionAtIndex (Id 2) (Index 0) #Attr.12; - joinpoint #Derived_gen.14: + joinpoint #Derived_gen.12: joinpoint Test.31 Test.29: let Test.30 : U8 = GetTagId Test.7; switch Test.30: @@ -85,16 +77,16 @@ procedure Test.11 (#Derived_gen.10, #Derived_gen.11): jump Test.31 Test.32; in - let #Derived_gen.15 : Int1 = lowlevel RefCountIsUnique #Attr.12; - if #Derived_gen.15 then + let #Derived_gen.13 : Int1 = lowlevel RefCountIsUnique #Attr.12; + if #Derived_gen.13 then free #Attr.12; - jump #Derived_gen.14; + jump #Derived_gen.12; else inc Test.7; decref #Attr.12; - jump #Derived_gen.14; + jump #Derived_gen.12; in - jump Test.27 #Derived_gen.10 #Derived_gen.11; + jump Test.27 #Derived_gen.8 #Derived_gen.9; procedure Test.2 (Test.13): ret Test.13; @@ -125,7 +117,7 @@ procedure Test.6 (Test.7, Test.8, Test.5): procedure Test.9 (Test.10, #Attr.12): let Test.8 : Int1 = UnionAtIndex (Id 1) (Index 1) #Attr.12; let Test.7 : [, C *self Int1, C *self Int1] = UnionAtIndex (Id 1) (Index 0) #Attr.12; - joinpoint #Derived_gen.12: + joinpoint #Derived_gen.14: let Test.37 : U8 = GetTagId Test.7; joinpoint Test.38 Test.36: switch Test.8: @@ -153,14 +145,14 @@ procedure Test.9 (Test.10, #Attr.12): jump Test.38 Test.39; in - let #Derived_gen.13 : Int1 = lowlevel RefCountIsUnique #Attr.12; - if #Derived_gen.13 then + let #Derived_gen.15 : Int1 = lowlevel RefCountIsUnique #Attr.12; + if #Derived_gen.15 then free #Attr.12; - jump #Derived_gen.12; + jump #Derived_gen.14; else inc Test.7; decref #Attr.12; - jump #Derived_gen.12; + jump #Derived_gen.14; procedure Test.0 (): let Test.41 : Int1 = false; diff --git a/crates/compiler/test_mono/generated/dict.txt b/crates/compiler/test_mono/generated/dict.txt index 693107f54b..dc6e7bcd26 100644 --- a/crates/compiler/test_mono/generated/dict.txt +++ b/crates/compiler/test_mono/generated/dict.txt @@ -24,68 +24,68 @@ procedure Dict.4 (Dict.562): dec #Derived_gen.6; ret Dict.100; -procedure List.11 (List.121, List.122): - let List.522 : List I8 = CallByName List.68 List.122; - let List.521 : List I8 = CallByName List.83 List.121 List.122 List.522; - ret List.521; +procedure List.11 (List.124, List.125): + let List.536 : List I8 = CallByName List.68 List.125; + let List.535 : List I8 = CallByName List.84 List.124 List.125 List.536; + ret List.535; -procedure List.11 (List.121, List.122): - let List.534 : List U64 = CallByName List.68 List.122; - let List.533 : List U64 = CallByName List.83 List.121 List.122 List.534; - ret List.533; +procedure List.11 (List.124, List.125): + let List.548 : List U64 = CallByName List.68 List.125; + let List.547 : List U64 = CallByName List.84 List.124 List.125 List.548; + ret List.547; procedure List.68 (#Attr.2): - let List.532 : List I8 = lowlevel ListWithCapacity #Attr.2; - ret List.532; + let List.546 : List I8 = lowlevel ListWithCapacity #Attr.2; + ret List.546; procedure List.68 (#Attr.2): - let List.544 : List U64 = lowlevel ListWithCapacity #Attr.2; - ret List.544; + let List.558 : List U64 = lowlevel ListWithCapacity #Attr.2; + ret List.558; procedure List.71 (#Attr.2, #Attr.3): - let List.529 : List I8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.529; + let List.543 : List I8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.543; procedure List.71 (#Attr.2, #Attr.3): - let List.541 : List U64 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.541; + let List.555 : List U64 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.555; -procedure List.83 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2): - joinpoint List.523 List.123 List.124 List.125: - let List.531 : U64 = 0i64; - let List.525 : Int1 = CallByName Num.24 List.124 List.531; - if List.525 then - let List.530 : U64 = 1i64; - let List.527 : U64 = CallByName Num.20 List.124 List.530; - let List.528 : List I8 = CallByName List.71 List.125 List.123; - jump List.523 List.123 List.527 List.528; +procedure List.84 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2): + joinpoint List.537 List.126 List.127 List.128: + let List.545 : U64 = 0i64; + let List.539 : Int1 = CallByName Num.24 List.127 List.545; + if List.539 then + let List.544 : U64 = 1i64; + let List.541 : U64 = CallByName Num.75 List.127 List.544; + let List.542 : List I8 = CallByName List.71 List.128 List.126; + jump List.537 List.126 List.541 List.542; else - ret List.125; + ret List.128; in - jump List.523 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2; + jump List.537 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2; -procedure List.83 (#Derived_gen.3, #Derived_gen.4, #Derived_gen.5): - joinpoint List.535 List.123 List.124 List.125: - let List.543 : U64 = 0i64; - let List.537 : Int1 = CallByName Num.24 List.124 List.543; - if List.537 then - let List.542 : U64 = 1i64; - let List.539 : U64 = CallByName Num.20 List.124 List.542; - let List.540 : List U64 = CallByName List.71 List.125 List.123; - jump List.535 List.123 List.539 List.540; +procedure List.84 (#Derived_gen.3, #Derived_gen.4, #Derived_gen.5): + joinpoint List.549 List.126 List.127 List.128: + let List.557 : U64 = 0i64; + let List.551 : Int1 = CallByName Num.24 List.127 List.557; + if List.551 then + let List.556 : U64 = 1i64; + let List.553 : U64 = CallByName Num.75 List.127 List.556; + let List.554 : List U64 = CallByName List.71 List.128 List.126; + jump List.549 List.126 List.553 List.554; else - ret List.125; + ret List.128; in - jump List.535 #Derived_gen.3 #Derived_gen.4 #Derived_gen.5; - -procedure Num.20 (#Attr.2, #Attr.3): - let Num.293 : U64 = lowlevel NumSub #Attr.2 #Attr.3; - ret Num.293; + jump List.549 #Derived_gen.3 #Derived_gen.4 #Derived_gen.5; procedure Num.24 (#Attr.2, #Attr.3): let Num.295 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; ret Num.295; +procedure Num.75 (#Attr.2, #Attr.3): + let Num.293 : U64 = lowlevel NumSubWrap #Attr.2 #Attr.3; + ret Num.293; + procedure Test.0 (): let Test.3 : {} = Struct {}; let Test.2 : {List {[], []}, List U64, List I8, U64} = CallByName Dict.1 Test.3; diff --git a/crates/compiler/test_mono/generated/empty_list_of_function_type.txt b/crates/compiler/test_mono/generated/empty_list_of_function_type.txt index 8f46084280..26c5227277 100644 --- a/crates/compiler/test_mono/generated/empty_list_of_function_type.txt +++ b/crates/compiler/test_mono/generated/empty_list_of_function_type.txt @@ -2,27 +2,27 @@ procedure Bool.1 (): let Bool.23 : Int1 = false; ret Bool.23; -procedure List.2 (List.97, List.98): - let List.527 : U64 = CallByName List.6 List.97; - let List.523 : Int1 = CallByName Num.22 List.98 List.527; - if List.523 then - let List.525 : {} = CallByName List.66 List.97 List.98; - dec List.97; - let List.524 : [C {}, C {}] = TagId(1) List.525; - ret List.524; +procedure List.2 (List.100, List.101): + let List.541 : U64 = CallByName List.6 List.100; + let List.537 : Int1 = CallByName Num.22 List.101 List.541; + if List.537 then + let List.539 : {} = CallByName List.66 List.100 List.101; + dec List.100; + let List.538 : [C {}, C {}] = TagId(1) List.539; + ret List.538; else - dec List.97; - let List.522 : {} = Struct {}; - let List.521 : [C {}, C {}] = TagId(0) List.522; - ret List.521; + dec List.100; + let List.536 : {} = Struct {}; + let List.535 : [C {}, C {}] = TagId(0) List.536; + ret List.535; procedure List.6 (#Attr.2): - let List.528 : U64 = lowlevel ListLen #Attr.2; - ret List.528; + let List.542 : U64 = lowlevel ListLen #Attr.2; + ret List.542; procedure List.66 (#Attr.2, #Attr.3): - let List.526 : {} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.526; + let List.540 : {} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.540; procedure Num.22 (#Attr.2, #Attr.3): let Num.292 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; diff --git a/crates/compiler/test_mono/generated/encode.txt b/crates/compiler/test_mono/generated/encode.txt index ce0c8b5b66..2bb6e433d6 100644 --- a/crates/compiler/test_mono/generated/encode.txt +++ b/crates/compiler/test_mono/generated/encode.txt @@ -1,16 +1,16 @@ -procedure List.4 (List.113, List.114): - let List.524 : U64 = 1i64; - let List.522 : List U8 = CallByName List.70 List.113 List.524; - let List.521 : List U8 = CallByName List.71 List.522 List.114; - ret List.521; +procedure List.4 (List.116, List.117): + let List.538 : U64 = 1i64; + let List.536 : List U8 = CallByName List.70 List.116 List.538; + let List.535 : List U8 = CallByName List.71 List.536 List.117; + ret List.535; procedure List.70 (#Attr.2, #Attr.3): - let List.525 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.525; + let List.539 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.539; procedure List.71 (#Attr.2, #Attr.3): - let List.523 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.523; + let List.537 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.537; procedure Test.23 (Test.24, Test.35, Test.22): let Test.37 : List U8 = CallByName List.4 Test.24 Test.22; diff --git a/crates/compiler/test_mono/generated/encode_derived_nested_record_string.txt b/crates/compiler/test_mono/generated/encode_derived_nested_record_string.txt index da00523cb6..8692bb997b 100644 --- a/crates/compiler/test_mono/generated/encode_derived_nested_record_string.txt +++ b/crates/compiler/test_mono/generated/encode_derived_nested_record_string.txt @@ -78,271 +78,247 @@ procedure Encode.26 (Encode.105, Encode.106): ret Encode.108; procedure List.13 (#Attr.2, #Attr.3): - let List.689 : List Str = lowlevel ListPrepend #Attr.2 #Attr.3; - ret List.689; + let List.679 : List Str = lowlevel ListPrepend #Attr.2 #Attr.3; + ret List.679; -procedure List.145 (List.146, List.147, List.144): - let List.569 : {List U8, U64} = CallByName TotallyNotJson.237 List.146 List.147 List.144; - ret List.569; +procedure List.18 (List.145, List.146, List.147): + let List.565 : U64 = 0i64; + let List.566 : U64 = CallByName List.6 List.145; + let List.564 : {List U8, U64} = CallByName List.86 List.145 List.146 List.147 List.565 List.566; + ret List.564; -procedure List.145 (List.146, List.147, List.144): - let List.637 : {List U8, U64} = CallByName TotallyNotJson.237 List.146 List.147 List.144; - ret List.637; +procedure List.18 (List.145, List.146, List.147): + let List.625 : U64 = 0i64; + let List.626 : U64 = CallByName List.6 List.145; + let List.624 : {List U8, U64} = CallByName List.86 List.145 List.146 List.147 List.625 List.626; + ret List.624; -procedure List.145 (List.146, List.147, List.144): - let List.657 : List U8 = CallByName TotallyNotJson.215 List.146 List.147; - ret List.657; +procedure List.18 (List.145, List.146, List.147): + let List.637 : U64 = 0i64; + let List.638 : U64 = CallByName List.6 List.145; + let List.636 : List U8 = CallByName List.86 List.145 List.146 List.147 List.637 List.638; + ret List.636; -procedure List.18 (List.142, List.143, List.144): - let List.550 : {List U8, U64} = CallByName List.93 List.142 List.143 List.144; - ret List.550; - -procedure List.18 (List.142, List.143, List.144): - let List.618 : {List U8, U64} = CallByName List.93 List.142 List.143 List.144; - ret List.618; - -procedure List.18 (List.142, List.143, List.144): - let List.638 : List U8 = CallByName List.93 List.142 List.143 List.144; - ret List.638; - -procedure List.26 (List.159, List.160, List.161): - let List.706 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.93 List.159 List.160 List.161; - let List.709 : U8 = 1i64; - let List.710 : U8 = GetTagId List.706; - let List.711 : Int1 = lowlevel Eq List.709 List.710; - if List.711 then - let List.162 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.706; - ret List.162; +procedure List.26 (List.172, List.173, List.174): + let List.696 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.96 List.172 List.173 List.174; + let List.699 : U8 = 1i64; + let List.700 : U8 = GetTagId List.696; + let List.701 : Int1 = lowlevel Eq List.699 List.700; + if List.701 then + let List.175 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.696; + ret List.175; else - let List.163 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.706; - ret List.163; + let List.176 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.696; + ret List.176; procedure List.31 (#Attr.2, #Attr.3): - let List.671 : List Str = lowlevel ListDropAt #Attr.2 #Attr.3; - ret List.671; + let List.661 : List Str = lowlevel ListDropAt #Attr.2 #Attr.3; + ret List.661; -procedure List.38 (List.298): - let List.679 : U64 = 0i64; - let List.678 : List Str = CallByName List.31 List.298 List.679; +procedure List.38 (List.311): + let List.669 : U64 = 0i64; + let List.668 : List Str = CallByName List.31 List.311 List.669; + ret List.668; + +procedure List.4 (List.116, List.117): + let List.620 : U64 = 1i64; + let List.619 : List Str = CallByName List.70 List.116 List.620; + let List.618 : List Str = CallByName List.71 List.619 List.117; + ret List.618; + +procedure List.4 (List.116, List.117): + let List.623 : U64 = 1i64; + let List.622 : List U8 = CallByName List.70 List.116 List.623; + let List.621 : List U8 = CallByName List.71 List.622 List.117; + ret List.621; + +procedure List.49 (List.390, List.391): + let List.688 : U64 = StructAtIndex 0 List.391; + let List.689 : U64 = 0i64; + let List.686 : Int1 = CallByName Bool.11 List.688 List.689; + if List.686 then + dec List.390; + let List.687 : List U8 = Array []; + ret List.687; + else + let List.683 : U64 = StructAtIndex 1 List.391; + let List.684 : U64 = StructAtIndex 0 List.391; + let List.682 : List U8 = CallByName List.72 List.390 List.683 List.684; + ret List.682; + +procedure List.52 (List.405, List.406): + let List.407 : U64 = CallByName List.6 List.405; + joinpoint List.694 List.408: + let List.692 : U64 = 0i64; + let List.691 : {U64, U64} = Struct {List.408, List.692}; + inc List.405; + let List.409 : List U8 = CallByName List.49 List.405 List.691; + let List.690 : U64 = CallByName Num.75 List.407 List.408; + let List.681 : {U64, U64} = Struct {List.690, List.408}; + let List.410 : List U8 = CallByName List.49 List.405 List.681; + let List.680 : {List U8, List U8} = Struct {List.409, List.410}; + ret List.680; + in + let List.695 : Int1 = CallByName Num.24 List.407 List.406; + if List.695 then + jump List.694 List.406; + else + jump List.694 List.407; + +procedure List.6 (#Attr.2): + let List.594 : U64 = lowlevel ListLen #Attr.2; + ret List.594; + +procedure List.6 (#Attr.2): + let List.675 : U64 = lowlevel ListLen #Attr.2; + ret List.675; + +procedure List.6 (#Attr.2): + let List.676 : U64 = lowlevel ListLen #Attr.2; + ret List.676; + +procedure List.6 (#Attr.2): + let List.678 : U64 = lowlevel ListLen #Attr.2; ret List.678; -procedure List.4 (List.113, List.114): - let List.614 : U64 = 1i64; - let List.613 : List Str = CallByName List.70 List.113 List.614; - let List.612 : List Str = CallByName List.71 List.613 List.114; - ret List.612; - -procedure List.4 (List.113, List.114): - let List.617 : U64 = 1i64; - let List.616 : List U8 = CallByName List.70 List.113 List.617; - let List.615 : List U8 = CallByName List.71 List.616 List.114; - ret List.615; - -procedure List.49 (List.376, List.377): - let List.698 : U64 = StructAtIndex 0 List.377; - let List.699 : U64 = 0i64; - let List.696 : Int1 = CallByName Bool.11 List.698 List.699; - if List.696 then - dec List.376; - let List.697 : List U8 = Array []; - ret List.697; - else - let List.693 : U64 = StructAtIndex 1 List.377; - let List.694 : U64 = StructAtIndex 0 List.377; - let List.692 : List U8 = CallByName List.72 List.376 List.693 List.694; - ret List.692; - -procedure List.52 (List.391, List.392): - let List.393 : U64 = CallByName List.6 List.391; - joinpoint List.704 List.394: - let List.702 : U64 = 0i64; - let List.701 : {U64, U64} = Struct {List.394, List.702}; - inc List.391; - let List.395 : List U8 = CallByName List.49 List.391 List.701; - let List.700 : U64 = CallByName Num.20 List.393 List.394; - let List.691 : {U64, U64} = Struct {List.700, List.394}; - let List.396 : List U8 = CallByName List.49 List.391 List.691; - let List.690 : {List U8, List U8} = Struct {List.395, List.396}; - ret List.690; - in - let List.705 : Int1 = CallByName Num.24 List.393 List.392; - if List.705 then - jump List.704 List.392; - else - jump List.704 List.393; - -procedure List.6 (#Attr.2): - let List.588 : U64 = lowlevel ListLen #Attr.2; - ret List.588; - -procedure List.6 (#Attr.2): - let List.685 : U64 = lowlevel ListLen #Attr.2; - ret List.685; - -procedure List.6 (#Attr.2): - let List.686 : U64 = lowlevel ListLen #Attr.2; - ret List.686; - -procedure List.6 (#Attr.2): - let List.688 : U64 = lowlevel ListLen #Attr.2; - ret List.688; - procedure List.66 (#Attr.2, #Attr.3): - let List.566 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.566; + let List.574 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.574; procedure List.66 (#Attr.2, #Attr.3): let List.634 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; ret List.634; procedure List.66 (#Attr.2, #Attr.3): - let List.654 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.654; + let List.646 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.646; procedure List.68 (#Attr.2): - let List.681 : List Str = lowlevel ListWithCapacity #Attr.2; - ret List.681; + let List.671 : List Str = lowlevel ListWithCapacity #Attr.2; + ret List.671; procedure List.68 (#Attr.2): - let List.683 : List U8 = lowlevel ListWithCapacity #Attr.2; - ret List.683; + let List.673 : List U8 = lowlevel ListWithCapacity #Attr.2; + ret List.673; procedure List.70 (#Attr.2, #Attr.3): - let List.594 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.594; + let List.600 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.600; procedure List.70 (#Attr.2, #Attr.3): - let List.611 : List Str = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.611; + let List.617 : List Str = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.617; procedure List.71 (#Attr.2, #Attr.3): - let List.592 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.592; + let List.598 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.598; procedure List.71 (#Attr.2, #Attr.3): - let List.609 : List Str = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.609; + let List.615 : List Str = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.615; procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.695 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.695; + let List.685 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.685; procedure List.8 (#Attr.2, #Attr.3): - let List.660 : List Str = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.660; + let List.650 : List Str = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.650; procedure List.8 (#Attr.2, #Attr.3): - let List.668 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.668; + let List.658 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.658; procedure List.80 (#Derived_gen.30, #Derived_gen.31, #Derived_gen.32, #Derived_gen.33, #Derived_gen.34): - joinpoint List.715 List.439 List.440 List.441 List.442 List.443: - let List.717 : Int1 = CallByName Num.22 List.442 List.443; - if List.717 then - let List.726 : U8 = CallByName List.66 List.439 List.442; - let List.718 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.440 List.726; - let List.723 : U8 = 1i64; - let List.724 : U8 = GetTagId List.718; - let List.725 : Int1 = lowlevel Eq List.723 List.724; - if List.725 then - let List.444 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.718; - let List.721 : U64 = 1i64; - let List.720 : U64 = CallByName Num.19 List.442 List.721; - jump List.715 List.439 List.444 List.441 List.720 List.443; + joinpoint List.705 List.453 List.454 List.455 List.456 List.457: + let List.707 : Int1 = CallByName Num.22 List.456 List.457; + if List.707 then + let List.716 : U8 = CallByName List.66 List.453 List.456; + let List.708 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.454 List.716; + let List.713 : U8 = 1i64; + let List.714 : U8 = GetTagId List.708; + let List.715 : Int1 = lowlevel Eq List.713 List.714; + if List.715 then + let List.458 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.708; + let List.711 : U64 = 1i64; + let List.710 : U64 = CallByName Num.51 List.456 List.711; + jump List.705 List.453 List.458 List.455 List.710 List.457; else - dec List.439; - let List.445 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.718; - let List.722 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.445; - ret List.722; + dec List.453; + let List.459 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.708; + let List.712 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.459; + ret List.712; else - dec List.439; - let List.716 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.440; - ret List.716; + dec List.453; + let List.706 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.454; + ret List.706; in - jump List.715 #Derived_gen.30 #Derived_gen.31 #Derived_gen.32 #Derived_gen.33 #Derived_gen.34; + jump List.705 #Derived_gen.30 #Derived_gen.31 #Derived_gen.32 #Derived_gen.33 #Derived_gen.34; -procedure List.80 (#Derived_gen.36, #Derived_gen.37, #Derived_gen.38, #Derived_gen.39, #Derived_gen.40): - joinpoint List.644 List.439 List.440 List.441 List.442 List.443: - let List.646 : Int1 = CallByName Num.22 List.442 List.443; - if List.646 then - let List.653 : U8 = CallByName List.66 List.439 List.442; - let List.647 : List U8 = CallByName List.145 List.440 List.653 List.441; - let List.650 : U64 = 1i64; - let List.649 : U64 = CallByName Num.19 List.442 List.650; - jump List.644 List.439 List.647 List.441 List.649 List.443; +procedure List.86 (#Derived_gen.35, #Derived_gen.36, #Derived_gen.37, #Derived_gen.38, #Derived_gen.39): + joinpoint List.567 List.148 List.149 List.150 List.151 List.152: + let List.569 : Int1 = CallByName Num.22 List.151 List.152; + if List.569 then + let List.573 : {Str, Str} = CallByName List.66 List.148 List.151; + inc List.573; + let List.153 : {List U8, U64} = CallByName TotallyNotJson.237 List.149 List.573 List.150; + let List.572 : U64 = 1i64; + let List.571 : U64 = CallByName Num.51 List.151 List.572; + jump List.567 List.148 List.153 List.150 List.571 List.152; else - dec List.439; - ret List.440; + dec List.148; + ret List.149; in - jump List.644 #Derived_gen.36 #Derived_gen.37 #Derived_gen.38 #Derived_gen.39 #Derived_gen.40; + jump List.567 #Derived_gen.35 #Derived_gen.36 #Derived_gen.37 #Derived_gen.38 #Derived_gen.39; -procedure List.80 (#Derived_gen.41, #Derived_gen.42, #Derived_gen.43, #Derived_gen.44, #Derived_gen.45): - joinpoint List.624 List.439 List.440 List.441 List.442 List.443: - let List.626 : Int1 = CallByName Num.22 List.442 List.443; - if List.626 then - let List.633 : {Str, Str} = CallByName List.66 List.439 List.442; +procedure List.86 (#Derived_gen.46, #Derived_gen.47, #Derived_gen.48, #Derived_gen.49, #Derived_gen.50): + joinpoint List.639 List.148 List.149 List.150 List.151 List.152: + let List.641 : Int1 = CallByName Num.22 List.151 List.152; + if List.641 then + let List.645 : U8 = CallByName List.66 List.148 List.151; + let List.153 : List U8 = CallByName TotallyNotJson.215 List.149 List.645; + let List.644 : U64 = 1i64; + let List.643 : U64 = CallByName Num.51 List.151 List.644; + jump List.639 List.148 List.153 List.150 List.643 List.152; + else + dec List.148; + ret List.149; + in + jump List.639 #Derived_gen.46 #Derived_gen.47 #Derived_gen.48 #Derived_gen.49 #Derived_gen.50; + +procedure List.86 (#Derived_gen.52, #Derived_gen.53, #Derived_gen.54, #Derived_gen.55, #Derived_gen.56): + joinpoint List.627 List.148 List.149 List.150 List.151 List.152: + let List.629 : Int1 = CallByName Num.22 List.151 List.152; + if List.629 then + let List.633 : {Str, Str} = CallByName List.66 List.148 List.151; inc List.633; - let List.627 : {List U8, U64} = CallByName List.145 List.440 List.633 List.441; - let List.630 : U64 = 1i64; - let List.629 : U64 = CallByName Num.19 List.442 List.630; - jump List.624 List.439 List.627 List.441 List.629 List.443; + let List.153 : {List U8, U64} = CallByName TotallyNotJson.237 List.149 List.633 List.150; + let List.632 : U64 = 1i64; + let List.631 : U64 = CallByName Num.51 List.151 List.632; + jump List.627 List.148 List.153 List.150 List.631 List.152; else - dec List.439; - ret List.440; + dec List.148; + ret List.149; in - jump List.624 #Derived_gen.41 #Derived_gen.42 #Derived_gen.43 #Derived_gen.44 #Derived_gen.45; + jump List.627 #Derived_gen.52 #Derived_gen.53 #Derived_gen.54 #Derived_gen.55 #Derived_gen.56; -procedure List.80 (#Derived_gen.52, #Derived_gen.53, #Derived_gen.54, #Derived_gen.55, #Derived_gen.56): - joinpoint List.556 List.439 List.440 List.441 List.442 List.443: - let List.558 : Int1 = CallByName Num.22 List.442 List.443; - if List.558 then - let List.565 : {Str, Str} = CallByName List.66 List.439 List.442; - inc List.565; - let List.559 : {List U8, U64} = CallByName List.145 List.440 List.565 List.441; - let List.562 : U64 = 1i64; - let List.561 : U64 = CallByName Num.19 List.442 List.562; - jump List.556 List.439 List.559 List.441 List.561 List.443; - else - dec List.439; - ret List.440; - in - jump List.556 #Derived_gen.52 #Derived_gen.53 #Derived_gen.54 #Derived_gen.55 #Derived_gen.56; - -procedure List.93 (List.436, List.437, List.438): - let List.554 : U64 = 0i64; - let List.555 : U64 = CallByName List.6 List.436; - let List.553 : {List U8, U64} = CallByName List.80 List.436 List.437 List.438 List.554 List.555; - ret List.553; - -procedure List.93 (List.436, List.437, List.438): - let List.622 : U64 = 0i64; - let List.623 : U64 = CallByName List.6 List.436; - let List.621 : {List U8, U64} = CallByName List.80 List.436 List.437 List.438 List.622 List.623; - ret List.621; - -procedure List.93 (List.436, List.437, List.438): - let List.642 : U64 = 0i64; - let List.643 : U64 = CallByName List.6 List.436; - let List.641 : List U8 = CallByName List.80 List.436 List.437 List.438 List.642 List.643; - ret List.641; - -procedure List.93 (List.436, List.437, List.438): - let List.713 : U64 = 0i64; - let List.714 : U64 = CallByName List.6 List.436; - let List.712 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.436 List.437 List.438 List.713 List.714; - ret List.712; +procedure List.96 (List.450, List.451, List.452): + let List.703 : U64 = 0i64; + let List.704 : U64 = CallByName List.6 List.450; + let List.702 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.450 List.451 List.452 List.703 List.704; + ret List.702; procedure Num.127 (#Attr.2): let Num.307 : U8 = lowlevel NumIntCast #Attr.2; ret Num.307; procedure Num.19 (#Attr.2, #Attr.3): - let Num.316 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.316; + let Num.311 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.311; procedure Num.20 (#Attr.2, #Attr.3): - let Num.320 : U64 = lowlevel NumSub #Attr.2 #Attr.3; - ret Num.320; + let Num.308 : U64 = lowlevel NumSub #Attr.2 #Attr.3; + ret Num.308; procedure Num.21 (#Attr.2, #Attr.3): let Num.313 : U64 = lowlevel NumMul #Attr.2 #Attr.3; @@ -356,6 +332,14 @@ procedure Num.24 (#Attr.2, #Attr.3): let Num.321 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; ret Num.321; +procedure Num.51 (#Attr.2, #Attr.3): + let Num.316 : U64 = lowlevel NumAddWrap #Attr.2 #Attr.3; + ret Num.316; + +procedure Num.75 (#Attr.2, #Attr.3): + let Num.320 : U64 = lowlevel NumSubWrap #Attr.2 #Attr.3; + ret Num.320; + procedure Num.94 (#Attr.2, #Attr.3): let Num.312 : U64 = lowlevel NumDivCeilUnchecked #Attr.2 #Attr.3; ret Num.312; @@ -388,8 +372,8 @@ procedure Str.9 (Str.79): else let Str.291 : U8 = StructAtIndex 3 Str.80; let Str.292 : U64 = StructAtIndex 0 Str.80; - let #Derived_gen.57 : Str = StructAtIndex 1 Str.80; - dec #Derived_gen.57; + let #Derived_gen.58 : Str = StructAtIndex 1 Str.80; + dec #Derived_gen.58; let Str.290 : {U64, U8} = Struct {Str.292, Str.291}; let Str.289 : [C {U64, U8}, C Str] = TagId(0) Str.290; ret Str.289; @@ -1019,8 +1003,8 @@ procedure TotallyNotJson.102 (TotallyNotJson.852): else let TotallyNotJson.1691 : Str = "Z"; let TotallyNotJson.1692 : Int1 = lowlevel Eq TotallyNotJson.1691 TotallyNotJson.852; - dec TotallyNotJson.852; dec TotallyNotJson.1691; + dec TotallyNotJson.852; if TotallyNotJson.1692 then let TotallyNotJson.1689 : Int1 = CallByName Bool.2; ret TotallyNotJson.1689; @@ -1093,10 +1077,6 @@ procedure TotallyNotJson.189 (TotallyNotJson.1930, TotallyNotJson.192): ret TotallyNotJson.1955; -procedure TotallyNotJson.2 (): - let TotallyNotJson.1172 : [C , C [], C , C , C , C ] = TagId(2) ; - ret TotallyNotJson.1172; - procedure TotallyNotJson.215 (TotallyNotJson.216, TotallyNotJson.217): let TotallyNotJson.1901 : List U8 = CallByName TotallyNotJson.27 TotallyNotJson.217; let TotallyNotJson.1900 : List U8 = CallByName List.8 TotallyNotJson.216 TotallyNotJson.1901; @@ -1300,6 +1280,10 @@ procedure TotallyNotJson.29 (TotallyNotJson.233): let TotallyNotJson.1526 : List {Str, Str} = CallByName Encode.23 TotallyNotJson.233; ret TotallyNotJson.1526; +procedure TotallyNotJson.8 (): + let TotallyNotJson.1172 : [C , C [], C , C , C , C ] = TagId(2) ; + ret TotallyNotJson.1172; + procedure TotallyNotJson.82 (TotallyNotJson.802, TotallyNotJson.803): let TotallyNotJson.1873 : U8 = GetTagId TotallyNotJson.803; switch TotallyNotJson.1873: @@ -1331,14 +1315,14 @@ procedure TotallyNotJson.82 (TotallyNotJson.802, TotallyNotJson.803): procedure TotallyNotJson.832 (TotallyNotJson.1493): let TotallyNotJson.1845 : List Str = StructAtIndex 1 TotallyNotJson.1493; - let #Derived_gen.58 : List Str = StructAtIndex 0 TotallyNotJson.1493; - dec #Derived_gen.58; + let #Derived_gen.59 : List Str = StructAtIndex 0 TotallyNotJson.1493; + dec #Derived_gen.59; ret TotallyNotJson.1845; procedure TotallyNotJson.840 (TotallyNotJson.1214): let TotallyNotJson.1566 : List Str = StructAtIndex 1 TotallyNotJson.1214; - let #Derived_gen.59 : List Str = StructAtIndex 0 TotallyNotJson.1214; - dec #Derived_gen.59; + let #Derived_gen.57 : List Str = StructAtIndex 0 TotallyNotJson.1214; + dec #Derived_gen.57; ret TotallyNotJson.1566; procedure TotallyNotJson.87 (TotallyNotJson.809): @@ -1389,11 +1373,11 @@ procedure TotallyNotJson.95 (TotallyNotJson.829): let TotallyNotJson.1840 : List Str = CallByName TotallyNotJson.832 TotallyNotJson.1842; let TotallyNotJson.1841 : Str = ""; let TotallyNotJson.1839 : Str = CallByName Str.4 TotallyNotJson.1840 TotallyNotJson.1841; - dec TotallyNotJson.1840; dec TotallyNotJson.1841; + dec TotallyNotJson.1840; ret TotallyNotJson.1839; -procedure TotallyNotJson.96 (#Derived_gen.29): +procedure TotallyNotJson.96 (#Derived_gen.51): joinpoint TotallyNotJson.1847 TotallyNotJson.1168: let TotallyNotJson.834 : List Str = StructAtIndex 0 TotallyNotJson.1168; let TotallyNotJson.833 : List Str = StructAtIndex 1 TotallyNotJson.1168; @@ -1429,7 +1413,7 @@ procedure TotallyNotJson.96 (#Derived_gen.29): let TotallyNotJson.1848 : {List Str, List Str} = Struct {TotallyNotJson.834, TotallyNotJson.833}; ret TotallyNotJson.1848; in - jump TotallyNotJson.1847 #Derived_gen.29; + jump TotallyNotJson.1847 #Derived_gen.51; procedure TotallyNotJson.97 (TotallyNotJson.837): let TotallyNotJson.838 : List Str = CallByName Str.55 TotallyNotJson.837; @@ -1446,7 +1430,7 @@ procedure TotallyNotJson.97 (TotallyNotJson.837): dec TotallyNotJson.1562; ret TotallyNotJson.1560; -procedure TotallyNotJson.98 (#Derived_gen.35): +procedure TotallyNotJson.98 (#Derived_gen.29): joinpoint TotallyNotJson.1568 TotallyNotJson.1169: let TotallyNotJson.842 : List Str = StructAtIndex 0 TotallyNotJson.1169; let TotallyNotJson.841 : List Str = StructAtIndex 1 TotallyNotJson.1169; @@ -1482,11 +1466,11 @@ procedure TotallyNotJson.98 (#Derived_gen.35): let TotallyNotJson.1569 : {List Str, List Str} = Struct {TotallyNotJson.842, TotallyNotJson.841}; ret TotallyNotJson.1569; in - jump TotallyNotJson.1568 #Derived_gen.35; + jump TotallyNotJson.1568 #Derived_gen.29; procedure Test.0 (): let Test.12 : Str = "bar"; - let Test.10 : [C , C [], C , C , C , C ] = CallByName TotallyNotJson.2; + let Test.10 : [C , C [], C , C , C , C ] = CallByName TotallyNotJson.8; let Test.8 : List U8 = CallByName Encode.26 Test.12 Test.10; let Test.1 : [C {U64, U8}, C Str] = CallByName Str.9 Test.8; let Test.5 : U8 = 1i64; diff --git a/crates/compiler/test_mono/generated/encode_derived_record_one_field_string.txt b/crates/compiler/test_mono/generated/encode_derived_record_one_field_string.txt index 81f7d70c33..22f61dea1f 100644 --- a/crates/compiler/test_mono/generated/encode_derived_record_one_field_string.txt +++ b/crates/compiler/test_mono/generated/encode_derived_record_one_field_string.txt @@ -51,233 +51,217 @@ procedure Encode.26 (Encode.105, Encode.106): ret Encode.108; procedure List.13 (#Attr.2, #Attr.3): - let List.621 : List Str = lowlevel ListPrepend #Attr.2 #Attr.3; - ret List.621; + let List.619 : List Str = lowlevel ListPrepend #Attr.2 #Attr.3; + ret List.619; -procedure List.145 (List.146, List.147, List.144): - let List.569 : {List U8, U64} = CallByName TotallyNotJson.237 List.146 List.147 List.144; - ret List.569; +procedure List.18 (List.145, List.146, List.147): + let List.565 : U64 = 0i64; + let List.566 : U64 = CallByName List.6 List.145; + let List.564 : {List U8, U64} = CallByName List.86 List.145 List.146 List.147 List.565 List.566; + ret List.564; -procedure List.145 (List.146, List.147, List.144): - let List.589 : List U8 = CallByName TotallyNotJson.215 List.146 List.147; - ret List.589; +procedure List.18 (List.145, List.146, List.147): + let List.577 : U64 = 0i64; + let List.578 : U64 = CallByName List.6 List.145; + let List.576 : List U8 = CallByName List.86 List.145 List.146 List.147 List.577 List.578; + ret List.576; -procedure List.18 (List.142, List.143, List.144): - let List.550 : {List U8, U64} = CallByName List.93 List.142 List.143 List.144; - ret List.550; - -procedure List.18 (List.142, List.143, List.144): - let List.570 : List U8 = CallByName List.93 List.142 List.143 List.144; - ret List.570; - -procedure List.26 (List.159, List.160, List.161): - let List.638 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.93 List.159 List.160 List.161; - let List.641 : U8 = 1i64; - let List.642 : U8 = GetTagId List.638; - let List.643 : Int1 = lowlevel Eq List.641 List.642; - if List.643 then - let List.162 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.638; - ret List.162; +procedure List.26 (List.172, List.173, List.174): + let List.636 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.96 List.172 List.173 List.174; + let List.639 : U8 = 1i64; + let List.640 : U8 = GetTagId List.636; + let List.641 : Int1 = lowlevel Eq List.639 List.640; + if List.641 then + let List.175 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.636; + ret List.175; else - let List.163 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.638; - ret List.163; + let List.176 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.636; + ret List.176; procedure List.31 (#Attr.2, #Attr.3): - let List.603 : List Str = lowlevel ListDropAt #Attr.2 #Attr.3; - ret List.603; + let List.601 : List Str = lowlevel ListDropAt #Attr.2 #Attr.3; + ret List.601; -procedure List.38 (List.298): - let List.611 : U64 = 0i64; - let List.610 : List Str = CallByName List.31 List.298 List.611; - ret List.610; +procedure List.38 (List.311): + let List.609 : U64 = 0i64; + let List.608 : List Str = CallByName List.31 List.311 List.609; + ret List.608; -procedure List.4 (List.113, List.114): - let List.546 : U64 = 1i64; - let List.545 : List Str = CallByName List.70 List.113 List.546; - let List.544 : List Str = CallByName List.71 List.545 List.114; - ret List.544; +procedure List.4 (List.116, List.117): + let List.560 : U64 = 1i64; + let List.559 : List Str = CallByName List.70 List.116 List.560; + let List.558 : List Str = CallByName List.71 List.559 List.117; + ret List.558; -procedure List.4 (List.113, List.114): - let List.549 : U64 = 1i64; - let List.548 : List U8 = CallByName List.70 List.113 List.549; - let List.547 : List U8 = CallByName List.71 List.548 List.114; - ret List.547; +procedure List.4 (List.116, List.117): + let List.563 : U64 = 1i64; + let List.562 : List U8 = CallByName List.70 List.116 List.563; + let List.561 : List U8 = CallByName List.71 List.562 List.117; + ret List.561; -procedure List.49 (List.376, List.377): - let List.630 : U64 = StructAtIndex 0 List.377; - let List.631 : U64 = 0i64; - let List.628 : Int1 = CallByName Bool.11 List.630 List.631; - if List.628 then - dec List.376; - let List.629 : List U8 = Array []; - ret List.629; +procedure List.49 (List.390, List.391): + let List.628 : U64 = StructAtIndex 0 List.391; + let List.629 : U64 = 0i64; + let List.626 : Int1 = CallByName Bool.11 List.628 List.629; + if List.626 then + dec List.390; + let List.627 : List U8 = Array []; + ret List.627; else - let List.625 : U64 = StructAtIndex 1 List.377; - let List.626 : U64 = StructAtIndex 0 List.377; - let List.624 : List U8 = CallByName List.72 List.376 List.625 List.626; - ret List.624; - -procedure List.52 (List.391, List.392): - let List.393 : U64 = CallByName List.6 List.391; - joinpoint List.636 List.394: - let List.634 : U64 = 0i64; - let List.633 : {U64, U64} = Struct {List.394, List.634}; - inc List.391; - let List.395 : List U8 = CallByName List.49 List.391 List.633; - let List.632 : U64 = CallByName Num.20 List.393 List.394; - let List.623 : {U64, U64} = Struct {List.632, List.394}; - let List.396 : List U8 = CallByName List.49 List.391 List.623; - let List.622 : {List U8, List U8} = Struct {List.395, List.396}; + let List.623 : U64 = StructAtIndex 1 List.391; + let List.624 : U64 = StructAtIndex 0 List.391; + let List.622 : List U8 = CallByName List.72 List.390 List.623 List.624; ret List.622; + +procedure List.52 (List.405, List.406): + let List.407 : U64 = CallByName List.6 List.405; + joinpoint List.634 List.408: + let List.632 : U64 = 0i64; + let List.631 : {U64, U64} = Struct {List.408, List.632}; + inc List.405; + let List.409 : List U8 = CallByName List.49 List.405 List.631; + let List.630 : U64 = CallByName Num.75 List.407 List.408; + let List.621 : {U64, U64} = Struct {List.630, List.408}; + let List.410 : List U8 = CallByName List.49 List.405 List.621; + let List.620 : {List U8, List U8} = Struct {List.409, List.410}; + ret List.620; in - let List.637 : Int1 = CallByName Num.24 List.393 List.392; - if List.637 then - jump List.636 List.392; + let List.635 : Int1 = CallByName Num.24 List.407 List.406; + if List.635 then + jump List.634 List.406; else - jump List.636 List.393; + jump List.634 List.407; procedure List.6 (#Attr.2): - let List.617 : U64 = lowlevel ListLen #Attr.2; - ret List.617; + let List.615 : U64 = lowlevel ListLen #Attr.2; + ret List.615; + +procedure List.6 (#Attr.2): + let List.616 : U64 = lowlevel ListLen #Attr.2; + ret List.616; procedure List.6 (#Attr.2): let List.618 : U64 = lowlevel ListLen #Attr.2; ret List.618; -procedure List.6 (#Attr.2): - let List.620 : U64 = lowlevel ListLen #Attr.2; - ret List.620; - procedure List.66 (#Attr.2, #Attr.3): - let List.566 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.566; + let List.574 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.574; procedure List.66 (#Attr.2, #Attr.3): let List.586 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; ret List.586; procedure List.68 (#Attr.2): - let List.613 : List Str = lowlevel ListWithCapacity #Attr.2; - ret List.613; + let List.611 : List Str = lowlevel ListWithCapacity #Attr.2; + ret List.611; procedure List.68 (#Attr.2): - let List.615 : List U8 = lowlevel ListWithCapacity #Attr.2; - ret List.615; + let List.613 : List U8 = lowlevel ListWithCapacity #Attr.2; + ret List.613; procedure List.70 (#Attr.2, #Attr.3): - let List.526 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.526; + let List.540 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.540; procedure List.70 (#Attr.2, #Attr.3): - let List.543 : List Str = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.543; + let List.557 : List Str = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.557; procedure List.71 (#Attr.2, #Attr.3): - let List.524 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.524; + let List.538 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.538; procedure List.71 (#Attr.2, #Attr.3): - let List.541 : List Str = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.541; + let List.555 : List Str = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.555; procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.627 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.627; + let List.625 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.625; procedure List.8 (#Attr.2, #Attr.3): - let List.592 : List Str = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.592; + let List.590 : List Str = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.590; procedure List.8 (#Attr.2, #Attr.3): - let List.600 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.600; + let List.598 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.598; -procedure List.80 (#Derived_gen.10, #Derived_gen.11, #Derived_gen.12, #Derived_gen.13, #Derived_gen.14): - joinpoint List.647 List.439 List.440 List.441 List.442 List.443: - let List.649 : Int1 = CallByName Num.22 List.442 List.443; - if List.649 then - let List.658 : U8 = CallByName List.66 List.439 List.442; - let List.650 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.440 List.658; - let List.655 : U8 = 1i64; - let List.656 : U8 = GetTagId List.650; - let List.657 : Int1 = lowlevel Eq List.655 List.656; - if List.657 then - let List.444 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.650; - let List.653 : U64 = 1i64; - let List.652 : U64 = CallByName Num.19 List.442 List.653; - jump List.647 List.439 List.444 List.441 List.652 List.443; +procedure List.80 (#Derived_gen.11, #Derived_gen.12, #Derived_gen.13, #Derived_gen.14, #Derived_gen.15): + joinpoint List.645 List.453 List.454 List.455 List.456 List.457: + let List.647 : Int1 = CallByName Num.22 List.456 List.457; + if List.647 then + let List.656 : U8 = CallByName List.66 List.453 List.456; + let List.648 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.454 List.656; + let List.653 : U8 = 1i64; + let List.654 : U8 = GetTagId List.648; + let List.655 : Int1 = lowlevel Eq List.653 List.654; + if List.655 then + let List.458 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.648; + let List.651 : U64 = 1i64; + let List.650 : U64 = CallByName Num.51 List.456 List.651; + jump List.645 List.453 List.458 List.455 List.650 List.457; else - dec List.439; - let List.445 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.650; - let List.654 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.445; - ret List.654; + dec List.453; + let List.459 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.648; + let List.652 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.459; + ret List.652; else - dec List.439; - let List.648 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.440; - ret List.648; + dec List.453; + let List.646 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.454; + ret List.646; in - jump List.647 #Derived_gen.10 #Derived_gen.11 #Derived_gen.12 #Derived_gen.13 #Derived_gen.14; + jump List.645 #Derived_gen.11 #Derived_gen.12 #Derived_gen.13 #Derived_gen.14 #Derived_gen.15; -procedure List.80 (#Derived_gen.18, #Derived_gen.19, #Derived_gen.20, #Derived_gen.21, #Derived_gen.22): - joinpoint List.576 List.439 List.440 List.441 List.442 List.443: - let List.578 : Int1 = CallByName Num.22 List.442 List.443; - if List.578 then - let List.585 : U8 = CallByName List.66 List.439 List.442; - let List.579 : List U8 = CallByName List.145 List.440 List.585 List.441; - let List.582 : U64 = 1i64; - let List.581 : U64 = CallByName Num.19 List.442 List.582; - jump List.576 List.439 List.579 List.441 List.581 List.443; +procedure List.86 (#Derived_gen.26, #Derived_gen.27, #Derived_gen.28, #Derived_gen.29, #Derived_gen.30): + joinpoint List.579 List.148 List.149 List.150 List.151 List.152: + let List.581 : Int1 = CallByName Num.22 List.151 List.152; + if List.581 then + let List.585 : U8 = CallByName List.66 List.148 List.151; + let List.153 : List U8 = CallByName TotallyNotJson.215 List.149 List.585; + let List.584 : U64 = 1i64; + let List.583 : U64 = CallByName Num.51 List.151 List.584; + jump List.579 List.148 List.153 List.150 List.583 List.152; else - dec List.439; - ret List.440; + dec List.148; + ret List.149; in - jump List.576 #Derived_gen.18 #Derived_gen.19 #Derived_gen.20 #Derived_gen.21 #Derived_gen.22; + jump List.579 #Derived_gen.26 #Derived_gen.27 #Derived_gen.28 #Derived_gen.29 #Derived_gen.30; -procedure List.80 (#Derived_gen.31, #Derived_gen.32, #Derived_gen.33, #Derived_gen.34, #Derived_gen.35): - joinpoint List.556 List.439 List.440 List.441 List.442 List.443: - let List.558 : Int1 = CallByName Num.22 List.442 List.443; - if List.558 then - let List.565 : {Str, Str} = CallByName List.66 List.439 List.442; - inc List.565; - let List.559 : {List U8, U64} = CallByName List.145 List.440 List.565 List.441; - let List.562 : U64 = 1i64; - let List.561 : U64 = CallByName Num.19 List.442 List.562; - jump List.556 List.439 List.559 List.441 List.561 List.443; +procedure List.86 (#Derived_gen.31, #Derived_gen.32, #Derived_gen.33, #Derived_gen.34, #Derived_gen.35): + joinpoint List.567 List.148 List.149 List.150 List.151 List.152: + let List.569 : Int1 = CallByName Num.22 List.151 List.152; + if List.569 then + let List.573 : {Str, Str} = CallByName List.66 List.148 List.151; + inc List.573; + let List.153 : {List U8, U64} = CallByName TotallyNotJson.237 List.149 List.573 List.150; + let List.572 : U64 = 1i64; + let List.571 : U64 = CallByName Num.51 List.151 List.572; + jump List.567 List.148 List.153 List.150 List.571 List.152; else - dec List.439; - ret List.440; + dec List.148; + ret List.149; in - jump List.556 #Derived_gen.31 #Derived_gen.32 #Derived_gen.33 #Derived_gen.34 #Derived_gen.35; + jump List.567 #Derived_gen.31 #Derived_gen.32 #Derived_gen.33 #Derived_gen.34 #Derived_gen.35; -procedure List.93 (List.436, List.437, List.438): - let List.554 : U64 = 0i64; - let List.555 : U64 = CallByName List.6 List.436; - let List.553 : {List U8, U64} = CallByName List.80 List.436 List.437 List.438 List.554 List.555; - ret List.553; - -procedure List.93 (List.436, List.437, List.438): - let List.574 : U64 = 0i64; - let List.575 : U64 = CallByName List.6 List.436; - let List.573 : List U8 = CallByName List.80 List.436 List.437 List.438 List.574 List.575; - ret List.573; - -procedure List.93 (List.436, List.437, List.438): - let List.645 : U64 = 0i64; - let List.646 : U64 = CallByName List.6 List.436; - let List.644 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.436 List.437 List.438 List.645 List.646; - ret List.644; +procedure List.96 (List.450, List.451, List.452): + let List.643 : U64 = 0i64; + let List.644 : U64 = CallByName List.6 List.450; + let List.642 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.450 List.451 List.452 List.643 List.644; + ret List.642; procedure Num.127 (#Attr.2): let Num.297 : U8 = lowlevel NumIntCast #Attr.2; ret Num.297; procedure Num.19 (#Attr.2, #Attr.3): - let Num.306 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.306; + let Num.301 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.301; procedure Num.20 (#Attr.2, #Attr.3): - let Num.310 : U64 = lowlevel NumSub #Attr.2 #Attr.3; - ret Num.310; + let Num.298 : U64 = lowlevel NumSub #Attr.2 #Attr.3; + ret Num.298; procedure Num.21 (#Attr.2, #Attr.3): let Num.303 : U64 = lowlevel NumMul #Attr.2 #Attr.3; @@ -291,6 +275,14 @@ procedure Num.24 (#Attr.2, #Attr.3): let Num.311 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; ret Num.311; +procedure Num.51 (#Attr.2, #Attr.3): + let Num.306 : U64 = lowlevel NumAddWrap #Attr.2 #Attr.3; + ret Num.306; + +procedure Num.75 (#Attr.2, #Attr.3): + let Num.310 : U64 = lowlevel NumSubWrap #Attr.2 #Attr.3; + ret Num.310; + procedure Num.94 (#Attr.2, #Attr.3): let Num.302 : U64 = lowlevel NumDivCeilUnchecked #Attr.2 #Attr.3; ret Num.302; @@ -1028,10 +1020,6 @@ procedure TotallyNotJson.189 (TotallyNotJson.1579, TotallyNotJson.192): ret TotallyNotJson.1604; -procedure TotallyNotJson.2 (): - let TotallyNotJson.1172 : [C , C [], C , C , C , C ] = TagId(2) ; - ret TotallyNotJson.1172; - procedure TotallyNotJson.215 (TotallyNotJson.216, TotallyNotJson.217): let TotallyNotJson.1550 : List U8 = CallByName TotallyNotJson.27 TotallyNotJson.217; let TotallyNotJson.1549 : List U8 = CallByName List.8 TotallyNotJson.216 TotallyNotJson.1550; @@ -1184,6 +1172,10 @@ procedure TotallyNotJson.29 (TotallyNotJson.233): let TotallyNotJson.1173 : List {Str, Str} = CallByName Encode.23 TotallyNotJson.233; ret TotallyNotJson.1173; +procedure TotallyNotJson.8 (): + let TotallyNotJson.1172 : [C , C [], C , C , C , C ] = TagId(2) ; + ret TotallyNotJson.1172; + procedure TotallyNotJson.82 (TotallyNotJson.802, TotallyNotJson.803): let TotallyNotJson.1522 : U8 = GetTagId TotallyNotJson.803; switch TotallyNotJson.1522: @@ -1215,14 +1207,14 @@ procedure TotallyNotJson.82 (TotallyNotJson.802, TotallyNotJson.803): procedure TotallyNotJson.832 (TotallyNotJson.1493): let TotallyNotJson.1494 : List Str = StructAtIndex 1 TotallyNotJson.1493; - let #Derived_gen.38 : List Str = StructAtIndex 0 TotallyNotJson.1493; - dec #Derived_gen.38; + let #Derived_gen.37 : List Str = StructAtIndex 0 TotallyNotJson.1493; + dec #Derived_gen.37; ret TotallyNotJson.1494; procedure TotallyNotJson.840 (TotallyNotJson.1214): let TotallyNotJson.1215 : List Str = StructAtIndex 1 TotallyNotJson.1214; - let #Derived_gen.37 : List Str = StructAtIndex 0 TotallyNotJson.1214; - dec #Derived_gen.37; + let #Derived_gen.38 : List Str = StructAtIndex 0 TotallyNotJson.1214; + dec #Derived_gen.38; ret TotallyNotJson.1215; procedure TotallyNotJson.87 (TotallyNotJson.809): @@ -1255,8 +1247,8 @@ procedure TotallyNotJson.94 (TotallyNotJson.824): let TotallyNotJson.1400 : List Str = CallByName List.13 TotallyNotJson.828 TotallyNotJson.827; let TotallyNotJson.1401 : Str = ""; let TotallyNotJson.1399 : Str = CallByName Str.4 TotallyNotJson.1400 TotallyNotJson.1401; - dec TotallyNotJson.1400; dec TotallyNotJson.1401; + dec TotallyNotJson.1400; ret TotallyNotJson.1399; else dec TotallyNotJson.825; @@ -1277,7 +1269,7 @@ procedure TotallyNotJson.95 (TotallyNotJson.829): dec TotallyNotJson.1489; ret TotallyNotJson.1488; -procedure TotallyNotJson.96 (#Derived_gen.26): +procedure TotallyNotJson.96 (#Derived_gen.25): joinpoint TotallyNotJson.1496 TotallyNotJson.1168: let TotallyNotJson.834 : List Str = StructAtIndex 0 TotallyNotJson.1168; let TotallyNotJson.833 : List Str = StructAtIndex 1 TotallyNotJson.1168; @@ -1313,7 +1305,7 @@ procedure TotallyNotJson.96 (#Derived_gen.26): let TotallyNotJson.1497 : {List Str, List Str} = Struct {TotallyNotJson.834, TotallyNotJson.833}; ret TotallyNotJson.1497; in - jump TotallyNotJson.1496 #Derived_gen.26; + jump TotallyNotJson.1496 #Derived_gen.25; procedure TotallyNotJson.97 (TotallyNotJson.837): let TotallyNotJson.838 : List Str = CallByName Str.55 TotallyNotJson.837; @@ -1330,7 +1322,7 @@ procedure TotallyNotJson.97 (TotallyNotJson.837): dec TotallyNotJson.1210; ret TotallyNotJson.1209; -procedure TotallyNotJson.98 (#Derived_gen.30): +procedure TotallyNotJson.98 (#Derived_gen.10): joinpoint TotallyNotJson.1217 TotallyNotJson.1169: let TotallyNotJson.842 : List Str = StructAtIndex 0 TotallyNotJson.1169; let TotallyNotJson.841 : List Str = StructAtIndex 1 TotallyNotJson.1169; @@ -1366,11 +1358,11 @@ procedure TotallyNotJson.98 (#Derived_gen.30): let TotallyNotJson.1218 : {List Str, List Str} = Struct {TotallyNotJson.842, TotallyNotJson.841}; ret TotallyNotJson.1218; in - jump TotallyNotJson.1217 #Derived_gen.30; + jump TotallyNotJson.1217 #Derived_gen.10; procedure Test.0 (): let Test.11 : Str = "foo"; - let Test.10 : [C , C [], C , C , C , C ] = CallByName TotallyNotJson.2; + let Test.10 : [C , C [], C , C , C , C ] = CallByName TotallyNotJson.8; let Test.8 : List U8 = CallByName Encode.26 Test.11 Test.10; let Test.1 : [C {U64, U8}, C Str] = CallByName Str.9 Test.8; let Test.5 : U8 = 1i64; diff --git a/crates/compiler/test_mono/generated/encode_derived_record_two_field_strings.txt b/crates/compiler/test_mono/generated/encode_derived_record_two_field_strings.txt index 810705ef6f..cc3d1eef46 100644 --- a/crates/compiler/test_mono/generated/encode_derived_record_two_field_strings.txt +++ b/crates/compiler/test_mono/generated/encode_derived_record_two_field_strings.txt @@ -58,233 +58,217 @@ procedure Encode.26 (Encode.105, Encode.106): ret Encode.108; procedure List.13 (#Attr.2, #Attr.3): - let List.621 : List Str = lowlevel ListPrepend #Attr.2 #Attr.3; - ret List.621; + let List.619 : List Str = lowlevel ListPrepend #Attr.2 #Attr.3; + ret List.619; -procedure List.145 (List.146, List.147, List.144): - let List.569 : {List U8, U64} = CallByName TotallyNotJson.237 List.146 List.147 List.144; - ret List.569; +procedure List.18 (List.145, List.146, List.147): + let List.565 : U64 = 0i64; + let List.566 : U64 = CallByName List.6 List.145; + let List.564 : {List U8, U64} = CallByName List.86 List.145 List.146 List.147 List.565 List.566; + ret List.564; -procedure List.145 (List.146, List.147, List.144): - let List.589 : List U8 = CallByName TotallyNotJson.215 List.146 List.147; - ret List.589; +procedure List.18 (List.145, List.146, List.147): + let List.577 : U64 = 0i64; + let List.578 : U64 = CallByName List.6 List.145; + let List.576 : List U8 = CallByName List.86 List.145 List.146 List.147 List.577 List.578; + ret List.576; -procedure List.18 (List.142, List.143, List.144): - let List.550 : {List U8, U64} = CallByName List.93 List.142 List.143 List.144; - ret List.550; - -procedure List.18 (List.142, List.143, List.144): - let List.570 : List U8 = CallByName List.93 List.142 List.143 List.144; - ret List.570; - -procedure List.26 (List.159, List.160, List.161): - let List.638 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.93 List.159 List.160 List.161; - let List.641 : U8 = 1i64; - let List.642 : U8 = GetTagId List.638; - let List.643 : Int1 = lowlevel Eq List.641 List.642; - if List.643 then - let List.162 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.638; - ret List.162; +procedure List.26 (List.172, List.173, List.174): + let List.636 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.96 List.172 List.173 List.174; + let List.639 : U8 = 1i64; + let List.640 : U8 = GetTagId List.636; + let List.641 : Int1 = lowlevel Eq List.639 List.640; + if List.641 then + let List.175 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.636; + ret List.175; else - let List.163 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.638; - ret List.163; + let List.176 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.636; + ret List.176; procedure List.31 (#Attr.2, #Attr.3): - let List.603 : List Str = lowlevel ListDropAt #Attr.2 #Attr.3; - ret List.603; + let List.601 : List Str = lowlevel ListDropAt #Attr.2 #Attr.3; + ret List.601; -procedure List.38 (List.298): - let List.611 : U64 = 0i64; - let List.610 : List Str = CallByName List.31 List.298 List.611; - ret List.610; +procedure List.38 (List.311): + let List.609 : U64 = 0i64; + let List.608 : List Str = CallByName List.31 List.311 List.609; + ret List.608; -procedure List.4 (List.113, List.114): - let List.546 : U64 = 1i64; - let List.545 : List Str = CallByName List.70 List.113 List.546; - let List.544 : List Str = CallByName List.71 List.545 List.114; - ret List.544; +procedure List.4 (List.116, List.117): + let List.560 : U64 = 1i64; + let List.559 : List Str = CallByName List.70 List.116 List.560; + let List.558 : List Str = CallByName List.71 List.559 List.117; + ret List.558; -procedure List.4 (List.113, List.114): - let List.549 : U64 = 1i64; - let List.548 : List U8 = CallByName List.70 List.113 List.549; - let List.547 : List U8 = CallByName List.71 List.548 List.114; - ret List.547; +procedure List.4 (List.116, List.117): + let List.563 : U64 = 1i64; + let List.562 : List U8 = CallByName List.70 List.116 List.563; + let List.561 : List U8 = CallByName List.71 List.562 List.117; + ret List.561; -procedure List.49 (List.376, List.377): - let List.630 : U64 = StructAtIndex 0 List.377; - let List.631 : U64 = 0i64; - let List.628 : Int1 = CallByName Bool.11 List.630 List.631; - if List.628 then - dec List.376; - let List.629 : List U8 = Array []; - ret List.629; +procedure List.49 (List.390, List.391): + let List.628 : U64 = StructAtIndex 0 List.391; + let List.629 : U64 = 0i64; + let List.626 : Int1 = CallByName Bool.11 List.628 List.629; + if List.626 then + dec List.390; + let List.627 : List U8 = Array []; + ret List.627; else - let List.625 : U64 = StructAtIndex 1 List.377; - let List.626 : U64 = StructAtIndex 0 List.377; - let List.624 : List U8 = CallByName List.72 List.376 List.625 List.626; - ret List.624; - -procedure List.52 (List.391, List.392): - let List.393 : U64 = CallByName List.6 List.391; - joinpoint List.636 List.394: - let List.634 : U64 = 0i64; - let List.633 : {U64, U64} = Struct {List.394, List.634}; - inc List.391; - let List.395 : List U8 = CallByName List.49 List.391 List.633; - let List.632 : U64 = CallByName Num.20 List.393 List.394; - let List.623 : {U64, U64} = Struct {List.632, List.394}; - let List.396 : List U8 = CallByName List.49 List.391 List.623; - let List.622 : {List U8, List U8} = Struct {List.395, List.396}; + let List.623 : U64 = StructAtIndex 1 List.391; + let List.624 : U64 = StructAtIndex 0 List.391; + let List.622 : List U8 = CallByName List.72 List.390 List.623 List.624; ret List.622; + +procedure List.52 (List.405, List.406): + let List.407 : U64 = CallByName List.6 List.405; + joinpoint List.634 List.408: + let List.632 : U64 = 0i64; + let List.631 : {U64, U64} = Struct {List.408, List.632}; + inc List.405; + let List.409 : List U8 = CallByName List.49 List.405 List.631; + let List.630 : U64 = CallByName Num.75 List.407 List.408; + let List.621 : {U64, U64} = Struct {List.630, List.408}; + let List.410 : List U8 = CallByName List.49 List.405 List.621; + let List.620 : {List U8, List U8} = Struct {List.409, List.410}; + ret List.620; in - let List.637 : Int1 = CallByName Num.24 List.393 List.392; - if List.637 then - jump List.636 List.392; + let List.635 : Int1 = CallByName Num.24 List.407 List.406; + if List.635 then + jump List.634 List.406; else - jump List.636 List.393; + jump List.634 List.407; procedure List.6 (#Attr.2): - let List.617 : U64 = lowlevel ListLen #Attr.2; - ret List.617; + let List.615 : U64 = lowlevel ListLen #Attr.2; + ret List.615; + +procedure List.6 (#Attr.2): + let List.616 : U64 = lowlevel ListLen #Attr.2; + ret List.616; procedure List.6 (#Attr.2): let List.618 : U64 = lowlevel ListLen #Attr.2; ret List.618; -procedure List.6 (#Attr.2): - let List.620 : U64 = lowlevel ListLen #Attr.2; - ret List.620; - procedure List.66 (#Attr.2, #Attr.3): - let List.566 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.566; + let List.574 : {Str, Str} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.574; procedure List.66 (#Attr.2, #Attr.3): let List.586 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; ret List.586; procedure List.68 (#Attr.2): - let List.613 : List Str = lowlevel ListWithCapacity #Attr.2; - ret List.613; + let List.611 : List Str = lowlevel ListWithCapacity #Attr.2; + ret List.611; procedure List.68 (#Attr.2): - let List.615 : List U8 = lowlevel ListWithCapacity #Attr.2; - ret List.615; + let List.613 : List U8 = lowlevel ListWithCapacity #Attr.2; + ret List.613; procedure List.70 (#Attr.2, #Attr.3): - let List.526 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.526; + let List.540 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.540; procedure List.70 (#Attr.2, #Attr.3): - let List.543 : List Str = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.543; + let List.557 : List Str = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.557; procedure List.71 (#Attr.2, #Attr.3): - let List.524 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.524; + let List.538 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.538; procedure List.71 (#Attr.2, #Attr.3): - let List.541 : List Str = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.541; + let List.555 : List Str = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.555; procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.627 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.627; + let List.625 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.625; procedure List.8 (#Attr.2, #Attr.3): - let List.592 : List Str = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.592; + let List.590 : List Str = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.590; procedure List.8 (#Attr.2, #Attr.3): - let List.600 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.600; + let List.598 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.598; -procedure List.80 (#Derived_gen.14, #Derived_gen.15, #Derived_gen.16, #Derived_gen.17, #Derived_gen.18): - joinpoint List.647 List.439 List.440 List.441 List.442 List.443: - let List.649 : Int1 = CallByName Num.22 List.442 List.443; - if List.649 then - let List.658 : U8 = CallByName List.66 List.439 List.442; - let List.650 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.440 List.658; - let List.655 : U8 = 1i64; - let List.656 : U8 = GetTagId List.650; - let List.657 : Int1 = lowlevel Eq List.655 List.656; - if List.657 then - let List.444 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.650; - let List.653 : U64 = 1i64; - let List.652 : U64 = CallByName Num.19 List.442 List.653; - jump List.647 List.439 List.444 List.441 List.652 List.443; +procedure List.80 (#Derived_gen.15, #Derived_gen.16, #Derived_gen.17, #Derived_gen.18, #Derived_gen.19): + joinpoint List.645 List.453 List.454 List.455 List.456 List.457: + let List.647 : Int1 = CallByName Num.22 List.456 List.457; + if List.647 then + let List.656 : U8 = CallByName List.66 List.453 List.456; + let List.648 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.454 List.656; + let List.653 : U8 = 1i64; + let List.654 : U8 = GetTagId List.648; + let List.655 : Int1 = lowlevel Eq List.653 List.654; + if List.655 then + let List.458 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.648; + let List.651 : U64 = 1i64; + let List.650 : U64 = CallByName Num.51 List.456 List.651; + jump List.645 List.453 List.458 List.455 List.650 List.457; else - dec List.439; - let List.445 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.650; - let List.654 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.445; - ret List.654; + dec List.453; + let List.459 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.648; + let List.652 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.459; + ret List.652; else - dec List.439; - let List.648 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.440; - ret List.648; + dec List.453; + let List.646 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.454; + ret List.646; in - jump List.647 #Derived_gen.14 #Derived_gen.15 #Derived_gen.16 #Derived_gen.17 #Derived_gen.18; + jump List.645 #Derived_gen.15 #Derived_gen.16 #Derived_gen.17 #Derived_gen.18 #Derived_gen.19; -procedure List.80 (#Derived_gen.22, #Derived_gen.23, #Derived_gen.24, #Derived_gen.25, #Derived_gen.26): - joinpoint List.576 List.439 List.440 List.441 List.442 List.443: - let List.578 : Int1 = CallByName Num.22 List.442 List.443; - if List.578 then - let List.585 : U8 = CallByName List.66 List.439 List.442; - let List.579 : List U8 = CallByName List.145 List.440 List.585 List.441; - let List.582 : U64 = 1i64; - let List.581 : U64 = CallByName Num.19 List.442 List.582; - jump List.576 List.439 List.579 List.441 List.581 List.443; +procedure List.86 (#Derived_gen.30, #Derived_gen.31, #Derived_gen.32, #Derived_gen.33, #Derived_gen.34): + joinpoint List.579 List.148 List.149 List.150 List.151 List.152: + let List.581 : Int1 = CallByName Num.22 List.151 List.152; + if List.581 then + let List.585 : U8 = CallByName List.66 List.148 List.151; + let List.153 : List U8 = CallByName TotallyNotJson.215 List.149 List.585; + let List.584 : U64 = 1i64; + let List.583 : U64 = CallByName Num.51 List.151 List.584; + jump List.579 List.148 List.153 List.150 List.583 List.152; else - dec List.439; - ret List.440; + dec List.148; + ret List.149; in - jump List.576 #Derived_gen.22 #Derived_gen.23 #Derived_gen.24 #Derived_gen.25 #Derived_gen.26; + jump List.579 #Derived_gen.30 #Derived_gen.31 #Derived_gen.32 #Derived_gen.33 #Derived_gen.34; -procedure List.80 (#Derived_gen.35, #Derived_gen.36, #Derived_gen.37, #Derived_gen.38, #Derived_gen.39): - joinpoint List.556 List.439 List.440 List.441 List.442 List.443: - let List.558 : Int1 = CallByName Num.22 List.442 List.443; - if List.558 then - let List.565 : {Str, Str} = CallByName List.66 List.439 List.442; - inc List.565; - let List.559 : {List U8, U64} = CallByName List.145 List.440 List.565 List.441; - let List.562 : U64 = 1i64; - let List.561 : U64 = CallByName Num.19 List.442 List.562; - jump List.556 List.439 List.559 List.441 List.561 List.443; +procedure List.86 (#Derived_gen.35, #Derived_gen.36, #Derived_gen.37, #Derived_gen.38, #Derived_gen.39): + joinpoint List.567 List.148 List.149 List.150 List.151 List.152: + let List.569 : Int1 = CallByName Num.22 List.151 List.152; + if List.569 then + let List.573 : {Str, Str} = CallByName List.66 List.148 List.151; + inc List.573; + let List.153 : {List U8, U64} = CallByName TotallyNotJson.237 List.149 List.573 List.150; + let List.572 : U64 = 1i64; + let List.571 : U64 = CallByName Num.51 List.151 List.572; + jump List.567 List.148 List.153 List.150 List.571 List.152; else - dec List.439; - ret List.440; + dec List.148; + ret List.149; in - jump List.556 #Derived_gen.35 #Derived_gen.36 #Derived_gen.37 #Derived_gen.38 #Derived_gen.39; + jump List.567 #Derived_gen.35 #Derived_gen.36 #Derived_gen.37 #Derived_gen.38 #Derived_gen.39; -procedure List.93 (List.436, List.437, List.438): - let List.554 : U64 = 0i64; - let List.555 : U64 = CallByName List.6 List.436; - let List.553 : {List U8, U64} = CallByName List.80 List.436 List.437 List.438 List.554 List.555; - ret List.553; - -procedure List.93 (List.436, List.437, List.438): - let List.574 : U64 = 0i64; - let List.575 : U64 = CallByName List.6 List.436; - let List.573 : List U8 = CallByName List.80 List.436 List.437 List.438 List.574 List.575; - ret List.573; - -procedure List.93 (List.436, List.437, List.438): - let List.645 : U64 = 0i64; - let List.646 : U64 = CallByName List.6 List.436; - let List.644 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.436 List.437 List.438 List.645 List.646; - ret List.644; +procedure List.96 (List.450, List.451, List.452): + let List.643 : U64 = 0i64; + let List.644 : U64 = CallByName List.6 List.450; + let List.642 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.450 List.451 List.452 List.643 List.644; + ret List.642; procedure Num.127 (#Attr.2): let Num.297 : U8 = lowlevel NumIntCast #Attr.2; ret Num.297; procedure Num.19 (#Attr.2, #Attr.3): - let Num.306 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.306; + let Num.301 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.301; procedure Num.20 (#Attr.2, #Attr.3): - let Num.310 : U64 = lowlevel NumSub #Attr.2 #Attr.3; - ret Num.310; + let Num.298 : U64 = lowlevel NumSub #Attr.2 #Attr.3; + ret Num.298; procedure Num.21 (#Attr.2, #Attr.3): let Num.303 : U64 = lowlevel NumMul #Attr.2 #Attr.3; @@ -298,6 +282,14 @@ procedure Num.24 (#Attr.2, #Attr.3): let Num.311 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; ret Num.311; +procedure Num.51 (#Attr.2, #Attr.3): + let Num.306 : U64 = lowlevel NumAddWrap #Attr.2 #Attr.3; + ret Num.306; + +procedure Num.75 (#Attr.2, #Attr.3): + let Num.310 : U64 = lowlevel NumSubWrap #Attr.2 #Attr.3; + ret Num.310; + procedure Num.94 (#Attr.2, #Attr.3): let Num.302 : U64 = lowlevel NumDivCeilUnchecked #Attr.2 #Attr.3; ret Num.302; @@ -1035,10 +1027,6 @@ procedure TotallyNotJson.189 (TotallyNotJson.1579, TotallyNotJson.192): ret TotallyNotJson.1604; -procedure TotallyNotJson.2 (): - let TotallyNotJson.1172 : [C , C [], C , C , C , C ] = TagId(2) ; - ret TotallyNotJson.1172; - procedure TotallyNotJson.215 (TotallyNotJson.216, TotallyNotJson.217): let TotallyNotJson.1550 : List U8 = CallByName TotallyNotJson.27 TotallyNotJson.217; let TotallyNotJson.1549 : List U8 = CallByName List.8 TotallyNotJson.216 TotallyNotJson.1550; @@ -1191,6 +1179,10 @@ procedure TotallyNotJson.29 (TotallyNotJson.233): let TotallyNotJson.1173 : List {Str, Str} = CallByName Encode.23 TotallyNotJson.233; ret TotallyNotJson.1173; +procedure TotallyNotJson.8 (): + let TotallyNotJson.1172 : [C , C [], C , C , C , C ] = TagId(2) ; + ret TotallyNotJson.1172; + procedure TotallyNotJson.82 (TotallyNotJson.802, TotallyNotJson.803): let TotallyNotJson.1522 : U8 = GetTagId TotallyNotJson.803; switch TotallyNotJson.1522: @@ -1222,14 +1214,14 @@ procedure TotallyNotJson.82 (TotallyNotJson.802, TotallyNotJson.803): procedure TotallyNotJson.832 (TotallyNotJson.1493): let TotallyNotJson.1494 : List Str = StructAtIndex 1 TotallyNotJson.1493; - let #Derived_gen.42 : List Str = StructAtIndex 0 TotallyNotJson.1493; - dec #Derived_gen.42; + let #Derived_gen.41 : List Str = StructAtIndex 0 TotallyNotJson.1493; + dec #Derived_gen.41; ret TotallyNotJson.1494; procedure TotallyNotJson.840 (TotallyNotJson.1214): let TotallyNotJson.1215 : List Str = StructAtIndex 1 TotallyNotJson.1214; - let #Derived_gen.41 : List Str = StructAtIndex 0 TotallyNotJson.1214; - dec #Derived_gen.41; + let #Derived_gen.42 : List Str = StructAtIndex 0 TotallyNotJson.1214; + dec #Derived_gen.42; ret TotallyNotJson.1215; procedure TotallyNotJson.87 (TotallyNotJson.809): @@ -1262,8 +1254,8 @@ procedure TotallyNotJson.94 (TotallyNotJson.824): let TotallyNotJson.1400 : List Str = CallByName List.13 TotallyNotJson.828 TotallyNotJson.827; let TotallyNotJson.1401 : Str = ""; let TotallyNotJson.1399 : Str = CallByName Str.4 TotallyNotJson.1400 TotallyNotJson.1401; - dec TotallyNotJson.1400; dec TotallyNotJson.1401; + dec TotallyNotJson.1400; ret TotallyNotJson.1399; else dec TotallyNotJson.825; @@ -1284,7 +1276,7 @@ procedure TotallyNotJson.95 (TotallyNotJson.829): dec TotallyNotJson.1489; ret TotallyNotJson.1488; -procedure TotallyNotJson.96 (#Derived_gen.30): +procedure TotallyNotJson.96 (#Derived_gen.29): joinpoint TotallyNotJson.1496 TotallyNotJson.1168: let TotallyNotJson.834 : List Str = StructAtIndex 0 TotallyNotJson.1168; let TotallyNotJson.833 : List Str = StructAtIndex 1 TotallyNotJson.1168; @@ -1320,7 +1312,7 @@ procedure TotallyNotJson.96 (#Derived_gen.30): let TotallyNotJson.1497 : {List Str, List Str} = Struct {TotallyNotJson.834, TotallyNotJson.833}; ret TotallyNotJson.1497; in - jump TotallyNotJson.1496 #Derived_gen.30; + jump TotallyNotJson.1496 #Derived_gen.29; procedure TotallyNotJson.97 (TotallyNotJson.837): let TotallyNotJson.838 : List Str = CallByName Str.55 TotallyNotJson.837; @@ -1337,7 +1329,7 @@ procedure TotallyNotJson.97 (TotallyNotJson.837): dec TotallyNotJson.1210; ret TotallyNotJson.1209; -procedure TotallyNotJson.98 (#Derived_gen.34): +procedure TotallyNotJson.98 (#Derived_gen.14): joinpoint TotallyNotJson.1217 TotallyNotJson.1169: let TotallyNotJson.842 : List Str = StructAtIndex 0 TotallyNotJson.1169; let TotallyNotJson.841 : List Str = StructAtIndex 1 TotallyNotJson.1169; @@ -1373,13 +1365,13 @@ procedure TotallyNotJson.98 (#Derived_gen.34): let TotallyNotJson.1218 : {List Str, List Str} = Struct {TotallyNotJson.842, TotallyNotJson.841}; ret TotallyNotJson.1218; in - jump TotallyNotJson.1217 #Derived_gen.34; + jump TotallyNotJson.1217 #Derived_gen.14; procedure Test.0 (): let Test.11 : Str = "foo"; let Test.12 : Str = "bar"; let Test.9 : {Str, Str} = Struct {Test.11, Test.12}; - let Test.10 : [C , C [], C , C , C , C ] = CallByName TotallyNotJson.2; + let Test.10 : [C , C [], C , C , C , C ] = CallByName TotallyNotJson.8; let Test.8 : List U8 = CallByName Encode.26 Test.9 Test.10; let Test.1 : [C {U64, U8}, C Str] = CallByName Str.9 Test.8; let Test.5 : U8 = 1i64; diff --git a/crates/compiler/test_mono/generated/encode_derived_string.txt b/crates/compiler/test_mono/generated/encode_derived_string.txt index 3d42e396c8..3a6839c811 100644 --- a/crates/compiler/test_mono/generated/encode_derived_string.txt +++ b/crates/compiler/test_mono/generated/encode_derived_string.txt @@ -15,139 +15,127 @@ procedure Encode.26 (Encode.105, Encode.106): let Encode.108 : List U8 = CallByName Encode.24 Encode.109 Encode.110 Encode.106; ret Encode.108; -procedure List.145 (List.146, List.147, List.144): - let List.552 : List U8 = CallByName TotallyNotJson.215 List.146 List.147; - ret List.552; +procedure List.18 (List.145, List.146, List.147): + let List.549 : U64 = 0i64; + let List.550 : U64 = CallByName List.6 List.145; + let List.548 : List U8 = CallByName List.86 List.145 List.146 List.147 List.549 List.550; + ret List.548; -procedure List.18 (List.142, List.143, List.144): - let List.534 : List U8 = CallByName List.93 List.142 List.143 List.144; - ret List.534; - -procedure List.26 (List.159, List.160, List.161): - let List.569 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.93 List.159 List.160 List.161; - let List.572 : U8 = 1i64; - let List.573 : U8 = GetTagId List.569; - let List.574 : Int1 = lowlevel Eq List.572 List.573; - if List.574 then - let List.162 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.569; - ret List.162; +procedure List.26 (List.172, List.173, List.174): + let List.575 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.96 List.172 List.173 List.174; + let List.578 : U8 = 1i64; + let List.579 : U8 = GetTagId List.575; + let List.580 : Int1 = lowlevel Eq List.578 List.579; + if List.580 then + let List.175 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.575; + ret List.175; else - let List.163 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.569; - ret List.163; + let List.176 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.575; + ret List.176; -procedure List.49 (List.376, List.377): - let List.561 : U64 = StructAtIndex 0 List.377; - let List.562 : U64 = 0i64; - let List.559 : Int1 = CallByName Bool.11 List.561 List.562; - if List.559 then - dec List.376; - let List.560 : List U8 = Array []; - ret List.560; +procedure List.49 (List.390, List.391): + let List.567 : U64 = StructAtIndex 0 List.391; + let List.568 : U64 = 0i64; + let List.565 : Int1 = CallByName Bool.11 List.567 List.568; + if List.565 then + dec List.390; + let List.566 : List U8 = Array []; + ret List.566; else - let List.556 : U64 = StructAtIndex 1 List.377; - let List.557 : U64 = StructAtIndex 0 List.377; - let List.555 : List U8 = CallByName List.72 List.376 List.556 List.557; - ret List.555; + let List.562 : U64 = StructAtIndex 1 List.391; + let List.563 : U64 = StructAtIndex 0 List.391; + let List.561 : List U8 = CallByName List.72 List.390 List.562 List.563; + ret List.561; -procedure List.52 (List.391, List.392): - let List.393 : U64 = CallByName List.6 List.391; - joinpoint List.567 List.394: - let List.565 : U64 = 0i64; - let List.564 : {U64, U64} = Struct {List.394, List.565}; - inc List.391; - let List.395 : List U8 = CallByName List.49 List.391 List.564; - let List.563 : U64 = CallByName Num.20 List.393 List.394; - let List.554 : {U64, U64} = Struct {List.563, List.394}; - let List.396 : List U8 = CallByName List.49 List.391 List.554; - let List.553 : {List U8, List U8} = Struct {List.395, List.396}; - ret List.553; +procedure List.52 (List.405, List.406): + let List.407 : U64 = CallByName List.6 List.405; + joinpoint List.573 List.408: + let List.571 : U64 = 0i64; + let List.570 : {U64, U64} = Struct {List.408, List.571}; + inc List.405; + let List.409 : List U8 = CallByName List.49 List.405 List.570; + let List.569 : U64 = CallByName Num.75 List.407 List.408; + let List.560 : {U64, U64} = Struct {List.569, List.408}; + let List.410 : List U8 = CallByName List.49 List.405 List.560; + let List.559 : {List U8, List U8} = Struct {List.409, List.410}; + ret List.559; in - let List.568 : Int1 = CallByName Num.24 List.393 List.392; - if List.568 then - jump List.567 List.392; + let List.574 : Int1 = CallByName Num.24 List.407 List.406; + if List.574 then + jump List.573 List.406; else - jump List.567 List.393; + jump List.573 List.407; procedure List.6 (#Attr.2): - let List.533 : U64 = lowlevel ListLen #Attr.2; - ret List.533; + let List.547 : U64 = lowlevel ListLen #Attr.2; + ret List.547; procedure List.66 (#Attr.2, #Attr.3): - let List.550 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.550; - -procedure List.68 (#Attr.2): - let List.531 : List U8 = lowlevel ListWithCapacity #Attr.2; - ret List.531; - -procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.558 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + let List.558 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; ret List.558; -procedure List.8 (#Attr.2, #Attr.3): - let List.529 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.529; +procedure List.68 (#Attr.2): + let List.545 : List U8 = lowlevel ListWithCapacity #Attr.2; + ret List.545; -procedure List.80 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4): - joinpoint List.540 List.439 List.440 List.441 List.442 List.443: - let List.542 : Int1 = CallByName Num.22 List.442 List.443; - if List.542 then - let List.549 : U8 = CallByName List.66 List.439 List.442; - let List.543 : List U8 = CallByName List.145 List.440 List.549 List.441; - let List.546 : U64 = 1i64; - let List.545 : U64 = CallByName Num.19 List.442 List.546; - jump List.540 List.439 List.543 List.441 List.545 List.443; - else - dec List.439; - ret List.440; - in - jump List.540 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; +procedure List.72 (#Attr.2, #Attr.3, #Attr.4): + let List.564 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.564; + +procedure List.8 (#Attr.2, #Attr.3): + let List.543 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.543; procedure List.80 (#Derived_gen.8, #Derived_gen.9, #Derived_gen.10, #Derived_gen.11, #Derived_gen.12): - joinpoint List.578 List.439 List.440 List.441 List.442 List.443: - let List.580 : Int1 = CallByName Num.22 List.442 List.443; - if List.580 then - let List.589 : U8 = CallByName List.66 List.439 List.442; - let List.581 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.440 List.589; - let List.586 : U8 = 1i64; - let List.587 : U8 = GetTagId List.581; - let List.588 : Int1 = lowlevel Eq List.586 List.587; - if List.588 then - let List.444 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.581; - let List.584 : U64 = 1i64; - let List.583 : U64 = CallByName Num.19 List.442 List.584; - jump List.578 List.439 List.444 List.441 List.583 List.443; + joinpoint List.584 List.453 List.454 List.455 List.456 List.457: + let List.586 : Int1 = CallByName Num.22 List.456 List.457; + if List.586 then + let List.595 : U8 = CallByName List.66 List.453 List.456; + let List.587 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.454 List.595; + let List.592 : U8 = 1i64; + let List.593 : U8 = GetTagId List.587; + let List.594 : Int1 = lowlevel Eq List.592 List.593; + if List.594 then + let List.458 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.587; + let List.590 : U64 = 1i64; + let List.589 : U64 = CallByName Num.51 List.456 List.590; + jump List.584 List.453 List.458 List.455 List.589 List.457; else - dec List.439; - let List.445 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.581; - let List.585 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.445; - ret List.585; + dec List.453; + let List.459 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.587; + let List.591 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.459; + ret List.591; else - dec List.439; - let List.579 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.440; - ret List.579; + dec List.453; + let List.585 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.454; + ret List.585; in - jump List.578 #Derived_gen.8 #Derived_gen.9 #Derived_gen.10 #Derived_gen.11 #Derived_gen.12; + jump List.584 #Derived_gen.8 #Derived_gen.9 #Derived_gen.10 #Derived_gen.11 #Derived_gen.12; -procedure List.93 (List.436, List.437, List.438): - let List.538 : U64 = 0i64; - let List.539 : U64 = CallByName List.6 List.436; - let List.537 : List U8 = CallByName List.80 List.436 List.437 List.438 List.538 List.539; - ret List.537; +procedure List.86 (#Derived_gen.3, #Derived_gen.4, #Derived_gen.5, #Derived_gen.6, #Derived_gen.7): + joinpoint List.551 List.148 List.149 List.150 List.151 List.152: + let List.553 : Int1 = CallByName Num.22 List.151 List.152; + if List.553 then + let List.557 : U8 = CallByName List.66 List.148 List.151; + let List.153 : List U8 = CallByName TotallyNotJson.215 List.149 List.557; + let List.556 : U64 = 1i64; + let List.555 : U64 = CallByName Num.51 List.151 List.556; + jump List.551 List.148 List.153 List.150 List.555 List.152; + else + dec List.148; + ret List.149; + in + jump List.551 #Derived_gen.3 #Derived_gen.4 #Derived_gen.5 #Derived_gen.6 #Derived_gen.7; -procedure List.93 (List.436, List.437, List.438): - let List.576 : U64 = 0i64; - let List.577 : U64 = CallByName List.6 List.436; - let List.575 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.436 List.437 List.438 List.576 List.577; - ret List.575; +procedure List.96 (List.450, List.451, List.452): + let List.582 : U64 = 0i64; + let List.583 : U64 = CallByName List.6 List.450; + let List.581 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.450 List.451 List.452 List.582 List.583; + ret List.581; procedure Num.19 (#Attr.2, #Attr.3): - let Num.297 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.297; - -procedure Num.20 (#Attr.2, #Attr.3): - let Num.300 : U64 = lowlevel NumSub #Attr.2 #Attr.3; - ret Num.300; + let Num.293 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.293; procedure Num.21 (#Attr.2, #Attr.3): let Num.295 : U64 = lowlevel NumMul #Attr.2 #Attr.3; @@ -161,6 +149,14 @@ procedure Num.24 (#Attr.2, #Attr.3): let Num.301 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; ret Num.301; +procedure Num.51 (#Attr.2, #Attr.3): + let Num.297 : U64 = lowlevel NumAddWrap #Attr.2 #Attr.3; + ret Num.297; + +procedure Num.75 (#Attr.2, #Attr.3): + let Num.300 : U64 = lowlevel NumSubWrap #Attr.2 #Attr.3; + ret Num.300; + procedure Num.94 (#Attr.2, #Attr.3): let Num.294 : U64 = lowlevel NumDivCeilUnchecked #Attr.2 #Attr.3; ret Num.294; @@ -256,10 +252,6 @@ procedure TotallyNotJson.189 (TotallyNotJson.1226, TotallyNotJson.192): ret TotallyNotJson.1251; -procedure TotallyNotJson.2 (): - let TotallyNotJson.1172 : [C , C [], C , C , C , C ] = TagId(2) ; - ret TotallyNotJson.1172; - procedure TotallyNotJson.215 (TotallyNotJson.216, TotallyNotJson.217): let TotallyNotJson.1197 : List U8 = CallByName TotallyNotJson.27 TotallyNotJson.217; let TotallyNotJson.1196 : List U8 = CallByName List.8 TotallyNotJson.216 TotallyNotJson.1197; @@ -361,9 +353,13 @@ procedure TotallyNotJson.27 (TotallyNotJson.218): ret TotallyNotJson.1211; +procedure TotallyNotJson.8 (): + let TotallyNotJson.1172 : [C , C [], C , C , C , C ] = TagId(2) ; + ret TotallyNotJson.1172; + procedure Test.0 (): let Test.9 : Str = "abc"; - let Test.10 : [C , C [], C , C , C , C ] = CallByName TotallyNotJson.2; + let Test.10 : [C , C [], C , C , C , C ] = CallByName TotallyNotJson.8; let Test.8 : List U8 = CallByName Encode.26 Test.9 Test.10; let Test.1 : [C {U64, U8}, C Str] = CallByName Str.9 Test.8; let Test.5 : U8 = 1i64; diff --git a/crates/compiler/test_mono/generated/encode_derived_tag_one_field_string.txt b/crates/compiler/test_mono/generated/encode_derived_tag_one_field_string.txt index d89fbb2e38..2e1fde28f3 100644 --- a/crates/compiler/test_mono/generated/encode_derived_tag_one_field_string.txt +++ b/crates/compiler/test_mono/generated/encode_derived_tag_one_field_string.txt @@ -44,195 +44,179 @@ procedure Encode.26 (Encode.105, Encode.106): let Encode.108 : List U8 = CallByName Encode.24 Encode.109 Encode.110 Encode.106; ret Encode.108; -procedure List.145 (List.146, List.147, List.144): - let List.567 : {List U8, U64} = CallByName TotallyNotJson.267 List.146 List.147 List.144; - ret List.567; +procedure List.18 (List.145, List.146, List.147): + let List.563 : U64 = 0i64; + let List.564 : U64 = CallByName List.6 List.145; + let List.562 : {List U8, U64} = CallByName List.86 List.145 List.146 List.147 List.563 List.564; + ret List.562; -procedure List.145 (List.146, List.147, List.144): - let List.587 : List U8 = CallByName TotallyNotJson.215 List.146 List.147; - ret List.587; +procedure List.18 (List.145, List.146, List.147): + let List.575 : U64 = 0i64; + let List.576 : U64 = CallByName List.6 List.145; + let List.574 : List U8 = CallByName List.86 List.145 List.146 List.147 List.575 List.576; + ret List.574; -procedure List.18 (List.142, List.143, List.144): - let List.548 : {List U8, U64} = CallByName List.93 List.142 List.143 List.144; - ret List.548; - -procedure List.18 (List.142, List.143, List.144): - let List.568 : List U8 = CallByName List.93 List.142 List.143 List.144; - ret List.568; - -procedure List.26 (List.159, List.160, List.161): - let List.618 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.93 List.159 List.160 List.161; - let List.621 : U8 = 1i64; - let List.622 : U8 = GetTagId List.618; - let List.623 : Int1 = lowlevel Eq List.621 List.622; - if List.623 then - let List.162 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.618; - ret List.162; +procedure List.26 (List.172, List.173, List.174): + let List.616 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.96 List.172 List.173 List.174; + let List.619 : U8 = 1i64; + let List.620 : U8 = GetTagId List.616; + let List.621 : Int1 = lowlevel Eq List.619 List.620; + if List.621 then + let List.175 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.616; + ret List.175; else - let List.163 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.618; - ret List.163; + let List.176 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.616; + ret List.176; -procedure List.4 (List.113, List.114): - let List.547 : U64 = 1i64; - let List.546 : List U8 = CallByName List.70 List.113 List.547; - let List.545 : List U8 = CallByName List.71 List.546 List.114; - ret List.545; +procedure List.4 (List.116, List.117): + let List.561 : U64 = 1i64; + let List.560 : List U8 = CallByName List.70 List.116 List.561; + let List.559 : List U8 = CallByName List.71 List.560 List.117; + ret List.559; -procedure List.49 (List.376, List.377): - let List.610 : U64 = StructAtIndex 0 List.377; - let List.611 : U64 = 0i64; - let List.608 : Int1 = CallByName Bool.11 List.610 List.611; - if List.608 then - dec List.376; - let List.609 : List U8 = Array []; - ret List.609; +procedure List.49 (List.390, List.391): + let List.608 : U64 = StructAtIndex 0 List.391; + let List.609 : U64 = 0i64; + let List.606 : Int1 = CallByName Bool.11 List.608 List.609; + if List.606 then + dec List.390; + let List.607 : List U8 = Array []; + ret List.607; else - let List.605 : U64 = StructAtIndex 1 List.377; - let List.606 : U64 = StructAtIndex 0 List.377; - let List.604 : List U8 = CallByName List.72 List.376 List.605 List.606; - ret List.604; - -procedure List.52 (List.391, List.392): - let List.393 : U64 = CallByName List.6 List.391; - joinpoint List.616 List.394: - let List.614 : U64 = 0i64; - let List.613 : {U64, U64} = Struct {List.394, List.614}; - inc List.391; - let List.395 : List U8 = CallByName List.49 List.391 List.613; - let List.612 : U64 = CallByName Num.20 List.393 List.394; - let List.603 : {U64, U64} = Struct {List.612, List.394}; - let List.396 : List U8 = CallByName List.49 List.391 List.603; - let List.602 : {List U8, List U8} = Struct {List.395, List.396}; + let List.603 : U64 = StructAtIndex 1 List.391; + let List.604 : U64 = StructAtIndex 0 List.391; + let List.602 : List U8 = CallByName List.72 List.390 List.603 List.604; ret List.602; + +procedure List.52 (List.405, List.406): + let List.407 : U64 = CallByName List.6 List.405; + joinpoint List.614 List.408: + let List.612 : U64 = 0i64; + let List.611 : {U64, U64} = Struct {List.408, List.612}; + inc List.405; + let List.409 : List U8 = CallByName List.49 List.405 List.611; + let List.610 : U64 = CallByName Num.75 List.407 List.408; + let List.601 : {U64, U64} = Struct {List.610, List.408}; + let List.410 : List U8 = CallByName List.49 List.405 List.601; + let List.600 : {List U8, List U8} = Struct {List.409, List.410}; + ret List.600; in - let List.617 : Int1 = CallByName Num.24 List.393 List.392; - if List.617 then - jump List.616 List.392; + let List.615 : Int1 = CallByName Num.24 List.407 List.406; + if List.615 then + jump List.614 List.406; else - jump List.616 List.393; + jump List.614 List.407; + +procedure List.6 (#Attr.2): + let List.586 : U64 = lowlevel ListLen #Attr.2; + ret List.586; procedure List.6 (#Attr.2): let List.588 : U64 = lowlevel ListLen #Attr.2; ret List.588; -procedure List.6 (#Attr.2): - let List.590 : U64 = lowlevel ListLen #Attr.2; - ret List.590; - procedure List.66 (#Attr.2, #Attr.3): - let List.564 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.564; + let List.572 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.572; procedure List.66 (#Attr.2, #Attr.3): let List.584 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; ret List.584; procedure List.68 (#Attr.2): - let List.601 : List U8 = lowlevel ListWithCapacity #Attr.2; - ret List.601; - -procedure List.70 (#Attr.2, #Attr.3): - let List.526 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.526; - -procedure List.71 (#Attr.2, #Attr.3): - let List.524 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.524; - -procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.607 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.607; - -procedure List.8 (#Attr.2, #Attr.3): - let List.599 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + let List.599 : List U8 = lowlevel ListWithCapacity #Attr.2; ret List.599; +procedure List.70 (#Attr.2, #Attr.3): + let List.540 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.540; + +procedure List.71 (#Attr.2, #Attr.3): + let List.538 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.538; + +procedure List.72 (#Attr.2, #Attr.3, #Attr.4): + let List.605 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.605; + +procedure List.8 (#Attr.2, #Attr.3): + let List.597 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.597; + procedure List.80 (#Derived_gen.16, #Derived_gen.17, #Derived_gen.18, #Derived_gen.19, #Derived_gen.20): - joinpoint List.627 List.439 List.440 List.441 List.442 List.443: - let List.629 : Int1 = CallByName Num.22 List.442 List.443; - if List.629 then - let List.638 : U8 = CallByName List.66 List.439 List.442; - let List.630 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.440 List.638; - let List.635 : U8 = 1i64; - let List.636 : U8 = GetTagId List.630; - let List.637 : Int1 = lowlevel Eq List.635 List.636; - if List.637 then - let List.444 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.630; - let List.633 : U64 = 1i64; - let List.632 : U64 = CallByName Num.19 List.442 List.633; - jump List.627 List.439 List.444 List.441 List.632 List.443; + joinpoint List.625 List.453 List.454 List.455 List.456 List.457: + let List.627 : Int1 = CallByName Num.22 List.456 List.457; + if List.627 then + let List.636 : U8 = CallByName List.66 List.453 List.456; + let List.628 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.454 List.636; + let List.633 : U8 = 1i64; + let List.634 : U8 = GetTagId List.628; + let List.635 : Int1 = lowlevel Eq List.633 List.634; + if List.635 then + let List.458 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.628; + let List.631 : U64 = 1i64; + let List.630 : U64 = CallByName Num.51 List.456 List.631; + jump List.625 List.453 List.458 List.455 List.630 List.457; else - dec List.439; - let List.445 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.630; - let List.634 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.445; - ret List.634; + dec List.453; + let List.459 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.628; + let List.632 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.459; + ret List.632; else - dec List.439; - let List.628 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.440; - ret List.628; + dec List.453; + let List.626 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.454; + ret List.626; in - jump List.627 #Derived_gen.16 #Derived_gen.17 #Derived_gen.18 #Derived_gen.19 #Derived_gen.20; + jump List.625 #Derived_gen.16 #Derived_gen.17 #Derived_gen.18 #Derived_gen.19 #Derived_gen.20; -procedure List.80 (#Derived_gen.24, #Derived_gen.25, #Derived_gen.26, #Derived_gen.27, #Derived_gen.28): - joinpoint List.574 List.439 List.440 List.441 List.442 List.443: - let List.576 : Int1 = CallByName Num.22 List.442 List.443; - if List.576 then - let List.583 : U8 = CallByName List.66 List.439 List.442; - let List.577 : List U8 = CallByName List.145 List.440 List.583 List.441; - let List.580 : U64 = 1i64; - let List.579 : U64 = CallByName Num.19 List.442 List.580; - jump List.574 List.439 List.577 List.441 List.579 List.443; +procedure List.86 (#Derived_gen.21, #Derived_gen.22, #Derived_gen.23, #Derived_gen.24, #Derived_gen.25): + joinpoint List.577 List.148 List.149 List.150 List.151 List.152: + let List.579 : Int1 = CallByName Num.22 List.151 List.152; + if List.579 then + let List.583 : U8 = CallByName List.66 List.148 List.151; + let List.153 : List U8 = CallByName TotallyNotJson.215 List.149 List.583; + let List.582 : U64 = 1i64; + let List.581 : U64 = CallByName Num.51 List.151 List.582; + jump List.577 List.148 List.153 List.150 List.581 List.152; else - dec List.439; - ret List.440; + dec List.148; + ret List.149; in - jump List.574 #Derived_gen.24 #Derived_gen.25 #Derived_gen.26 #Derived_gen.27 #Derived_gen.28; + jump List.577 #Derived_gen.21 #Derived_gen.22 #Derived_gen.23 #Derived_gen.24 #Derived_gen.25; -procedure List.80 (#Derived_gen.29, #Derived_gen.30, #Derived_gen.31, #Derived_gen.32, #Derived_gen.33): - joinpoint List.554 List.439 List.440 List.441 List.442 List.443: - let List.556 : Int1 = CallByName Num.22 List.442 List.443; - if List.556 then - let List.563 : Str = CallByName List.66 List.439 List.442; - inc List.563; - let List.557 : {List U8, U64} = CallByName List.145 List.440 List.563 List.441; - let List.560 : U64 = 1i64; - let List.559 : U64 = CallByName Num.19 List.442 List.560; - jump List.554 List.439 List.557 List.441 List.559 List.443; +procedure List.86 (#Derived_gen.26, #Derived_gen.27, #Derived_gen.28, #Derived_gen.29, #Derived_gen.30): + joinpoint List.565 List.148 List.149 List.150 List.151 List.152: + let List.567 : Int1 = CallByName Num.22 List.151 List.152; + if List.567 then + let List.571 : Str = CallByName List.66 List.148 List.151; + inc List.571; + let List.153 : {List U8, U64} = CallByName TotallyNotJson.267 List.149 List.571 List.150; + let List.570 : U64 = 1i64; + let List.569 : U64 = CallByName Num.51 List.151 List.570; + jump List.565 List.148 List.153 List.150 List.569 List.152; else - dec List.439; - ret List.440; + dec List.148; + ret List.149; in - jump List.554 #Derived_gen.29 #Derived_gen.30 #Derived_gen.31 #Derived_gen.32 #Derived_gen.33; + jump List.565 #Derived_gen.26 #Derived_gen.27 #Derived_gen.28 #Derived_gen.29 #Derived_gen.30; -procedure List.93 (List.436, List.437, List.438): - let List.552 : U64 = 0i64; - let List.553 : U64 = CallByName List.6 List.436; - let List.551 : {List U8, U64} = CallByName List.80 List.436 List.437 List.438 List.552 List.553; - ret List.551; - -procedure List.93 (List.436, List.437, List.438): - let List.572 : U64 = 0i64; - let List.573 : U64 = CallByName List.6 List.436; - let List.571 : List U8 = CallByName List.80 List.436 List.437 List.438 List.572 List.573; - ret List.571; - -procedure List.93 (List.436, List.437, List.438): - let List.625 : U64 = 0i64; - let List.626 : U64 = CallByName List.6 List.436; - let List.624 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.436 List.437 List.438 List.625 List.626; - ret List.624; +procedure List.96 (List.450, List.451, List.452): + let List.623 : U64 = 0i64; + let List.624 : U64 = CallByName List.6 List.450; + let List.622 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.450 List.451 List.452 List.623 List.624; + ret List.622; procedure Num.127 (#Attr.2): let Num.299 : U8 = lowlevel NumIntCast #Attr.2; ret Num.299; procedure Num.19 (#Attr.2, #Attr.3): - let Num.308 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.308; + let Num.303 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.303; procedure Num.20 (#Attr.2, #Attr.3): - let Num.312 : U64 = lowlevel NumSub #Attr.2 #Attr.3; - ret Num.312; + let Num.300 : U64 = lowlevel NumSub #Attr.2 #Attr.3; + ret Num.300; procedure Num.21 (#Attr.2, #Attr.3): let Num.305 : U64 = lowlevel NumMul #Attr.2 #Attr.3; @@ -246,6 +230,14 @@ procedure Num.24 (#Attr.2, #Attr.3): let Num.313 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; ret Num.313; +procedure Num.51 (#Attr.2, #Attr.3): + let Num.308 : U64 = lowlevel NumAddWrap #Attr.2 #Attr.3; + ret Num.308; + +procedure Num.75 (#Attr.2, #Attr.3): + let Num.312 : U64 = lowlevel NumSubWrap #Attr.2 #Attr.3; + ret Num.312; + procedure Num.94 (#Attr.2, #Attr.3): let Num.304 : U64 = lowlevel NumDivCeilUnchecked #Attr.2 #Attr.3; ret Num.304; @@ -341,10 +333,6 @@ procedure TotallyNotJson.189 (TotallyNotJson.1267, TotallyNotJson.192): ret TotallyNotJson.1292; -procedure TotallyNotJson.2 (): - let TotallyNotJson.1172 : [C , C [], C , C , C , C ] = TagId(2) ; - ret TotallyNotJson.1172; - procedure TotallyNotJson.215 (TotallyNotJson.216, TotallyNotJson.217): let TotallyNotJson.1238 : List U8 = CallByName TotallyNotJson.27 TotallyNotJson.217; let TotallyNotJson.1237 : List U8 = CallByName List.8 TotallyNotJson.216 TotallyNotJson.1238; @@ -503,9 +491,13 @@ procedure TotallyNotJson.32 (TotallyNotJson.262, TotallyNotJson.263): let TotallyNotJson.1173 : {Str, List Str} = CallByName Encode.23 TotallyNotJson.1174; ret TotallyNotJson.1173; +procedure TotallyNotJson.8 (): + let TotallyNotJson.1172 : [C , C [], C , C , C , C ] = TagId(2) ; + ret TotallyNotJson.1172; + procedure Test.0 (): let Test.12 : Str = "foo"; - let Test.11 : [C , C [], C , C , C , C ] = CallByName TotallyNotJson.2; + let Test.11 : [C , C [], C , C , C , C ] = CallByName TotallyNotJson.8; let Test.10 : List U8 = CallByName Encode.26 Test.12 Test.11; let Test.2 : [C {U64, U8}, C Str] = CallByName Str.9 Test.10; let Test.7 : U8 = 1i64; diff --git a/crates/compiler/test_mono/generated/encode_derived_tag_two_payloads_string.txt b/crates/compiler/test_mono/generated/encode_derived_tag_two_payloads_string.txt index 93524dfb6b..6a0152990b 100644 --- a/crates/compiler/test_mono/generated/encode_derived_tag_two_payloads_string.txt +++ b/crates/compiler/test_mono/generated/encode_derived_tag_two_payloads_string.txt @@ -47,195 +47,179 @@ procedure Encode.26 (Encode.105, Encode.106): let Encode.108 : List U8 = CallByName Encode.24 Encode.109 Encode.110 Encode.106; ret Encode.108; -procedure List.145 (List.146, List.147, List.144): - let List.567 : {List U8, U64} = CallByName TotallyNotJson.267 List.146 List.147 List.144; - ret List.567; +procedure List.18 (List.145, List.146, List.147): + let List.563 : U64 = 0i64; + let List.564 : U64 = CallByName List.6 List.145; + let List.562 : {List U8, U64} = CallByName List.86 List.145 List.146 List.147 List.563 List.564; + ret List.562; -procedure List.145 (List.146, List.147, List.144): - let List.587 : List U8 = CallByName TotallyNotJson.215 List.146 List.147; - ret List.587; +procedure List.18 (List.145, List.146, List.147): + let List.575 : U64 = 0i64; + let List.576 : U64 = CallByName List.6 List.145; + let List.574 : List U8 = CallByName List.86 List.145 List.146 List.147 List.575 List.576; + ret List.574; -procedure List.18 (List.142, List.143, List.144): - let List.548 : {List U8, U64} = CallByName List.93 List.142 List.143 List.144; - ret List.548; - -procedure List.18 (List.142, List.143, List.144): - let List.568 : List U8 = CallByName List.93 List.142 List.143 List.144; - ret List.568; - -procedure List.26 (List.159, List.160, List.161): - let List.618 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.93 List.159 List.160 List.161; - let List.621 : U8 = 1i64; - let List.622 : U8 = GetTagId List.618; - let List.623 : Int1 = lowlevel Eq List.621 List.622; - if List.623 then - let List.162 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.618; - ret List.162; +procedure List.26 (List.172, List.173, List.174): + let List.616 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.96 List.172 List.173 List.174; + let List.619 : U8 = 1i64; + let List.620 : U8 = GetTagId List.616; + let List.621 : Int1 = lowlevel Eq List.619 List.620; + if List.621 then + let List.175 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.616; + ret List.175; else - let List.163 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.618; - ret List.163; + let List.176 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.616; + ret List.176; -procedure List.4 (List.113, List.114): - let List.547 : U64 = 1i64; - let List.546 : List U8 = CallByName List.70 List.113 List.547; - let List.545 : List U8 = CallByName List.71 List.546 List.114; - ret List.545; +procedure List.4 (List.116, List.117): + let List.561 : U64 = 1i64; + let List.560 : List U8 = CallByName List.70 List.116 List.561; + let List.559 : List U8 = CallByName List.71 List.560 List.117; + ret List.559; -procedure List.49 (List.376, List.377): - let List.610 : U64 = StructAtIndex 0 List.377; - let List.611 : U64 = 0i64; - let List.608 : Int1 = CallByName Bool.11 List.610 List.611; - if List.608 then - dec List.376; - let List.609 : List U8 = Array []; - ret List.609; +procedure List.49 (List.390, List.391): + let List.608 : U64 = StructAtIndex 0 List.391; + let List.609 : U64 = 0i64; + let List.606 : Int1 = CallByName Bool.11 List.608 List.609; + if List.606 then + dec List.390; + let List.607 : List U8 = Array []; + ret List.607; else - let List.605 : U64 = StructAtIndex 1 List.377; - let List.606 : U64 = StructAtIndex 0 List.377; - let List.604 : List U8 = CallByName List.72 List.376 List.605 List.606; - ret List.604; - -procedure List.52 (List.391, List.392): - let List.393 : U64 = CallByName List.6 List.391; - joinpoint List.616 List.394: - let List.614 : U64 = 0i64; - let List.613 : {U64, U64} = Struct {List.394, List.614}; - inc List.391; - let List.395 : List U8 = CallByName List.49 List.391 List.613; - let List.612 : U64 = CallByName Num.20 List.393 List.394; - let List.603 : {U64, U64} = Struct {List.612, List.394}; - let List.396 : List U8 = CallByName List.49 List.391 List.603; - let List.602 : {List U8, List U8} = Struct {List.395, List.396}; + let List.603 : U64 = StructAtIndex 1 List.391; + let List.604 : U64 = StructAtIndex 0 List.391; + let List.602 : List U8 = CallByName List.72 List.390 List.603 List.604; ret List.602; + +procedure List.52 (List.405, List.406): + let List.407 : U64 = CallByName List.6 List.405; + joinpoint List.614 List.408: + let List.612 : U64 = 0i64; + let List.611 : {U64, U64} = Struct {List.408, List.612}; + inc List.405; + let List.409 : List U8 = CallByName List.49 List.405 List.611; + let List.610 : U64 = CallByName Num.75 List.407 List.408; + let List.601 : {U64, U64} = Struct {List.610, List.408}; + let List.410 : List U8 = CallByName List.49 List.405 List.601; + let List.600 : {List U8, List U8} = Struct {List.409, List.410}; + ret List.600; in - let List.617 : Int1 = CallByName Num.24 List.393 List.392; - if List.617 then - jump List.616 List.392; + let List.615 : Int1 = CallByName Num.24 List.407 List.406; + if List.615 then + jump List.614 List.406; else - jump List.616 List.393; + jump List.614 List.407; + +procedure List.6 (#Attr.2): + let List.586 : U64 = lowlevel ListLen #Attr.2; + ret List.586; procedure List.6 (#Attr.2): let List.588 : U64 = lowlevel ListLen #Attr.2; ret List.588; -procedure List.6 (#Attr.2): - let List.590 : U64 = lowlevel ListLen #Attr.2; - ret List.590; - procedure List.66 (#Attr.2, #Attr.3): - let List.564 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.564; + let List.572 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.572; procedure List.66 (#Attr.2, #Attr.3): let List.584 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; ret List.584; procedure List.68 (#Attr.2): - let List.601 : List U8 = lowlevel ListWithCapacity #Attr.2; - ret List.601; - -procedure List.70 (#Attr.2, #Attr.3): - let List.526 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.526; - -procedure List.71 (#Attr.2, #Attr.3): - let List.524 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.524; - -procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.607 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.607; - -procedure List.8 (#Attr.2, #Attr.3): - let List.599 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + let List.599 : List U8 = lowlevel ListWithCapacity #Attr.2; ret List.599; -procedure List.80 (#Derived_gen.11, #Derived_gen.12, #Derived_gen.13, #Derived_gen.14, #Derived_gen.15): - joinpoint List.627 List.439 List.440 List.441 List.442 List.443: - let List.629 : Int1 = CallByName Num.22 List.442 List.443; - if List.629 then - let List.638 : U8 = CallByName List.66 List.439 List.442; - let List.630 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.440 List.638; - let List.635 : U8 = 1i64; - let List.636 : U8 = GetTagId List.630; - let List.637 : Int1 = lowlevel Eq List.635 List.636; - if List.637 then - let List.444 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.630; - let List.633 : U64 = 1i64; - let List.632 : U64 = CallByName Num.19 List.442 List.633; - jump List.627 List.439 List.444 List.441 List.632 List.443; +procedure List.70 (#Attr.2, #Attr.3): + let List.540 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.540; + +procedure List.71 (#Attr.2, #Attr.3): + let List.538 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.538; + +procedure List.72 (#Attr.2, #Attr.3, #Attr.4): + let List.605 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.605; + +procedure List.8 (#Attr.2, #Attr.3): + let List.597 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.597; + +procedure List.80 (#Derived_gen.14, #Derived_gen.15, #Derived_gen.16, #Derived_gen.17, #Derived_gen.18): + joinpoint List.625 List.453 List.454 List.455 List.456 List.457: + let List.627 : Int1 = CallByName Num.22 List.456 List.457; + if List.627 then + let List.636 : U8 = CallByName List.66 List.453 List.456; + let List.628 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.454 List.636; + let List.633 : U8 = 1i64; + let List.634 : U8 = GetTagId List.628; + let List.635 : Int1 = lowlevel Eq List.633 List.634; + if List.635 then + let List.458 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.628; + let List.631 : U64 = 1i64; + let List.630 : U64 = CallByName Num.51 List.456 List.631; + jump List.625 List.453 List.458 List.455 List.630 List.457; else - dec List.439; - let List.445 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.630; - let List.634 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.445; - ret List.634; + dec List.453; + let List.459 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.628; + let List.632 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.459; + ret List.632; else - dec List.439; - let List.628 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.440; - ret List.628; + dec List.453; + let List.626 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.454; + ret List.626; in - jump List.627 #Derived_gen.11 #Derived_gen.12 #Derived_gen.13 #Derived_gen.14 #Derived_gen.15; + jump List.625 #Derived_gen.14 #Derived_gen.15 #Derived_gen.16 #Derived_gen.17 #Derived_gen.18; -procedure List.80 (#Derived_gen.19, #Derived_gen.20, #Derived_gen.21, #Derived_gen.22, #Derived_gen.23): - joinpoint List.554 List.439 List.440 List.441 List.442 List.443: - let List.556 : Int1 = CallByName Num.22 List.442 List.443; - if List.556 then - let List.563 : Str = CallByName List.66 List.439 List.442; - inc List.563; - let List.557 : {List U8, U64} = CallByName List.145 List.440 List.563 List.441; - let List.560 : U64 = 1i64; - let List.559 : U64 = CallByName Num.19 List.442 List.560; - jump List.554 List.439 List.557 List.441 List.559 List.443; +procedure List.86 (#Derived_gen.19, #Derived_gen.20, #Derived_gen.21, #Derived_gen.22, #Derived_gen.23): + joinpoint List.565 List.148 List.149 List.150 List.151 List.152: + let List.567 : Int1 = CallByName Num.22 List.151 List.152; + if List.567 then + let List.571 : Str = CallByName List.66 List.148 List.151; + inc List.571; + let List.153 : {List U8, U64} = CallByName TotallyNotJson.267 List.149 List.571 List.150; + let List.570 : U64 = 1i64; + let List.569 : U64 = CallByName Num.51 List.151 List.570; + jump List.565 List.148 List.153 List.150 List.569 List.152; else - dec List.439; - ret List.440; + dec List.148; + ret List.149; in - jump List.554 #Derived_gen.19 #Derived_gen.20 #Derived_gen.21 #Derived_gen.22 #Derived_gen.23; + jump List.565 #Derived_gen.19 #Derived_gen.20 #Derived_gen.21 #Derived_gen.22 #Derived_gen.23; -procedure List.80 (#Derived_gen.24, #Derived_gen.25, #Derived_gen.26, #Derived_gen.27, #Derived_gen.28): - joinpoint List.574 List.439 List.440 List.441 List.442 List.443: - let List.576 : Int1 = CallByName Num.22 List.442 List.443; - if List.576 then - let List.583 : U8 = CallByName List.66 List.439 List.442; - let List.577 : List U8 = CallByName List.145 List.440 List.583 List.441; - let List.580 : U64 = 1i64; - let List.579 : U64 = CallByName Num.19 List.442 List.580; - jump List.574 List.439 List.577 List.441 List.579 List.443; +procedure List.86 (#Derived_gen.27, #Derived_gen.28, #Derived_gen.29, #Derived_gen.30, #Derived_gen.31): + joinpoint List.577 List.148 List.149 List.150 List.151 List.152: + let List.579 : Int1 = CallByName Num.22 List.151 List.152; + if List.579 then + let List.583 : U8 = CallByName List.66 List.148 List.151; + let List.153 : List U8 = CallByName TotallyNotJson.215 List.149 List.583; + let List.582 : U64 = 1i64; + let List.581 : U64 = CallByName Num.51 List.151 List.582; + jump List.577 List.148 List.153 List.150 List.581 List.152; else - dec List.439; - ret List.440; + dec List.148; + ret List.149; in - jump List.574 #Derived_gen.24 #Derived_gen.25 #Derived_gen.26 #Derived_gen.27 #Derived_gen.28; + jump List.577 #Derived_gen.27 #Derived_gen.28 #Derived_gen.29 #Derived_gen.30 #Derived_gen.31; -procedure List.93 (List.436, List.437, List.438): - let List.552 : U64 = 0i64; - let List.553 : U64 = CallByName List.6 List.436; - let List.551 : {List U8, U64} = CallByName List.80 List.436 List.437 List.438 List.552 List.553; - ret List.551; - -procedure List.93 (List.436, List.437, List.438): - let List.572 : U64 = 0i64; - let List.573 : U64 = CallByName List.6 List.436; - let List.571 : List U8 = CallByName List.80 List.436 List.437 List.438 List.572 List.573; - ret List.571; - -procedure List.93 (List.436, List.437, List.438): - let List.625 : U64 = 0i64; - let List.626 : U64 = CallByName List.6 List.436; - let List.624 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.436 List.437 List.438 List.625 List.626; - ret List.624; +procedure List.96 (List.450, List.451, List.452): + let List.623 : U64 = 0i64; + let List.624 : U64 = CallByName List.6 List.450; + let List.622 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.450 List.451 List.452 List.623 List.624; + ret List.622; procedure Num.127 (#Attr.2): let Num.299 : U8 = lowlevel NumIntCast #Attr.2; ret Num.299; procedure Num.19 (#Attr.2, #Attr.3): - let Num.308 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.308; + let Num.303 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.303; procedure Num.20 (#Attr.2, #Attr.3): - let Num.312 : U64 = lowlevel NumSub #Attr.2 #Attr.3; - ret Num.312; + let Num.300 : U64 = lowlevel NumSub #Attr.2 #Attr.3; + ret Num.300; procedure Num.21 (#Attr.2, #Attr.3): let Num.305 : U64 = lowlevel NumMul #Attr.2 #Attr.3; @@ -249,6 +233,14 @@ procedure Num.24 (#Attr.2, #Attr.3): let Num.313 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; ret Num.313; +procedure Num.51 (#Attr.2, #Attr.3): + let Num.308 : U64 = lowlevel NumAddWrap #Attr.2 #Attr.3; + ret Num.308; + +procedure Num.75 (#Attr.2, #Attr.3): + let Num.312 : U64 = lowlevel NumSubWrap #Attr.2 #Attr.3; + ret Num.312; + procedure Num.94 (#Attr.2, #Attr.3): let Num.304 : U64 = lowlevel NumDivCeilUnchecked #Attr.2 #Attr.3; ret Num.304; @@ -344,10 +336,6 @@ procedure TotallyNotJson.189 (TotallyNotJson.1267, TotallyNotJson.192): ret TotallyNotJson.1292; -procedure TotallyNotJson.2 (): - let TotallyNotJson.1172 : [C , C [], C , C , C , C ] = TagId(2) ; - ret TotallyNotJson.1172; - procedure TotallyNotJson.215 (TotallyNotJson.216, TotallyNotJson.217): let TotallyNotJson.1238 : List U8 = CallByName TotallyNotJson.27 TotallyNotJson.217; let TotallyNotJson.1237 : List U8 = CallByName List.8 TotallyNotJson.216 TotallyNotJson.1238; @@ -506,11 +494,15 @@ procedure TotallyNotJson.32 (TotallyNotJson.262, TotallyNotJson.263): let TotallyNotJson.1173 : {Str, List Str} = CallByName Encode.23 TotallyNotJson.1174; ret TotallyNotJson.1173; +procedure TotallyNotJson.8 (): + let TotallyNotJson.1172 : [C , C [], C , C , C , C ] = TagId(2) ; + ret TotallyNotJson.1172; + procedure Test.0 (): let Test.13 : Str = "foo"; let Test.12 : Str = "foo"; let Test.1 : {Str, Str} = Struct {Test.12, Test.13}; - let Test.11 : [C , C [], C , C , C , C ] = CallByName TotallyNotJson.2; + let Test.11 : [C , C [], C , C , C , C ] = CallByName TotallyNotJson.8; let Test.10 : List U8 = CallByName Encode.26 Test.1 Test.11; let Test.2 : [C {U64, U8}, C Str] = CallByName Str.9 Test.10; let Test.7 : U8 = 1i64; diff --git a/crates/compiler/test_mono/generated/inline_return_joinpoints_in_union_lambda_set.txt b/crates/compiler/test_mono/generated/inline_return_joinpoints_in_union_lambda_set.txt index 6ab49274c5..750e2fa29d 100644 --- a/crates/compiler/test_mono/generated/inline_return_joinpoints_in_union_lambda_set.txt +++ b/crates/compiler/test_mono/generated/inline_return_joinpoints_in_union_lambda_set.txt @@ -17,7 +17,7 @@ procedure Test.4 (Test.5, #Attr.12): let Test.16 : I64 = CallByName Num.19 Test.5 Test.1; ret Test.16; -procedure Test.0 (#Derived_gen.0): +procedure Test.0 (#Derived_gen.2): joinpoint Test.7 Test.1: let Test.20 : I64 = 1i64; let Test.9 : I64 = CallByName Num.19 Test.1 Test.20; @@ -33,4 +33,4 @@ procedure Test.0 (#Derived_gen.0): ret Test.8; in - jump Test.7 #Derived_gen.0; + jump Test.7 #Derived_gen.2; diff --git a/crates/compiler/test_mono/generated/ir_int_add.txt b/crates/compiler/test_mono/generated/ir_int_add.txt index 2e4de96845..45689fc196 100644 --- a/crates/compiler/test_mono/generated/ir_int_add.txt +++ b/crates/compiler/test_mono/generated/ir_int_add.txt @@ -1,6 +1,6 @@ procedure List.6 (#Attr.2): - let List.521 : U64 = lowlevel ListLen #Attr.2; - ret List.521; + let List.535 : U64 = lowlevel ListLen #Attr.2; + ret List.535; procedure Num.19 (#Attr.2, #Attr.3): let Num.294 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; diff --git a/crates/compiler/test_mono/generated/issue_2583_specialize_errors_behind_unified_branches.txt b/crates/compiler/test_mono/generated/issue_2583_specialize_errors_behind_unified_branches.txt index 96c021a84b..e77fe1a39f 100644 --- a/crates/compiler/test_mono/generated/issue_2583_specialize_errors_behind_unified_branches.txt +++ b/crates/compiler/test_mono/generated/issue_2583_specialize_errors_behind_unified_branches.txt @@ -6,42 +6,42 @@ procedure Bool.2 (): let Bool.23 : Int1 = true; ret Bool.23; -procedure List.2 (List.97, List.98): - let List.535 : U64 = CallByName List.6 List.97; - let List.531 : Int1 = CallByName Num.22 List.98 List.535; - if List.531 then - let List.533 : I64 = CallByName List.66 List.97 List.98; - dec List.97; - let List.532 : [C {}, C I64] = TagId(1) List.533; - ret List.532; +procedure List.2 (List.100, List.101): + let List.549 : U64 = CallByName List.6 List.100; + let List.545 : Int1 = CallByName Num.22 List.101 List.549; + if List.545 then + let List.547 : I64 = CallByName List.66 List.100 List.101; + dec List.100; + let List.546 : [C {}, C I64] = TagId(1) List.547; + ret List.546; else - dec List.97; - let List.530 : {} = Struct {}; - let List.529 : [C {}, C I64] = TagId(0) List.530; - ret List.529; + dec List.100; + let List.544 : {} = Struct {}; + let List.543 : [C {}, C I64] = TagId(0) List.544; + ret List.543; procedure List.6 (#Attr.2): - let List.536 : U64 = lowlevel ListLen #Attr.2; - ret List.536; + let List.550 : U64 = lowlevel ListLen #Attr.2; + ret List.550; procedure List.66 (#Attr.2, #Attr.3): - let List.534 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.534; + let List.548 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.548; -procedure List.9 (List.293): - let List.528 : U64 = 0i64; - let List.521 : [C {}, C I64] = CallByName List.2 List.293 List.528; - let List.525 : U8 = 1i64; - let List.526 : U8 = GetTagId List.521; - let List.527 : Int1 = lowlevel Eq List.525 List.526; - if List.527 then - let List.294 : I64 = UnionAtIndex (Id 1) (Index 0) List.521; - let List.522 : [C Int1, C I64] = TagId(1) List.294; - ret List.522; +procedure List.9 (List.306): + let List.542 : U64 = 0i64; + let List.535 : [C {}, C I64] = CallByName List.2 List.306 List.542; + let List.539 : U8 = 1i64; + let List.540 : U8 = GetTagId List.535; + let List.541 : Int1 = lowlevel Eq List.539 List.540; + if List.541 then + let List.307 : I64 = UnionAtIndex (Id 1) (Index 0) List.535; + let List.536 : [C Int1, C I64] = TagId(1) List.307; + ret List.536; else - let List.524 : Int1 = true; - let List.523 : [C Int1, C I64] = TagId(0) List.524; - ret List.523; + let List.538 : Int1 = true; + let List.537 : [C Int1, C I64] = TagId(0) List.538; + ret List.537; procedure Num.22 (#Attr.2, #Attr.3): let Num.292 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; diff --git a/crates/compiler/test_mono/generated/issue_4749.txt b/crates/compiler/test_mono/generated/issue_4749.txt index 61797ec653..c893a42791 100644 --- a/crates/compiler/test_mono/generated/issue_4749.txt +++ b/crates/compiler/test_mono/generated/issue_4749.txt @@ -64,144 +64,144 @@ procedure Decode.27 (Decode.107, Decode.108): let Decode.123 : [C [C List U8, C ], C Str] = TagId(0) Decode.124; ret Decode.123; -procedure List.1 (List.96): - let List.588 : U64 = CallByName List.6 List.96; - dec List.96; - let List.589 : U64 = 0i64; - let List.587 : Int1 = CallByName Bool.11 List.588 List.589; - ret List.587; +procedure List.1 (List.99): + let List.602 : U64 = CallByName List.6 List.99; + dec List.99; + let List.603 : U64 = 0i64; + let List.601 : Int1 = CallByName Bool.11 List.602 List.603; + ret List.601; -procedure List.2 (List.97, List.98): - let List.571 : U64 = CallByName List.6 List.97; - let List.568 : Int1 = CallByName Num.22 List.98 List.571; - if List.568 then - let List.570 : U8 = CallByName List.66 List.97 List.98; - dec List.97; - let List.569 : [C {}, C U8] = TagId(1) List.570; - ret List.569; - else - dec List.97; - let List.567 : {} = Struct {}; - let List.566 : [C {}, C U8] = TagId(0) List.567; - ret List.566; - -procedure List.26 (List.159, List.160, List.161): - let List.590 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = CallByName List.93 List.159 List.160 List.161; - let List.593 : U8 = 1i64; - let List.594 : U8 = GetTagId List.590; - let List.595 : Int1 = lowlevel Eq List.593 List.594; - if List.595 then - let List.162 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 1) (Index 0) List.590; - ret List.162; - else - let List.163 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 0) (Index 0) List.590; - ret List.163; - -procedure List.29 (List.304, List.305): - let List.545 : U64 = CallByName List.6 List.304; - let List.306 : U64 = CallByName Num.77 List.545 List.305; - let List.544 : List U8 = CallByName List.43 List.304 List.306; - ret List.544; - -procedure List.31 (#Attr.2, #Attr.3): - let List.558 : List U8 = lowlevel ListDropAt #Attr.2 #Attr.3; - ret List.558; - -procedure List.38 (List.298): - let List.557 : U64 = 0i64; - let List.556 : List U8 = CallByName List.31 List.298 List.557; - ret List.556; - -procedure List.4 (List.113, List.114): - let List.555 : U64 = 1i64; - let List.554 : List U8 = CallByName List.70 List.113 List.555; - let List.553 : List U8 = CallByName List.71 List.554 List.114; - ret List.553; - -procedure List.43 (List.302, List.303): - let List.537 : U64 = CallByName List.6 List.302; - let List.536 : U64 = CallByName Num.77 List.537 List.303; - let List.527 : {U64, U64} = Struct {List.303, List.536}; - let List.526 : List U8 = CallByName List.49 List.302 List.527; - ret List.526; - -procedure List.49 (List.376, List.377): - let List.584 : U64 = StructAtIndex 0 List.377; - let List.585 : U64 = 0i64; - let List.582 : Int1 = CallByName Bool.11 List.584 List.585; +procedure List.2 (List.100, List.101): + let List.585 : U64 = CallByName List.6 List.100; + let List.582 : Int1 = CallByName Num.22 List.101 List.585; if List.582 then - dec List.376; - let List.583 : List U8 = Array []; + let List.584 : U8 = CallByName List.66 List.100 List.101; + dec List.100; + let List.583 : [C {}, C U8] = TagId(1) List.584; ret List.583; else - let List.580 : U64 = StructAtIndex 1 List.377; - let List.581 : U64 = StructAtIndex 0 List.377; - let List.579 : List U8 = CallByName List.72 List.376 List.580 List.581; - ret List.579; + dec List.100; + let List.581 : {} = Struct {}; + let List.580 : [C {}, C U8] = TagId(0) List.581; + ret List.580; + +procedure List.26 (List.172, List.173, List.174): + let List.604 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = CallByName List.96 List.172 List.173 List.174; + let List.607 : U8 = 1i64; + let List.608 : U8 = GetTagId List.604; + let List.609 : Int1 = lowlevel Eq List.607 List.608; + if List.609 then + let List.175 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 1) (Index 0) List.604; + ret List.175; + else + let List.176 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 0) (Index 0) List.604; + ret List.176; + +procedure List.29 (List.317, List.318): + let List.559 : U64 = CallByName List.6 List.317; + let List.319 : U64 = CallByName Num.77 List.559 List.318; + let List.558 : List U8 = CallByName List.43 List.317 List.319; + ret List.558; + +procedure List.31 (#Attr.2, #Attr.3): + let List.572 : List U8 = lowlevel ListDropAt #Attr.2 #Attr.3; + ret List.572; + +procedure List.38 (List.311): + let List.571 : U64 = 0i64; + let List.570 : List U8 = CallByName List.31 List.311 List.571; + ret List.570; + +procedure List.4 (List.116, List.117): + let List.569 : U64 = 1i64; + let List.568 : List U8 = CallByName List.70 List.116 List.569; + let List.567 : List U8 = CallByName List.71 List.568 List.117; + ret List.567; + +procedure List.43 (List.315, List.316): + let List.551 : U64 = CallByName List.6 List.315; + let List.550 : U64 = CallByName Num.77 List.551 List.316; + let List.541 : {U64, U64} = Struct {List.316, List.550}; + let List.540 : List U8 = CallByName List.49 List.315 List.541; + ret List.540; + +procedure List.49 (List.390, List.391): + let List.598 : U64 = StructAtIndex 0 List.391; + let List.599 : U64 = 0i64; + let List.596 : Int1 = CallByName Bool.11 List.598 List.599; + if List.596 then + dec List.390; + let List.597 : List U8 = Array []; + ret List.597; + else + let List.594 : U64 = StructAtIndex 1 List.391; + let List.595 : U64 = StructAtIndex 0 List.391; + let List.593 : List U8 = CallByName List.72 List.390 List.594 List.595; + ret List.593; procedure List.6 (#Attr.2): - let List.611 : U64 = lowlevel ListLen #Attr.2; - ret List.611; + let List.625 : U64 = lowlevel ListLen #Attr.2; + ret List.625; procedure List.66 (#Attr.2, #Attr.3): - let List.564 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.564; + let List.578 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.578; procedure List.70 (#Attr.2, #Attr.3): - let List.552 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.552; + let List.566 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.566; procedure List.71 (#Attr.2, #Attr.3): - let List.550 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.550; + let List.564 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.564; procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.531 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.531; + let List.545 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.545; procedure List.8 (#Attr.2, #Attr.3): - let List.547 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.547; + let List.561 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.561; procedure List.80 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4): - joinpoint List.599 List.439 List.440 List.441 List.442 List.443: - let List.601 : Int1 = CallByName Num.22 List.442 List.443; - if List.601 then - let List.610 : U8 = CallByName List.66 List.439 List.442; - let List.602 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = CallByName TotallyNotJson.62 List.440 List.610; - let List.607 : U8 = 1i64; - let List.608 : U8 = GetTagId List.602; - let List.609 : Int1 = lowlevel Eq List.607 List.608; - if List.609 then - let List.444 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 1) (Index 0) List.602; - let List.605 : U64 = 1i64; - let List.604 : U64 = CallByName Num.19 List.442 List.605; - jump List.599 List.439 List.444 List.441 List.604 List.443; + joinpoint List.613 List.453 List.454 List.455 List.456 List.457: + let List.615 : Int1 = CallByName Num.22 List.456 List.457; + if List.615 then + let List.624 : U8 = CallByName List.66 List.453 List.456; + let List.616 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = CallByName TotallyNotJson.62 List.454 List.624; + let List.621 : U8 = 1i64; + let List.622 : U8 = GetTagId List.616; + let List.623 : Int1 = lowlevel Eq List.621 List.622; + if List.623 then + let List.458 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 1) (Index 0) List.616; + let List.619 : U64 = 1i64; + let List.618 : U64 = CallByName Num.51 List.456 List.619; + jump List.613 List.453 List.458 List.455 List.618 List.457; else - dec List.439; - let List.445 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 0) (Index 0) List.602; - let List.606 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = TagId(0) List.445; - ret List.606; + dec List.453; + let List.459 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 0) (Index 0) List.616; + let List.620 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = TagId(0) List.459; + ret List.620; else - dec List.439; - let List.600 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = TagId(1) List.440; - ret List.600; + dec List.453; + let List.614 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = TagId(1) List.454; + ret List.614; in - jump List.599 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; + jump List.613 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; -procedure List.93 (List.436, List.437, List.438): - let List.597 : U64 = 0i64; - let List.598 : U64 = CallByName List.6 List.436; - let List.596 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = CallByName List.80 List.436 List.437 List.438 List.597 List.598; - ret List.596; +procedure List.96 (List.450, List.451, List.452): + let List.611 : U64 = 0i64; + let List.612 : U64 = CallByName List.6 List.450; + let List.610 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = CallByName List.80 List.450 List.451 List.452 List.611 List.612; + ret List.610; procedure Num.19 (#Attr.2, #Attr.3): let Num.295 : U8 = lowlevel NumAdd #Attr.2 #Attr.3; ret Num.295; procedure Num.19 (#Attr.2, #Attr.3): - let Num.329 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.329; + let Num.304 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.304; procedure Num.20 (#Attr.2, #Attr.3): let Num.307 : U8 = lowlevel NumSub #Attr.2 #Attr.3; @@ -219,6 +219,10 @@ procedure Num.25 (#Attr.2, #Attr.3): let Num.319 : Int1 = lowlevel NumGte #Attr.2 #Attr.3; ret Num.319; +procedure Num.51 (#Attr.2, #Attr.3): + let Num.329 : U64 = lowlevel NumAddWrap #Attr.2 #Attr.3; + ret Num.329; + procedure Num.71 (#Attr.2, #Attr.3): let Num.292 : U8 = lowlevel NumBitwiseOr #Attr.2 #Attr.3; ret Num.292; @@ -255,7 +259,7 @@ procedure Str.9 (Str.79): procedure Test.3 (): let Test.0 : List U8 = Array [82i64, 111i64, 99i64]; - let Test.8 : [C , C [], C , C , C , C ] = CallByName TotallyNotJson.2; + let Test.8 : [C , C [], C , C , C , C ] = CallByName TotallyNotJson.8; inc Test.0; let Test.1 : [C [C List U8, C ], C Str] = CallByName Decode.27 Test.0 Test.8; let Test.7 : Str = "Roc"; @@ -263,15 +267,11 @@ procedure Test.3 (): let Test.5 : Int1 = CallByName Bool.11 Test.1 Test.6; dec Test.7; expect Test.5; - dec Test.0; dec Test.1; + dec Test.0; let Test.4 : {} = Struct {}; ret Test.4; -procedure TotallyNotJson.2 (): - let TotallyNotJson.1172 : [C , C [], C , C , C , C ] = TagId(2) ; - ret TotallyNotJson.1172; - procedure TotallyNotJson.525 (TotallyNotJson.526, TotallyNotJson.1175): joinpoint TotallyNotJson.1458: inc TotallyNotJson.526; @@ -281,8 +281,8 @@ procedure TotallyNotJson.525 (TotallyNotJson.526, TotallyNotJson.1175): inc TotallyNotJson.529; let TotallyNotJson.1323 : Int1 = CallByName List.1 TotallyNotJson.529; if TotallyNotJson.1323 then - dec TotallyNotJson.529; dec TotallyNotJson.530; + dec TotallyNotJson.529; let TotallyNotJson.1326 : {} = Struct {}; let TotallyNotJson.1325 : [C {}, C Str] = TagId(0) TotallyNotJson.1326; let TotallyNotJson.1324 : {List U8, [C {}, C Str]} = Struct {TotallyNotJson.526, TotallyNotJson.1325}; @@ -309,8 +309,8 @@ procedure TotallyNotJson.525 (TotallyNotJson.526, TotallyNotJson.1175): let TotallyNotJson.1181 : {List U8, [C {}, C Str]} = Struct {TotallyNotJson.530, TotallyNotJson.1182}; ret TotallyNotJson.1181; else - dec TotallyNotJson.533; dec TotallyNotJson.530; + dec TotallyNotJson.533; let TotallyNotJson.1185 : {} = Struct {}; let TotallyNotJson.1184 : [C {}, C Str] = TagId(0) TotallyNotJson.1185; let TotallyNotJson.1183 : {List U8, [C {}, C Str]} = Struct {TotallyNotJson.526, TotallyNotJson.1184}; @@ -835,3 +835,7 @@ procedure TotallyNotJson.70 (#Derived_gen.5): ret TotallyNotJson.1276; in jump TotallyNotJson.1198 #Derived_gen.5; + +procedure TotallyNotJson.8 (): + let TotallyNotJson.1172 : [C , C [], C , C , C , C ] = TagId(2) ; + ret TotallyNotJson.1172; diff --git a/crates/compiler/test_mono/generated/issue_4770.txt b/crates/compiler/test_mono/generated/issue_4770.txt index 7c010f6334..7bf5bf4ca6 100644 --- a/crates/compiler/test_mono/generated/issue_4770.txt +++ b/crates/compiler/test_mono/generated/issue_4770.txt @@ -6,84 +6,80 @@ procedure Bool.2 (): let Bool.24 : Int1 = true; ret Bool.24; -procedure List.194 (List.523, List.195, List.193): - let List.553 : Int1 = CallByName Test.1 List.195; - if List.553 then - let List.555 : {} = Struct {}; - let List.554 : [C {}, C {}] = TagId(1) List.555; - ret List.554; +procedure List.207 (List.537, List.208, List.206): + let List.567 : Int1 = CallByName Test.1 List.208; + if List.567 then + let List.569 : {} = Struct {}; + let List.568 : [C {}, C {}] = TagId(1) List.569; + ret List.568; else - let List.552 : {} = Struct {}; - let List.551 : [C {}, C {}] = TagId(0) List.552; - ret List.551; + let List.566 : {} = Struct {}; + let List.565 : [C {}, C {}] = TagId(0) List.566; + ret List.565; procedure List.23 (#Attr.2, #Attr.3, #Attr.4): - let List.556 : List {[C I64, C List *self], [C I64, C List *self]} = lowlevel ListMap2 { xs: `#Attr.#arg1`, ys: `#Attr.#arg2` } #Attr.2 #Attr.3 Test.15 #Attr.4; + let List.570 : List {[C I64, C List *self], [C I64, C List *self]} = lowlevel ListMap2 { xs: `#Attr.#arg1`, ys: `#Attr.#arg2` } #Attr.2 #Attr.3 Test.15 #Attr.4; decref #Attr.3; decref #Attr.2; - ret List.556; + ret List.570; -procedure List.56 (List.192, List.193): - let List.532 : {} = Struct {}; - let List.524 : [C {}, C {}] = CallByName List.93 List.192 List.532 List.193; - let List.529 : U8 = 1i64; - let List.530 : U8 = GetTagId List.524; - let List.531 : Int1 = lowlevel Eq List.529 List.530; - if List.531 then - let List.525 : Int1 = CallByName Bool.2; - ret List.525; +procedure List.56 (List.205, List.206): + let List.546 : {} = Struct {}; + let List.538 : [C {}, C {}] = CallByName List.96 List.205 List.546 List.206; + let List.543 : U8 = 1i64; + let List.544 : U8 = GetTagId List.538; + let List.545 : Int1 = lowlevel Eq List.543 List.544; + if List.545 then + let List.539 : Int1 = CallByName Bool.2; + ret List.539; else - let List.526 : Int1 = CallByName Bool.1; - ret List.526; + let List.540 : Int1 = CallByName Bool.1; + ret List.540; procedure List.6 (#Attr.2): - let List.522 : U64 = lowlevel ListLen #Attr.2; - ret List.522; + let List.536 : U64 = lowlevel ListLen #Attr.2; + ret List.536; procedure List.6 (#Attr.2): - let List.550 : U64 = lowlevel ListLen #Attr.2; - ret List.550; + let List.564 : U64 = lowlevel ListLen #Attr.2; + ret List.564; procedure List.66 (#Attr.2, #Attr.3): - let List.549 : {[C I64, C List *self], [C I64, C List *self]} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.549; + let List.563 : {[C I64, C List *self], [C I64, C List *self]} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.563; procedure List.80 (#Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4, #Derived_gen.5): - joinpoint List.537 List.439 List.440 List.441 List.442 List.443: - let List.539 : Int1 = CallByName Num.22 List.442 List.443; - if List.539 then - let List.548 : {[C I64, C List *self], [C I64, C List *self]} = CallByName List.66 List.439 List.442; - inc List.548; - let List.540 : [C {}, C {}] = CallByName List.194 List.440 List.548 List.441; - let List.545 : U8 = 1i64; - let List.546 : U8 = GetTagId List.540; - let List.547 : Int1 = lowlevel Eq List.545 List.546; - if List.547 then - let List.444 : {} = UnionAtIndex (Id 1) (Index 0) List.540; - let List.543 : U64 = 1i64; - let List.542 : U64 = CallByName Num.19 List.442 List.543; - jump List.537 List.439 List.444 List.441 List.542 List.443; + joinpoint List.551 List.453 List.454 List.455 List.456 List.457: + let List.553 : Int1 = CallByName Num.22 List.456 List.457; + if List.553 then + let List.562 : {[C I64, C List *self], [C I64, C List *self]} = CallByName List.66 List.453 List.456; + inc List.562; + let List.554 : [C {}, C {}] = CallByName List.207 List.454 List.562 List.455; + let List.559 : U8 = 1i64; + let List.560 : U8 = GetTagId List.554; + let List.561 : Int1 = lowlevel Eq List.559 List.560; + if List.561 then + let List.458 : {} = UnionAtIndex (Id 1) (Index 0) List.554; + let List.557 : U64 = 1i64; + let List.556 : U64 = CallByName Num.51 List.456 List.557; + jump List.551 List.453 List.458 List.455 List.556 List.457; else - dec List.439; - let List.445 : {} = UnionAtIndex (Id 0) (Index 0) List.540; - let List.544 : [C {}, C {}] = TagId(0) List.445; - ret List.544; + dec List.453; + let List.459 : {} = UnionAtIndex (Id 0) (Index 0) List.554; + let List.558 : [C {}, C {}] = TagId(0) List.459; + ret List.558; else - dec List.439; - let List.538 : [C {}, C {}] = TagId(1) List.440; - ret List.538; + dec List.453; + let List.552 : [C {}, C {}] = TagId(1) List.454; + ret List.552; in - jump List.537 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4 #Derived_gen.5; + jump List.551 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4 #Derived_gen.5; -procedure List.93 (List.436, List.437, List.438): - let List.535 : U64 = 0i64; - let List.536 : U64 = CallByName List.6 List.436; - let List.534 : [C {}, C {}] = CallByName List.80 List.436 List.437 List.438 List.535 List.536; - ret List.534; - -procedure Num.19 (#Attr.2, #Attr.3): - let Num.294 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.294; +procedure List.96 (List.450, List.451, List.452): + let List.549 : U64 = 0i64; + let List.550 : U64 = CallByName List.6 List.450; + let List.548 : [C {}, C {}] = CallByName List.80 List.450 List.451 List.452 List.549 List.550; + ret List.548; procedure Num.22 (#Attr.2, #Attr.3): let Num.292 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; @@ -93,6 +89,10 @@ procedure Num.22 (#Attr.2, #Attr.3): let Num.295 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; ret Num.295; +procedure Num.51 (#Attr.2, #Attr.3): + let Num.294 : U64 = lowlevel NumAddWrap #Attr.2 #Attr.3; + ret Num.294; + procedure Test.1 (#Derived_gen.0): joinpoint Test.26 Test.6: let Test.65 : [C I64, C List *self] = StructAtIndex 1 Test.6; diff --git a/crates/compiler/test_mono/generated/issue_4772_weakened_monomorphic_destructure.txt b/crates/compiler/test_mono/generated/issue_4772_weakened_monomorphic_destructure.txt index 368ce7bef1..64766aaa18 100644 --- a/crates/compiler/test_mono/generated/issue_4772_weakened_monomorphic_destructure.txt +++ b/crates/compiler/test_mono/generated/issue_4772_weakened_monomorphic_destructure.txt @@ -38,144 +38,144 @@ procedure Decode.26 (Decode.105, Decode.106): let Decode.122 : {List U8, [C {}, C Str]} = CallByName Decode.25 Decode.105 Decode.123 Decode.106; ret Decode.122; -procedure List.1 (List.96): - let List.584 : U64 = CallByName List.6 List.96; - dec List.96; - let List.585 : U64 = 0i64; - let List.583 : Int1 = CallByName Bool.11 List.584 List.585; - ret List.583; +procedure List.1 (List.99): + let List.598 : U64 = CallByName List.6 List.99; + dec List.99; + let List.599 : U64 = 0i64; + let List.597 : Int1 = CallByName Bool.11 List.598 List.599; + ret List.597; -procedure List.2 (List.97, List.98): - let List.567 : U64 = CallByName List.6 List.97; - let List.564 : Int1 = CallByName Num.22 List.98 List.567; - if List.564 then - let List.566 : U8 = CallByName List.66 List.97 List.98; - dec List.97; - let List.565 : [C {}, C U8] = TagId(1) List.566; - ret List.565; - else - dec List.97; - let List.563 : {} = Struct {}; - let List.562 : [C {}, C U8] = TagId(0) List.563; - ret List.562; - -procedure List.26 (List.159, List.160, List.161): - let List.586 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = CallByName List.93 List.159 List.160 List.161; - let List.589 : U8 = 1i64; - let List.590 : U8 = GetTagId List.586; - let List.591 : Int1 = lowlevel Eq List.589 List.590; - if List.591 then - let List.162 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 1) (Index 0) List.586; - ret List.162; - else - let List.163 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 0) (Index 0) List.586; - ret List.163; - -procedure List.29 (List.304, List.305): - let List.541 : U64 = CallByName List.6 List.304; - let List.306 : U64 = CallByName Num.77 List.541 List.305; - let List.540 : List U8 = CallByName List.43 List.304 List.306; - ret List.540; - -procedure List.31 (#Attr.2, #Attr.3): - let List.554 : List U8 = lowlevel ListDropAt #Attr.2 #Attr.3; - ret List.554; - -procedure List.38 (List.298): - let List.553 : U64 = 0i64; - let List.552 : List U8 = CallByName List.31 List.298 List.553; - ret List.552; - -procedure List.4 (List.113, List.114): - let List.551 : U64 = 1i64; - let List.550 : List U8 = CallByName List.70 List.113 List.551; - let List.549 : List U8 = CallByName List.71 List.550 List.114; - ret List.549; - -procedure List.43 (List.302, List.303): - let List.533 : U64 = CallByName List.6 List.302; - let List.532 : U64 = CallByName Num.77 List.533 List.303; - let List.523 : {U64, U64} = Struct {List.303, List.532}; - let List.522 : List U8 = CallByName List.49 List.302 List.523; - ret List.522; - -procedure List.49 (List.376, List.377): - let List.580 : U64 = StructAtIndex 0 List.377; - let List.581 : U64 = 0i64; - let List.578 : Int1 = CallByName Bool.11 List.580 List.581; +procedure List.2 (List.100, List.101): + let List.581 : U64 = CallByName List.6 List.100; + let List.578 : Int1 = CallByName Num.22 List.101 List.581; if List.578 then - dec List.376; - let List.579 : List U8 = Array []; + let List.580 : U8 = CallByName List.66 List.100 List.101; + dec List.100; + let List.579 : [C {}, C U8] = TagId(1) List.580; ret List.579; else - let List.576 : U64 = StructAtIndex 1 List.377; - let List.577 : U64 = StructAtIndex 0 List.377; - let List.575 : List U8 = CallByName List.72 List.376 List.576 List.577; - ret List.575; + dec List.100; + let List.577 : {} = Struct {}; + let List.576 : [C {}, C U8] = TagId(0) List.577; + ret List.576; + +procedure List.26 (List.172, List.173, List.174): + let List.600 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = CallByName List.96 List.172 List.173 List.174; + let List.603 : U8 = 1i64; + let List.604 : U8 = GetTagId List.600; + let List.605 : Int1 = lowlevel Eq List.603 List.604; + if List.605 then + let List.175 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 1) (Index 0) List.600; + ret List.175; + else + let List.176 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 0) (Index 0) List.600; + ret List.176; + +procedure List.29 (List.317, List.318): + let List.555 : U64 = CallByName List.6 List.317; + let List.319 : U64 = CallByName Num.77 List.555 List.318; + let List.554 : List U8 = CallByName List.43 List.317 List.319; + ret List.554; + +procedure List.31 (#Attr.2, #Attr.3): + let List.568 : List U8 = lowlevel ListDropAt #Attr.2 #Attr.3; + ret List.568; + +procedure List.38 (List.311): + let List.567 : U64 = 0i64; + let List.566 : List U8 = CallByName List.31 List.311 List.567; + ret List.566; + +procedure List.4 (List.116, List.117): + let List.565 : U64 = 1i64; + let List.564 : List U8 = CallByName List.70 List.116 List.565; + let List.563 : List U8 = CallByName List.71 List.564 List.117; + ret List.563; + +procedure List.43 (List.315, List.316): + let List.547 : U64 = CallByName List.6 List.315; + let List.546 : U64 = CallByName Num.77 List.547 List.316; + let List.537 : {U64, U64} = Struct {List.316, List.546}; + let List.536 : List U8 = CallByName List.49 List.315 List.537; + ret List.536; + +procedure List.49 (List.390, List.391): + let List.594 : U64 = StructAtIndex 0 List.391; + let List.595 : U64 = 0i64; + let List.592 : Int1 = CallByName Bool.11 List.594 List.595; + if List.592 then + dec List.390; + let List.593 : List U8 = Array []; + ret List.593; + else + let List.590 : U64 = StructAtIndex 1 List.391; + let List.591 : U64 = StructAtIndex 0 List.391; + let List.589 : List U8 = CallByName List.72 List.390 List.590 List.591; + ret List.589; procedure List.6 (#Attr.2): - let List.607 : U64 = lowlevel ListLen #Attr.2; - ret List.607; + let List.621 : U64 = lowlevel ListLen #Attr.2; + ret List.621; procedure List.66 (#Attr.2, #Attr.3): - let List.560 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.560; + let List.574 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.574; procedure List.70 (#Attr.2, #Attr.3): - let List.548 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.548; + let List.562 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.562; procedure List.71 (#Attr.2, #Attr.3): - let List.546 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.546; + let List.560 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.560; procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.527 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.527; + let List.541 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.541; procedure List.8 (#Attr.2, #Attr.3): - let List.543 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.543; + let List.557 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.557; procedure List.80 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4): - joinpoint List.595 List.439 List.440 List.441 List.442 List.443: - let List.597 : Int1 = CallByName Num.22 List.442 List.443; - if List.597 then - let List.606 : U8 = CallByName List.66 List.439 List.442; - let List.598 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = CallByName TotallyNotJson.62 List.440 List.606; - let List.603 : U8 = 1i64; - let List.604 : U8 = GetTagId List.598; - let List.605 : Int1 = lowlevel Eq List.603 List.604; - if List.605 then - let List.444 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 1) (Index 0) List.598; - let List.601 : U64 = 1i64; - let List.600 : U64 = CallByName Num.19 List.442 List.601; - jump List.595 List.439 List.444 List.441 List.600 List.443; + joinpoint List.609 List.453 List.454 List.455 List.456 List.457: + let List.611 : Int1 = CallByName Num.22 List.456 List.457; + if List.611 then + let List.620 : U8 = CallByName List.66 List.453 List.456; + let List.612 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = CallByName TotallyNotJson.62 List.454 List.620; + let List.617 : U8 = 1i64; + let List.618 : U8 = GetTagId List.612; + let List.619 : Int1 = lowlevel Eq List.617 List.618; + if List.619 then + let List.458 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 1) (Index 0) List.612; + let List.615 : U64 = 1i64; + let List.614 : U64 = CallByName Num.51 List.456 List.615; + jump List.609 List.453 List.458 List.455 List.614 List.457; else - dec List.439; - let List.445 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 0) (Index 0) List.598; - let List.602 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = TagId(0) List.445; - ret List.602; + dec List.453; + let List.459 : [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64] = UnionAtIndex (Id 0) (Index 0) List.612; + let List.616 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = TagId(0) List.459; + ret List.616; else - dec List.439; - let List.596 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = TagId(1) List.440; - ret List.596; + dec List.453; + let List.610 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = TagId(1) List.454; + ret List.610; in - jump List.595 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; + jump List.609 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; -procedure List.93 (List.436, List.437, List.438): - let List.593 : U64 = 0i64; - let List.594 : U64 = CallByName List.6 List.436; - let List.592 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = CallByName List.80 List.436 List.437 List.438 List.593 List.594; - ret List.592; +procedure List.96 (List.450, List.451, List.452): + let List.607 : U64 = 0i64; + let List.608 : U64 = CallByName List.6 List.450; + let List.606 : [C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64], C [C U64, C U64, C U64, C , C , C U64, C U64, C U64, C U64]] = CallByName List.80 List.450 List.451 List.452 List.607 List.608; + ret List.606; procedure Num.19 (#Attr.2, #Attr.3): let Num.295 : U8 = lowlevel NumAdd #Attr.2 #Attr.3; ret Num.295; procedure Num.19 (#Attr.2, #Attr.3): - let Num.329 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.329; + let Num.304 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.304; procedure Num.20 (#Attr.2, #Attr.3): let Num.307 : U8 = lowlevel NumSub #Attr.2 #Attr.3; @@ -193,6 +193,10 @@ procedure Num.25 (#Attr.2, #Attr.3): let Num.319 : Int1 = lowlevel NumGte #Attr.2 #Attr.3; ret Num.319; +procedure Num.51 (#Attr.2, #Attr.3): + let Num.329 : U64 = lowlevel NumAddWrap #Attr.2 #Attr.3; + ret Num.329; + procedure Num.71 (#Attr.2, #Attr.3): let Num.292 : U8 = lowlevel NumBitwiseOr #Attr.2 #Attr.3; ret Num.292; @@ -248,8 +252,8 @@ procedure Str.9 (Str.79): else let Str.301 : U8 = StructAtIndex 3 Str.80; let Str.302 : U64 = StructAtIndex 0 Str.80; - let #Derived_gen.7 : Str = StructAtIndex 1 Str.80; - dec #Derived_gen.7; + let #Derived_gen.6 : Str = StructAtIndex 1 Str.80; + dec #Derived_gen.6; let Str.300 : {U64, U8} = Struct {Str.302, Str.301}; let Str.299 : [C {U64, U8}, C Str] = TagId(0) Str.300; ret Str.299; @@ -257,7 +261,7 @@ procedure Str.9 (Str.79): procedure Test.0 (): let Test.37 : Str = "-1234"; let Test.35 : List U8 = CallByName Str.12 Test.37; - let Test.36 : [C , C [], C , C , C , C ] = CallByName TotallyNotJson.2; + let Test.36 : [C , C [], C , C , C , C ] = CallByName TotallyNotJson.8; let Test.34 : {List U8, [C {}, C Str]} = CallByName Decode.26 Test.35 Test.36; let Test.2 : List U8 = StructAtIndex 0 Test.34; let Test.1 : [C {}, C Str] = StructAtIndex 1 Test.34; @@ -281,8 +285,8 @@ procedure Test.0 (): let Test.22 : [C Str, C {List U8, I64}] = TagId(0) Test.24; ret Test.22; else - dec Test.1; dec Test.2; + dec Test.1; let Test.30 : Str = "not a number"; let Test.28 : [C Str, C {List U8, I64}] = TagId(0) Test.30; ret Test.28; @@ -300,10 +304,6 @@ procedure Test.12 (): let Test.13 : {} = Struct {}; ret Test.13; -procedure TotallyNotJson.2 (): - let TotallyNotJson.1172 : [C , C [], C , C , C , C ] = TagId(2) ; - ret TotallyNotJson.1172; - procedure TotallyNotJson.525 (TotallyNotJson.526, TotallyNotJson.1175): joinpoint TotallyNotJson.1458: inc TotallyNotJson.526; @@ -313,8 +313,8 @@ procedure TotallyNotJson.525 (TotallyNotJson.526, TotallyNotJson.1175): inc TotallyNotJson.529; let TotallyNotJson.1323 : Int1 = CallByName List.1 TotallyNotJson.529; if TotallyNotJson.1323 then - dec TotallyNotJson.529; dec TotallyNotJson.530; + dec TotallyNotJson.529; let TotallyNotJson.1326 : {} = Struct {}; let TotallyNotJson.1325 : [C {}, C Str] = TagId(0) TotallyNotJson.1326; let TotallyNotJson.1324 : {List U8, [C {}, C Str]} = Struct {TotallyNotJson.526, TotallyNotJson.1325}; @@ -341,8 +341,8 @@ procedure TotallyNotJson.525 (TotallyNotJson.526, TotallyNotJson.1175): let TotallyNotJson.1181 : {List U8, [C {}, C Str]} = Struct {TotallyNotJson.530, TotallyNotJson.1182}; ret TotallyNotJson.1181; else - dec TotallyNotJson.533; dec TotallyNotJson.530; + dec TotallyNotJson.533; let TotallyNotJson.1185 : {} = Struct {}; let TotallyNotJson.1184 : [C {}, C Str] = TagId(0) TotallyNotJson.1185; let TotallyNotJson.1183 : {List U8, [C {}, C Str]} = Struct {TotallyNotJson.526, TotallyNotJson.1184}; @@ -397,8 +397,8 @@ procedure TotallyNotJson.534 (TotallyNotJson.535): procedure TotallyNotJson.536 (TotallyNotJson.1192): let TotallyNotJson.1193 : List U8 = StructAtIndex 1 TotallyNotJson.1192; - let #Derived_gen.6 : List U8 = StructAtIndex 0 TotallyNotJson.1192; - dec #Derived_gen.6; + let #Derived_gen.7 : List U8 = StructAtIndex 0 TotallyNotJson.1192; + dec #Derived_gen.7; ret TotallyNotJson.1193; procedure TotallyNotJson.60 (): @@ -867,3 +867,7 @@ procedure TotallyNotJson.70 (#Derived_gen.5): ret TotallyNotJson.1276; in jump TotallyNotJson.1198 #Derived_gen.5; + +procedure TotallyNotJson.8 (): + let TotallyNotJson.1172 : [C , C [], C , C , C , C ] = TagId(2) ; + ret TotallyNotJson.1172; diff --git a/crates/compiler/test_mono/generated/layout_cache_structure_with_multiple_recursive_structures.txt b/crates/compiler/test_mono/generated/layout_cache_structure_with_multiple_recursive_structures.txt index d94a1b57be..62123e4418 100644 --- a/crates/compiler/test_mono/generated/layout_cache_structure_with_multiple_recursive_structures.txt +++ b/crates/compiler/test_mono/generated/layout_cache_structure_with_multiple_recursive_structures.txt @@ -1,49 +1,41 @@ -procedure List.145 (List.146, List.147, List.144): - let List.540 : [, C {[C *self, ], *self}] = CallByName Test.7 List.146 List.147; - ret List.540; - -procedure List.18 (List.142, List.143, List.144): - let List.521 : [, C {[C *self, ], *self}] = CallByName List.93 List.142 List.143 List.144; - ret List.521; +procedure List.18 (List.145, List.146, List.147): + let List.536 : U64 = 0i64; + let List.537 : U64 = CallByName List.6 List.145; + let List.535 : [, C {[C *self, ], *self}] = CallByName List.86 List.145 List.146 List.147 List.536 List.537; + ret List.535; procedure List.6 (#Attr.2): - let List.538 : U64 = lowlevel ListLen #Attr.2; - ret List.538; + let List.546 : U64 = lowlevel ListLen #Attr.2; + ret List.546; procedure List.66 (#Attr.2, #Attr.3): - let List.537 : [C *self, ] = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.537; + let List.545 : [C *self, ] = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.545; -procedure List.80 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4): - joinpoint List.527 List.439 List.440 List.441 List.442 List.443: - let List.529 : Int1 = CallByName Num.22 List.442 List.443; - if List.529 then - let List.536 : [C *self, ] = CallByName List.66 List.439 List.442; - inc List.536; - let List.530 : [, C {[C *self, ], *self}] = CallByName List.145 List.440 List.536 List.441; - let List.533 : U64 = 1i64; - let List.532 : U64 = CallByName Num.19 List.442 List.533; - jump List.527 List.439 List.530 List.441 List.532 List.443; +procedure List.86 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4): + joinpoint List.538 List.148 List.149 List.150 List.151 List.152: + let List.540 : Int1 = CallByName Num.22 List.151 List.152; + if List.540 then + let List.544 : [C *self, ] = CallByName List.66 List.148 List.151; + inc List.544; + let List.153 : [, C {[C *self, ], *self}] = CallByName Test.7 List.149 List.544; + let List.543 : U64 = 1i64; + let List.542 : U64 = CallByName Num.51 List.151 List.543; + jump List.538 List.148 List.153 List.150 List.542 List.152; else - dec List.439; - ret List.440; + dec List.148; + ret List.149; in - jump List.527 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; - -procedure List.93 (List.436, List.437, List.438): - let List.525 : U64 = 0i64; - let List.526 : U64 = CallByName List.6 List.436; - let List.524 : [, C {[C *self, ], *self}] = CallByName List.80 List.436 List.437 List.438 List.525 List.526; - ret List.524; - -procedure Num.19 (#Attr.2, #Attr.3): - let Num.292 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.292; + jump List.538 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; procedure Num.22 (#Attr.2, #Attr.3): let Num.293 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; ret Num.293; +procedure Num.51 (#Attr.2, #Attr.3): + let Num.292 : U64 = lowlevel NumAddWrap #Attr.2 #Attr.3; + ret Num.292; + procedure Test.7 (Test.11, Test.12): let Test.17 : {[C *self, ], [, C {[C *self, ], *self}]} = Struct {Test.12, Test.11}; let Test.16 : [, C {[C *self, ], *self}] = TagId(0) Test.17; diff --git a/crates/compiler/test_mono/generated/list_append.txt b/crates/compiler/test_mono/generated/list_append.txt index e13262740b..62b590417c 100644 --- a/crates/compiler/test_mono/generated/list_append.txt +++ b/crates/compiler/test_mono/generated/list_append.txt @@ -1,16 +1,16 @@ -procedure List.4 (List.113, List.114): - let List.524 : U64 = 1i64; - let List.522 : List I64 = CallByName List.70 List.113 List.524; - let List.521 : List I64 = CallByName List.71 List.522 List.114; - ret List.521; +procedure List.4 (List.116, List.117): + let List.538 : U64 = 1i64; + let List.536 : List I64 = CallByName List.70 List.116 List.538; + let List.535 : List I64 = CallByName List.71 List.536 List.117; + ret List.535; procedure List.70 (#Attr.2, #Attr.3): - let List.525 : List I64 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.525; + let List.539 : List I64 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.539; procedure List.71 (#Attr.2, #Attr.3): - let List.523 : List I64 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.523; + let List.537 : List I64 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.537; procedure Test.0 (): let Test.2 : List I64 = Array [1i64]; diff --git a/crates/compiler/test_mono/generated/list_append_closure.txt b/crates/compiler/test_mono/generated/list_append_closure.txt index e61910787a..4b4643fbd7 100644 --- a/crates/compiler/test_mono/generated/list_append_closure.txt +++ b/crates/compiler/test_mono/generated/list_append_closure.txt @@ -1,16 +1,16 @@ -procedure List.4 (List.113, List.114): - let List.524 : U64 = 1i64; - let List.522 : List I64 = CallByName List.70 List.113 List.524; - let List.521 : List I64 = CallByName List.71 List.522 List.114; - ret List.521; +procedure List.4 (List.116, List.117): + let List.538 : U64 = 1i64; + let List.536 : List I64 = CallByName List.70 List.116 List.538; + let List.535 : List I64 = CallByName List.71 List.536 List.117; + ret List.535; procedure List.70 (#Attr.2, #Attr.3): - let List.525 : List I64 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.525; + let List.539 : List I64 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.539; procedure List.71 (#Attr.2, #Attr.3): - let List.523 : List I64 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.523; + let List.537 : List I64 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.537; procedure Test.1 (Test.2): let Test.6 : I64 = 42i64; diff --git a/crates/compiler/test_mono/generated/list_cannot_update_inplace.txt b/crates/compiler/test_mono/generated/list_cannot_update_inplace.txt index feb8f2d3b7..be6a37f3ca 100644 --- a/crates/compiler/test_mono/generated/list_cannot_update_inplace.txt +++ b/crates/compiler/test_mono/generated/list_cannot_update_inplace.txt @@ -1,25 +1,25 @@ -procedure List.3 (List.105, List.106, List.107): - let List.524 : {List I64, I64} = CallByName List.64 List.105 List.106 List.107; - let List.523 : List I64 = StructAtIndex 0 List.524; - ret List.523; +procedure List.3 (List.108, List.109, List.110): + let List.538 : {List I64, I64} = CallByName List.64 List.108 List.109 List.110; + let List.537 : List I64 = StructAtIndex 0 List.538; + ret List.537; procedure List.6 (#Attr.2): - let List.522 : U64 = lowlevel ListLen #Attr.2; - ret List.522; + let List.536 : U64 = lowlevel ListLen #Attr.2; + ret List.536; -procedure List.64 (List.102, List.103, List.104): - let List.529 : U64 = CallByName List.6 List.102; - let List.526 : Int1 = CallByName Num.22 List.103 List.529; - if List.526 then - let List.527 : {List I64, I64} = CallByName List.67 List.102 List.103 List.104; - ret List.527; +procedure List.64 (List.105, List.106, List.107): + let List.543 : U64 = CallByName List.6 List.105; + let List.540 : Int1 = CallByName Num.22 List.106 List.543; + if List.540 then + let List.541 : {List I64, I64} = CallByName List.67 List.105 List.106 List.107; + ret List.541; else - let List.525 : {List I64, I64} = Struct {List.102, List.104}; - ret List.525; + let List.539 : {List I64, I64} = Struct {List.105, List.107}; + ret List.539; procedure List.67 (#Attr.2, #Attr.3, #Attr.4): - let List.528 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; - ret List.528; + let List.542 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; + ret List.542; procedure Num.19 (#Attr.2, #Attr.3): let Num.292 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; diff --git a/crates/compiler/test_mono/generated/list_get.txt b/crates/compiler/test_mono/generated/list_get.txt index 02404934e9..1db10526ed 100644 --- a/crates/compiler/test_mono/generated/list_get.txt +++ b/crates/compiler/test_mono/generated/list_get.txt @@ -1,24 +1,24 @@ -procedure List.2 (List.97, List.98): - let List.527 : U64 = CallByName List.6 List.97; - let List.523 : Int1 = CallByName Num.22 List.98 List.527; - if List.523 then - let List.525 : I64 = CallByName List.66 List.97 List.98; - dec List.97; - let List.524 : [C {}, C I64] = TagId(1) List.525; - ret List.524; +procedure List.2 (List.100, List.101): + let List.541 : U64 = CallByName List.6 List.100; + let List.537 : Int1 = CallByName Num.22 List.101 List.541; + if List.537 then + let List.539 : I64 = CallByName List.66 List.100 List.101; + dec List.100; + let List.538 : [C {}, C I64] = TagId(1) List.539; + ret List.538; else - dec List.97; - let List.522 : {} = Struct {}; - let List.521 : [C {}, C I64] = TagId(0) List.522; - ret List.521; + dec List.100; + let List.536 : {} = Struct {}; + let List.535 : [C {}, C I64] = TagId(0) List.536; + ret List.535; procedure List.6 (#Attr.2): - let List.528 : U64 = lowlevel ListLen #Attr.2; - ret List.528; + let List.542 : U64 = lowlevel ListLen #Attr.2; + ret List.542; procedure List.66 (#Attr.2, #Attr.3): - let List.526 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.526; + let List.540 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.540; procedure Num.22 (#Attr.2, #Attr.3): let Num.292 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; diff --git a/crates/compiler/test_mono/generated/list_len.txt b/crates/compiler/test_mono/generated/list_len.txt index 9691dc2b48..62da03f9c8 100644 --- a/crates/compiler/test_mono/generated/list_len.txt +++ b/crates/compiler/test_mono/generated/list_len.txt @@ -1,10 +1,10 @@ procedure List.6 (#Attr.2): - let List.521 : U64 = lowlevel ListLen #Attr.2; - ret List.521; + let List.535 : U64 = lowlevel ListLen #Attr.2; + ret List.535; procedure List.6 (#Attr.2): - let List.522 : U64 = lowlevel ListLen #Attr.2; - ret List.522; + let List.536 : U64 = lowlevel ListLen #Attr.2; + ret List.536; procedure Num.19 (#Attr.2, #Attr.3): let Num.292 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; diff --git a/crates/compiler/test_mono/generated/list_map_closure_borrows.txt b/crates/compiler/test_mono/generated/list_map_closure_borrows.txt index c5d65f94a7..dbd45992f6 100644 --- a/crates/compiler/test_mono/generated/list_map_closure_borrows.txt +++ b/crates/compiler/test_mono/generated/list_map_closure_borrows.txt @@ -1,30 +1,30 @@ -procedure List.2 (List.97, List.98): - let List.527 : U64 = CallByName List.6 List.97; - let List.523 : Int1 = CallByName Num.22 List.98 List.527; - if List.523 then - let List.525 : Str = CallByName List.66 List.97 List.98; - inc List.525; - dec List.97; - let List.524 : [C {}, C Str] = TagId(1) List.525; - ret List.524; +procedure List.2 (List.100, List.101): + let List.541 : U64 = CallByName List.6 List.100; + let List.537 : Int1 = CallByName Num.22 List.101 List.541; + if List.537 then + let List.539 : Str = CallByName List.66 List.100 List.101; + inc List.539; + dec List.100; + let List.538 : [C {}, C Str] = TagId(1) List.539; + ret List.538; else - dec List.97; - let List.522 : {} = Struct {}; - let List.521 : [C {}, C Str] = TagId(0) List.522; - ret List.521; + dec List.100; + let List.536 : {} = Struct {}; + let List.535 : [C {}, C Str] = TagId(0) List.536; + ret List.535; procedure List.5 (#Attr.2, #Attr.3): - let List.529 : List Str = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.3 #Attr.3; + let List.543 : List Str = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.3 #Attr.3; decref #Attr.2; - ret List.529; + ret List.543; procedure List.6 (#Attr.2): - let List.528 : U64 = lowlevel ListLen #Attr.2; - ret List.528; + let List.542 : U64 = lowlevel ListLen #Attr.2; + ret List.542; procedure List.66 (#Attr.2, #Attr.3): - let List.526 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.526; + let List.540 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.540; procedure Num.22 (#Attr.2, #Attr.3): let Num.292 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; diff --git a/crates/compiler/test_mono/generated/list_map_closure_owns.txt b/crates/compiler/test_mono/generated/list_map_closure_owns.txt index a384497df2..e005b4fda9 100644 --- a/crates/compiler/test_mono/generated/list_map_closure_owns.txt +++ b/crates/compiler/test_mono/generated/list_map_closure_owns.txt @@ -1,30 +1,30 @@ -procedure List.2 (List.97, List.98): - let List.527 : U64 = CallByName List.6 List.97; - let List.523 : Int1 = CallByName Num.22 List.98 List.527; - if List.523 then - let List.525 : Str = CallByName List.66 List.97 List.98; - inc List.525; - dec List.97; - let List.524 : [C {}, C Str] = TagId(1) List.525; - ret List.524; +procedure List.2 (List.100, List.101): + let List.541 : U64 = CallByName List.6 List.100; + let List.537 : Int1 = CallByName Num.22 List.101 List.541; + if List.537 then + let List.539 : Str = CallByName List.66 List.100 List.101; + inc List.539; + dec List.100; + let List.538 : [C {}, C Str] = TagId(1) List.539; + ret List.538; else - dec List.97; - let List.522 : {} = Struct {}; - let List.521 : [C {}, C Str] = TagId(0) List.522; - ret List.521; + dec List.100; + let List.536 : {} = Struct {}; + let List.535 : [C {}, C Str] = TagId(0) List.536; + ret List.535; procedure List.5 (#Attr.2, #Attr.3): - let List.529 : List Str = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.3 #Attr.3; + let List.543 : List Str = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.3 #Attr.3; decref #Attr.2; - ret List.529; + ret List.543; procedure List.6 (#Attr.2): - let List.528 : U64 = lowlevel ListLen #Attr.2; - ret List.528; + let List.542 : U64 = lowlevel ListLen #Attr.2; + ret List.542; procedure List.66 (#Attr.2, #Attr.3): - let List.526 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.526; + let List.540 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.540; procedure Num.22 (#Attr.2, #Attr.3): let Num.292 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; diff --git a/crates/compiler/test_mono/generated/list_map_take_capturing_or_noncapturing.txt b/crates/compiler/test_mono/generated/list_map_take_capturing_or_noncapturing.txt index 6054fd9062..b466332fab 100644 --- a/crates/compiler/test_mono/generated/list_map_take_capturing_or_noncapturing.txt +++ b/crates/compiler/test_mono/generated/list_map_take_capturing_or_noncapturing.txt @@ -1,23 +1,23 @@ procedure List.5 (#Attr.2, #Attr.3): - let List.522 : U8 = GetTagId #Attr.3; - joinpoint List.523 List.521: - ret List.521; + let List.536 : U8 = GetTagId #Attr.3; + joinpoint List.537 List.535: + ret List.535; in - switch List.522: + switch List.536: case 0: - let List.524 : List U8 = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.4 #Attr.3; + let List.538 : List U8 = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.4 #Attr.3; decref #Attr.2; - jump List.523 List.524; + jump List.537 List.538; case 1: - let List.525 : List U8 = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.6 #Attr.3; + let List.539 : List U8 = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.6 #Attr.3; decref #Attr.2; - jump List.523 List.525; + jump List.537 List.539; default: - let List.526 : List U8 = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.8 #Attr.3; + let List.540 : List U8 = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.8 #Attr.3; decref #Attr.2; - jump List.523 List.526; + jump List.537 List.540; procedure Num.19 (#Attr.2, #Attr.3): @@ -57,8 +57,8 @@ procedure Test.0 (): else let Test.20 : Str = "B"; let Test.21 : Int1 = lowlevel Eq Test.20 Test.12; - dec Test.20; dec Test.12; + dec Test.20; if Test.21 then let Test.16 : [C U8, C U8, C ] = TagId(1) Test.2; jump Test.13 Test.16; diff --git a/crates/compiler/test_mono/generated/list_pass_to_function.txt b/crates/compiler/test_mono/generated/list_pass_to_function.txt index e2b7c8a453..d54f51187c 100644 --- a/crates/compiler/test_mono/generated/list_pass_to_function.txt +++ b/crates/compiler/test_mono/generated/list_pass_to_function.txt @@ -1,25 +1,25 @@ -procedure List.3 (List.105, List.106, List.107): - let List.522 : {List I64, I64} = CallByName List.64 List.105 List.106 List.107; - let List.521 : List I64 = StructAtIndex 0 List.522; - ret List.521; +procedure List.3 (List.108, List.109, List.110): + let List.536 : {List I64, I64} = CallByName List.64 List.108 List.109 List.110; + let List.535 : List I64 = StructAtIndex 0 List.536; + ret List.535; procedure List.6 (#Attr.2): - let List.528 : U64 = lowlevel ListLen #Attr.2; - ret List.528; + let List.542 : U64 = lowlevel ListLen #Attr.2; + ret List.542; -procedure List.64 (List.102, List.103, List.104): - let List.527 : U64 = CallByName List.6 List.102; - let List.524 : Int1 = CallByName Num.22 List.103 List.527; - if List.524 then - let List.525 : {List I64, I64} = CallByName List.67 List.102 List.103 List.104; - ret List.525; +procedure List.64 (List.105, List.106, List.107): + let List.541 : U64 = CallByName List.6 List.105; + let List.538 : Int1 = CallByName Num.22 List.106 List.541; + if List.538 then + let List.539 : {List I64, I64} = CallByName List.67 List.105 List.106 List.107; + ret List.539; else - let List.523 : {List I64, I64} = Struct {List.102, List.104}; - ret List.523; + let List.537 : {List I64, I64} = Struct {List.105, List.107}; + ret List.537; procedure List.67 (#Attr.2, #Attr.3, #Attr.4): - let List.526 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; - ret List.526; + let List.540 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; + ret List.540; procedure Num.22 (#Attr.2, #Attr.3): let Num.292 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; diff --git a/crates/compiler/test_mono/generated/list_sort_asc.txt b/crates/compiler/test_mono/generated/list_sort_asc.txt index 92a0c599c1..a6c4bb0cac 100644 --- a/crates/compiler/test_mono/generated/list_sort_asc.txt +++ b/crates/compiler/test_mono/generated/list_sort_asc.txt @@ -1,11 +1,11 @@ procedure List.28 (#Attr.2, #Attr.3): - let List.523 : List I64 = lowlevel ListSortWith { xs: `#Attr.#arg1` } #Attr.2 Num.46 #Attr.3; - ret List.523; + let List.537 : List I64 = lowlevel ListSortWith { xs: `#Attr.#arg1` } #Attr.2 Num.46 #Attr.3; + ret List.537; -procedure List.59 (List.288): - let List.522 : {} = Struct {}; - let List.521 : List I64 = CallByName List.28 List.288 List.522; - ret List.521; +procedure List.59 (List.301): + let List.536 : {} = Struct {}; + let List.535 : List I64 = CallByName List.28 List.301 List.536; + ret List.535; procedure Num.46 (#Attr.2, #Attr.3): let Num.292 : U8 = lowlevel NumCompare #Attr.2 #Attr.3; diff --git a/crates/compiler/test_mono/generated/pattern_as_toplevel.txt b/crates/compiler/test_mono/generated/pattern_as_toplevel.txt index 4a70501f51..a124668cf0 100644 --- a/crates/compiler/test_mono/generated/pattern_as_toplevel.txt +++ b/crates/compiler/test_mono/generated/pattern_as_toplevel.txt @@ -20,9 +20,9 @@ procedure Test.0 (): if Test.13 then let Test.6 : {I64, Str} = CallByName Test.1; let Test.5 : Int1 = CallByName Bool.11 Test.6 Test.4; - dec Test.6; let #Derived_gen.0 : Str = StructAtIndex 1 Test.4; dec #Derived_gen.0; + dec Test.6; ret Test.5; else let #Derived_gen.1 : Str = StructAtIndex 1 Test.4; diff --git a/crates/compiler/test_mono/generated/quicksort_swap.txt b/crates/compiler/test_mono/generated/quicksort_swap.txt index b592bcc4e6..6003cc445f 100644 --- a/crates/compiler/test_mono/generated/quicksort_swap.txt +++ b/crates/compiler/test_mono/generated/quicksort_swap.txt @@ -1,43 +1,43 @@ -procedure List.2 (List.97, List.98): - let List.543 : U64 = CallByName List.6 List.97; - let List.540 : Int1 = CallByName Num.22 List.98 List.543; - if List.540 then - let List.542 : I64 = CallByName List.66 List.97 List.98; - dec List.97; - let List.541 : [C {}, C I64] = TagId(1) List.542; - ret List.541; +procedure List.2 (List.100, List.101): + let List.557 : U64 = CallByName List.6 List.100; + let List.554 : Int1 = CallByName Num.22 List.101 List.557; + if List.554 then + let List.556 : I64 = CallByName List.66 List.100 List.101; + dec List.100; + let List.555 : [C {}, C I64] = TagId(1) List.556; + ret List.555; else - dec List.97; - let List.539 : {} = Struct {}; - let List.538 : [C {}, C I64] = TagId(0) List.539; - ret List.538; + dec List.100; + let List.553 : {} = Struct {}; + let List.552 : [C {}, C I64] = TagId(0) List.553; + ret List.552; -procedure List.3 (List.105, List.106, List.107): - let List.530 : {List I64, I64} = CallByName List.64 List.105 List.106 List.107; - let List.529 : List I64 = StructAtIndex 0 List.530; - ret List.529; +procedure List.3 (List.108, List.109, List.110): + let List.544 : {List I64, I64} = CallByName List.64 List.108 List.109 List.110; + let List.543 : List I64 = StructAtIndex 0 List.544; + ret List.543; procedure List.6 (#Attr.2): - let List.528 : U64 = lowlevel ListLen #Attr.2; - ret List.528; + let List.542 : U64 = lowlevel ListLen #Attr.2; + ret List.542; -procedure List.64 (List.102, List.103, List.104): - let List.527 : U64 = CallByName List.6 List.102; - let List.524 : Int1 = CallByName Num.22 List.103 List.527; - if List.524 then - let List.525 : {List I64, I64} = CallByName List.67 List.102 List.103 List.104; - ret List.525; +procedure List.64 (List.105, List.106, List.107): + let List.541 : U64 = CallByName List.6 List.105; + let List.538 : Int1 = CallByName Num.22 List.106 List.541; + if List.538 then + let List.539 : {List I64, I64} = CallByName List.67 List.105 List.106 List.107; + ret List.539; else - let List.523 : {List I64, I64} = Struct {List.102, List.104}; - ret List.523; + let List.537 : {List I64, I64} = Struct {List.105, List.107}; + ret List.537; procedure List.66 (#Attr.2, #Attr.3): - let List.536 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.536; + let List.550 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.550; procedure List.67 (#Attr.2, #Attr.3, #Attr.4): - let List.526 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; - ret List.526; + let List.540 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; + ret List.540; procedure Num.22 (#Attr.2, #Attr.3): let Num.294 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; diff --git a/crates/compiler/test_mono/generated/record_update.txt b/crates/compiler/test_mono/generated/record_update.txt index e5b9598325..f14463363f 100644 --- a/crates/compiler/test_mono/generated/record_update.txt +++ b/crates/compiler/test_mono/generated/record_update.txt @@ -1,25 +1,25 @@ -procedure List.3 (List.105, List.106, List.107): - let List.530 : {List U64, U64} = CallByName List.64 List.105 List.106 List.107; - let List.529 : List U64 = StructAtIndex 0 List.530; - ret List.529; +procedure List.3 (List.108, List.109, List.110): + let List.544 : {List U64, U64} = CallByName List.64 List.108 List.109 List.110; + let List.543 : List U64 = StructAtIndex 0 List.544; + ret List.543; procedure List.6 (#Attr.2): - let List.528 : U64 = lowlevel ListLen #Attr.2; - ret List.528; + let List.542 : U64 = lowlevel ListLen #Attr.2; + ret List.542; -procedure List.64 (List.102, List.103, List.104): - let List.527 : U64 = CallByName List.6 List.102; - let List.524 : Int1 = CallByName Num.22 List.103 List.527; - if List.524 then - let List.525 : {List U64, U64} = CallByName List.67 List.102 List.103 List.104; - ret List.525; +procedure List.64 (List.105, List.106, List.107): + let List.541 : U64 = CallByName List.6 List.105; + let List.538 : Int1 = CallByName Num.22 List.106 List.541; + if List.538 then + let List.539 : {List U64, U64} = CallByName List.67 List.105 List.106 List.107; + ret List.539; else - let List.523 : {List U64, U64} = Struct {List.102, List.104}; - ret List.523; + let List.537 : {List U64, U64} = Struct {List.105, List.107}; + ret List.537; procedure List.67 (#Attr.2, #Attr.3, #Attr.4): - let List.526 : {List U64, U64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; - ret List.526; + let List.540 : {List U64, U64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; + ret List.540; procedure Num.22 (#Attr.2, #Attr.3): let Num.292 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; diff --git a/crates/compiler/test_mono/generated/recursive_function_and_union_with_inference_hole.txt b/crates/compiler/test_mono/generated/recursive_function_and_union_with_inference_hole.txt index 2e772fba51..33c93ab540 100644 --- a/crates/compiler/test_mono/generated/recursive_function_and_union_with_inference_hole.txt +++ b/crates/compiler/test_mono/generated/recursive_function_and_union_with_inference_hole.txt @@ -1,15 +1,15 @@ procedure List.5 (#Attr.2, #Attr.3): - let List.521 : List [C List *self] = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.2 #Attr.3; + let List.535 : List [C List *self] = lowlevel ListMap { xs: `#Attr.#arg1` } #Attr.2 Test.2 #Attr.3; decref #Attr.2; - ret List.521; + ret List.535; procedure Test.2 (Test.5): let Test.6 : List [C List *self] = UnionAtIndex (Id 0) (Index 0) Test.5; inc Test.6; - let #Derived_gen.2 : [C List *self] = Reset { symbol: Test.5, id: UpdateModeId { id: 1 } }; + let #Derived_gen.1 : [C List *self] = Reset { symbol: Test.5, id: UpdateModeId { id: 0 } }; let Test.15 : {} = Struct {}; let Test.7 : List [C List *self] = CallByName List.5 Test.6 Test.15; - let Test.14 : [C List *self] = Reuse #Derived_gen.2 UpdateModeId { id: 1 } TagId(0) Test.7; + let Test.14 : [C List *self] = Reuse #Derived_gen.1 UpdateModeId { id: 0 } TagId(0) Test.7; ret Test.14; procedure Test.0 (): diff --git a/crates/compiler/test_mono/generated/recursive_lambda_set_resolved_only_upon_specialization.txt b/crates/compiler/test_mono/generated/recursive_lambda_set_resolved_only_upon_specialization.txt index a6ad8acc15..4dd159615f 100644 --- a/crates/compiler/test_mono/generated/recursive_lambda_set_resolved_only_upon_specialization.txt +++ b/crates/compiler/test_mono/generated/recursive_lambda_set_resolved_only_upon_specialization.txt @@ -10,7 +10,7 @@ procedure Num.21 (#Attr.2, #Attr.3): let Num.292 : U8 = lowlevel NumMul #Attr.2 #Attr.3; ret Num.292; -procedure Test.1 (#Derived_gen.0, #Derived_gen.1): +procedure Test.1 (#Derived_gen.2, #Derived_gen.3): joinpoint Test.11 Test.2 Test.3: let Test.24 : U8 = 0i64; let Test.20 : Int1 = CallByName Bool.11 Test.2 Test.24; @@ -33,9 +33,9 @@ procedure Test.1 (#Derived_gen.0, #Derived_gen.1): let Test.14 : [, C *self U8] = TagId(0) Test.3 Test.2; jump Test.11 Test.13 Test.14; in - jump Test.11 #Derived_gen.0 #Derived_gen.1; + jump Test.11 #Derived_gen.2 #Derived_gen.3; -procedure Test.4 (#Derived_gen.2, #Derived_gen.3): +procedure Test.4 (#Derived_gen.0, #Derived_gen.1): joinpoint Test.15 Test.5 #Attr.12: let Test.2 : U8 = UnionAtIndex (Id 0) (Index 1) #Attr.12; let Test.3 : [, C *self U8] = UnionAtIndex (Id 0) (Index 0) #Attr.12; @@ -61,7 +61,7 @@ procedure Test.4 (#Derived_gen.2, #Derived_gen.3): decref #Attr.12; jump #Derived_gen.4; in - jump Test.15 #Derived_gen.2 #Derived_gen.3; + jump Test.15 #Derived_gen.0 #Derived_gen.1; procedure Test.6 (Test.7): ret Test.7; diff --git a/crates/compiler/test_mono/generated/recursively_build_effect.txt b/crates/compiler/test_mono/generated/recursively_build_effect.txt index cac652954a..7d1b9ea289 100644 --- a/crates/compiler/test_mono/generated/recursively_build_effect.txt +++ b/crates/compiler/test_mono/generated/recursively_build_effect.txt @@ -8,8 +8,8 @@ procedure Str.3 (#Attr.2, #Attr.3): procedure Test.11 (Test.29, #Attr.12): let Test.10 : {} = UnionAtIndex (Id 0) (Index 0) #Attr.12; - let #Derived_gen.9 : Int1 = lowlevel RefCountIsUnique #Attr.12; - if #Derived_gen.9 then + let #Derived_gen.11 : Int1 = lowlevel RefCountIsUnique #Attr.12; + if #Derived_gen.11 then free #Attr.12; ret Test.10; else @@ -19,11 +19,11 @@ procedure Test.11 (Test.29, #Attr.12): procedure Test.11 (Test.29, Test.10): ret Test.10; -procedure Test.14 (#Derived_gen.7, #Derived_gen.8): +procedure Test.14 (#Derived_gen.0, #Derived_gen.1): joinpoint Test.37 Test.36 #Attr.12: let Test.12 : {} = UnionAtIndex (Id 1) (Index 1) #Attr.12; let Test.13 : I64 = UnionAtIndex (Id 1) (Index 0) #Attr.12; - joinpoint #Derived_gen.10: + joinpoint #Derived_gen.9: let Test.43 : {} = Struct {}; let Test.42 : {} = CallByName Test.11 Test.43 Test.12; let Test.38 : [C {}, C I64 {}] = CallByName Test.9 Test.42 Test.13; @@ -38,15 +38,15 @@ procedure Test.14 (#Derived_gen.7, #Derived_gen.8): jump Test.37 Test.40 Test.38; in - let #Derived_gen.11 : Int1 = lowlevel RefCountIsUnique #Attr.12; - if #Derived_gen.11 then + let #Derived_gen.10 : Int1 = lowlevel RefCountIsUnique #Attr.12; + if #Derived_gen.10 then free #Attr.12; - jump #Derived_gen.10; + jump #Derived_gen.9; else decref #Attr.12; - jump #Derived_gen.10; + jump #Derived_gen.9; in - jump Test.37 #Derived_gen.7 #Derived_gen.8; + jump Test.37 #Derived_gen.0 #Derived_gen.1; procedure Test.2 (): let Test.6 : Str = "Hello"; diff --git a/crates/compiler/test_mono/generated/rigids.txt b/crates/compiler/test_mono/generated/rigids.txt index 5ba8e329d0..39cbc68751 100644 --- a/crates/compiler/test_mono/generated/rigids.txt +++ b/crates/compiler/test_mono/generated/rigids.txt @@ -1,43 +1,43 @@ -procedure List.2 (List.97, List.98): - let List.543 : U64 = CallByName List.6 List.97; - let List.540 : Int1 = CallByName Num.22 List.98 List.543; - if List.540 then - let List.542 : I64 = CallByName List.66 List.97 List.98; - dec List.97; - let List.541 : [C {}, C I64] = TagId(1) List.542; - ret List.541; +procedure List.2 (List.100, List.101): + let List.557 : U64 = CallByName List.6 List.100; + let List.554 : Int1 = CallByName Num.22 List.101 List.557; + if List.554 then + let List.556 : I64 = CallByName List.66 List.100 List.101; + dec List.100; + let List.555 : [C {}, C I64] = TagId(1) List.556; + ret List.555; else - dec List.97; - let List.539 : {} = Struct {}; - let List.538 : [C {}, C I64] = TagId(0) List.539; - ret List.538; + dec List.100; + let List.553 : {} = Struct {}; + let List.552 : [C {}, C I64] = TagId(0) List.553; + ret List.552; -procedure List.3 (List.105, List.106, List.107): - let List.530 : {List I64, I64} = CallByName List.64 List.105 List.106 List.107; - let List.529 : List I64 = StructAtIndex 0 List.530; - ret List.529; +procedure List.3 (List.108, List.109, List.110): + let List.544 : {List I64, I64} = CallByName List.64 List.108 List.109 List.110; + let List.543 : List I64 = StructAtIndex 0 List.544; + ret List.543; procedure List.6 (#Attr.2): - let List.528 : U64 = lowlevel ListLen #Attr.2; - ret List.528; + let List.542 : U64 = lowlevel ListLen #Attr.2; + ret List.542; -procedure List.64 (List.102, List.103, List.104): - let List.527 : U64 = CallByName List.6 List.102; - let List.524 : Int1 = CallByName Num.22 List.103 List.527; - if List.524 then - let List.525 : {List I64, I64} = CallByName List.67 List.102 List.103 List.104; - ret List.525; +procedure List.64 (List.105, List.106, List.107): + let List.541 : U64 = CallByName List.6 List.105; + let List.538 : Int1 = CallByName Num.22 List.106 List.541; + if List.538 then + let List.539 : {List I64, I64} = CallByName List.67 List.105 List.106 List.107; + ret List.539; else - let List.523 : {List I64, I64} = Struct {List.102, List.104}; - ret List.523; + let List.537 : {List I64, I64} = Struct {List.105, List.107}; + ret List.537; procedure List.66 (#Attr.2, #Attr.3): - let List.536 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.536; + let List.550 : I64 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.550; procedure List.67 (#Attr.2, #Attr.3, #Attr.4): - let List.526 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; - ret List.526; + let List.540 : {List I64, I64} = lowlevel ListReplaceUnsafe #Attr.2 #Attr.3 #Attr.4; + ret List.540; procedure Num.22 (#Attr.2, #Attr.3): let Num.294 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; diff --git a/crates/compiler/test_mono/generated/specialize_after_match.txt b/crates/compiler/test_mono/generated/specialize_after_match.txt index dfb63f7e7d..58d5048463 100644 --- a/crates/compiler/test_mono/generated/specialize_after_match.txt +++ b/crates/compiler/test_mono/generated/specialize_after_match.txt @@ -23,7 +23,7 @@ procedure Test.2 (Test.9, Test.10): let Test.29 : U64 = CallByName Test.3 Test.9; ret Test.29; else - joinpoint #Derived_gen.4: + joinpoint #Derived_gen.1: let Test.13 : Str = UnionAtIndex (Id 0) (Index 0) Test.10; let Test.14 : [, C Str *self] = UnionAtIndex (Id 0) (Index 1) Test.10; let Test.33 : U64 = CallByName Test.3 Test.12; @@ -36,15 +36,15 @@ procedure Test.2 (Test.9, Test.10): else ret Test.16; in - let #Derived_gen.5 : Int1 = lowlevel RefCountIsUnique Test.9; - if #Derived_gen.5 then + let #Derived_gen.2 : Int1 = lowlevel RefCountIsUnique Test.9; + if #Derived_gen.2 then dec Test.11; free Test.9; - jump #Derived_gen.4; + jump #Derived_gen.1; else inc Test.12; decref Test.9; - jump #Derived_gen.4; + jump #Derived_gen.1; procedure Test.3 (Test.17): let Test.26 : U8 = 1i64; @@ -55,22 +55,22 @@ procedure Test.3 (Test.17): ret Test.22; else let Test.18 : [, C Str *self] = UnionAtIndex (Id 0) (Index 1) Test.17; - joinpoint #Derived_gen.1: + joinpoint #Derived_gen.3: let Test.24 : U64 = 1i64; let Test.25 : U64 = CallByName Test.3 Test.18; let Test.23 : U64 = CallByName Num.19 Test.24 Test.25; ret Test.23; in - let #Derived_gen.3 : Int1 = lowlevel RefCountIsUnique Test.17; - if #Derived_gen.3 then - let #Derived_gen.2 : Str = UnionAtIndex (Id 0) (Index 0) Test.17; - dec #Derived_gen.2; + let #Derived_gen.5 : Int1 = lowlevel RefCountIsUnique Test.17; + if #Derived_gen.5 then + let #Derived_gen.4 : Str = UnionAtIndex (Id 0) (Index 0) Test.17; + dec #Derived_gen.4; free Test.17; - jump #Derived_gen.1; + jump #Derived_gen.3; else inc Test.18; decref Test.17; - jump #Derived_gen.1; + jump #Derived_gen.3; procedure Test.0 (): let Test.5 : [, C Str *self] = TagId(1) ; diff --git a/crates/compiler/test_mono/generated/unspecialized_lambda_set_unification_does_not_duplicate_identical_concrete_types.txt b/crates/compiler/test_mono/generated/unspecialized_lambda_set_unification_does_not_duplicate_identical_concrete_types.txt index ebeec28457..281ef56337 100644 --- a/crates/compiler/test_mono/generated/unspecialized_lambda_set_unification_does_not_duplicate_identical_concrete_types.txt +++ b/crates/compiler/test_mono/generated/unspecialized_lambda_set_unification_does_not_duplicate_identical_concrete_types.txt @@ -33,195 +33,179 @@ procedure Encode.26 (Encode.105, Encode.106): let Encode.108 : List U8 = CallByName Encode.24 Encode.109 Encode.110 Encode.106; ret Encode.108; -procedure List.145 (List.146, List.147, List.144): - let List.566 : {List U8, U64} = CallByName TotallyNotJson.267 List.146 List.147 List.144; - ret List.566; +procedure List.18 (List.145, List.146, List.147): + let List.562 : U64 = 0i64; + let List.563 : U64 = CallByName List.6 List.145; + let List.561 : {List U8, U64} = CallByName List.86 List.145 List.146 List.147 List.562 List.563; + ret List.561; -procedure List.145 (List.146, List.147, List.144): - let List.586 : List U8 = CallByName TotallyNotJson.215 List.146 List.147; - ret List.586; +procedure List.18 (List.145, List.146, List.147): + let List.574 : U64 = 0i64; + let List.575 : U64 = CallByName List.6 List.145; + let List.573 : List U8 = CallByName List.86 List.145 List.146 List.147 List.574 List.575; + ret List.573; -procedure List.18 (List.142, List.143, List.144): - let List.547 : {List U8, U64} = CallByName List.93 List.142 List.143 List.144; - ret List.547; - -procedure List.18 (List.142, List.143, List.144): - let List.567 : List U8 = CallByName List.93 List.142 List.143 List.144; - ret List.567; - -procedure List.26 (List.159, List.160, List.161): - let List.617 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.93 List.159 List.160 List.161; - let List.620 : U8 = 1i64; - let List.621 : U8 = GetTagId List.617; - let List.622 : Int1 = lowlevel Eq List.620 List.621; - if List.622 then - let List.162 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.617; - ret List.162; +procedure List.26 (List.172, List.173, List.174): + let List.615 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.96 List.172 List.173 List.174; + let List.618 : U8 = 1i64; + let List.619 : U8 = GetTagId List.615; + let List.620 : Int1 = lowlevel Eq List.618 List.619; + if List.620 then + let List.175 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.615; + ret List.175; else - let List.163 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.617; - ret List.163; + let List.176 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.615; + ret List.176; -procedure List.4 (List.113, List.114): - let List.546 : U64 = 1i64; - let List.545 : List U8 = CallByName List.70 List.113 List.546; - let List.544 : List U8 = CallByName List.71 List.545 List.114; - ret List.544; +procedure List.4 (List.116, List.117): + let List.560 : U64 = 1i64; + let List.559 : List U8 = CallByName List.70 List.116 List.560; + let List.558 : List U8 = CallByName List.71 List.559 List.117; + ret List.558; -procedure List.49 (List.376, List.377): - let List.609 : U64 = StructAtIndex 0 List.377; - let List.610 : U64 = 0i64; - let List.607 : Int1 = CallByName Bool.11 List.609 List.610; - if List.607 then - dec List.376; - let List.608 : List U8 = Array []; - ret List.608; +procedure List.49 (List.390, List.391): + let List.607 : U64 = StructAtIndex 0 List.391; + let List.608 : U64 = 0i64; + let List.605 : Int1 = CallByName Bool.11 List.607 List.608; + if List.605 then + dec List.390; + let List.606 : List U8 = Array []; + ret List.606; else - let List.604 : U64 = StructAtIndex 1 List.377; - let List.605 : U64 = StructAtIndex 0 List.377; - let List.603 : List U8 = CallByName List.72 List.376 List.604 List.605; - ret List.603; - -procedure List.52 (List.391, List.392): - let List.393 : U64 = CallByName List.6 List.391; - joinpoint List.615 List.394: - let List.613 : U64 = 0i64; - let List.612 : {U64, U64} = Struct {List.394, List.613}; - inc List.391; - let List.395 : List U8 = CallByName List.49 List.391 List.612; - let List.611 : U64 = CallByName Num.20 List.393 List.394; - let List.602 : {U64, U64} = Struct {List.611, List.394}; - let List.396 : List U8 = CallByName List.49 List.391 List.602; - let List.601 : {List U8, List U8} = Struct {List.395, List.396}; + let List.602 : U64 = StructAtIndex 1 List.391; + let List.603 : U64 = StructAtIndex 0 List.391; + let List.601 : List U8 = CallByName List.72 List.390 List.602 List.603; ret List.601; + +procedure List.52 (List.405, List.406): + let List.407 : U64 = CallByName List.6 List.405; + joinpoint List.613 List.408: + let List.611 : U64 = 0i64; + let List.610 : {U64, U64} = Struct {List.408, List.611}; + inc List.405; + let List.409 : List U8 = CallByName List.49 List.405 List.610; + let List.609 : U64 = CallByName Num.75 List.407 List.408; + let List.600 : {U64, U64} = Struct {List.609, List.408}; + let List.410 : List U8 = CallByName List.49 List.405 List.600; + let List.599 : {List U8, List U8} = Struct {List.409, List.410}; + ret List.599; in - let List.616 : Int1 = CallByName Num.24 List.393 List.392; - if List.616 then - jump List.615 List.392; + let List.614 : Int1 = CallByName Num.24 List.407 List.406; + if List.614 then + jump List.613 List.406; else - jump List.615 List.393; + jump List.613 List.407; + +procedure List.6 (#Attr.2): + let List.585 : U64 = lowlevel ListLen #Attr.2; + ret List.585; procedure List.6 (#Attr.2): let List.587 : U64 = lowlevel ListLen #Attr.2; ret List.587; -procedure List.6 (#Attr.2): - let List.589 : U64 = lowlevel ListLen #Attr.2; - ret List.589; - procedure List.66 (#Attr.2, #Attr.3): - let List.563 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.563; + let List.571 : Str = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.571; procedure List.66 (#Attr.2, #Attr.3): let List.583 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; ret List.583; procedure List.68 (#Attr.2): - let List.600 : List U8 = lowlevel ListWithCapacity #Attr.2; - ret List.600; - -procedure List.70 (#Attr.2, #Attr.3): - let List.525 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.525; - -procedure List.71 (#Attr.2, #Attr.3): - let List.523 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.523; - -procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.606 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.606; - -procedure List.8 (#Attr.2, #Attr.3): - let List.598 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + let List.598 : List U8 = lowlevel ListWithCapacity #Attr.2; ret List.598; -procedure List.80 (#Derived_gen.19, #Derived_gen.20, #Derived_gen.21, #Derived_gen.22, #Derived_gen.23): - joinpoint List.553 List.439 List.440 List.441 List.442 List.443: - let List.555 : Int1 = CallByName Num.22 List.442 List.443; - if List.555 then - let List.562 : Str = CallByName List.66 List.439 List.442; - inc List.562; - let List.556 : {List U8, U64} = CallByName List.145 List.440 List.562 List.441; - let List.559 : U64 = 1i64; - let List.558 : U64 = CallByName Num.19 List.442 List.559; - jump List.553 List.439 List.556 List.441 List.558 List.443; - else - dec List.439; - ret List.440; - in - jump List.553 #Derived_gen.19 #Derived_gen.20 #Derived_gen.21 #Derived_gen.22 #Derived_gen.23; +procedure List.70 (#Attr.2, #Attr.3): + let List.539 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.539; -procedure List.80 (#Derived_gen.3, #Derived_gen.4, #Derived_gen.5, #Derived_gen.6, #Derived_gen.7): - joinpoint List.573 List.439 List.440 List.441 List.442 List.443: - let List.575 : Int1 = CallByName Num.22 List.442 List.443; - if List.575 then - let List.582 : U8 = CallByName List.66 List.439 List.442; - let List.576 : List U8 = CallByName List.145 List.440 List.582 List.441; - let List.579 : U64 = 1i64; - let List.578 : U64 = CallByName Num.19 List.442 List.579; - jump List.573 List.439 List.576 List.441 List.578 List.443; - else - dec List.439; - ret List.440; - in - jump List.573 #Derived_gen.3 #Derived_gen.4 #Derived_gen.5 #Derived_gen.6 #Derived_gen.7; +procedure List.71 (#Attr.2, #Attr.3): + let List.537 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.537; + +procedure List.72 (#Attr.2, #Attr.3, #Attr.4): + let List.604 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.604; + +procedure List.8 (#Attr.2, #Attr.3): + let List.596 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.596; procedure List.80 (#Derived_gen.8, #Derived_gen.9, #Derived_gen.10, #Derived_gen.11, #Derived_gen.12): - joinpoint List.626 List.439 List.440 List.441 List.442 List.443: - let List.628 : Int1 = CallByName Num.22 List.442 List.443; - if List.628 then - let List.637 : U8 = CallByName List.66 List.439 List.442; - let List.629 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.440 List.637; - let List.634 : U8 = 1i64; - let List.635 : U8 = GetTagId List.629; - let List.636 : Int1 = lowlevel Eq List.634 List.635; - if List.636 then - let List.444 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.629; - let List.632 : U64 = 1i64; - let List.631 : U64 = CallByName Num.19 List.442 List.632; - jump List.626 List.439 List.444 List.441 List.631 List.443; + joinpoint List.624 List.453 List.454 List.455 List.456 List.457: + let List.626 : Int1 = CallByName Num.22 List.456 List.457; + if List.626 then + let List.635 : U8 = CallByName List.66 List.453 List.456; + let List.627 : [C {U64, Int1}, C {U64, Int1}] = CallByName TotallyNotJson.189 List.454 List.635; + let List.632 : U8 = 1i64; + let List.633 : U8 = GetTagId List.627; + let List.634 : Int1 = lowlevel Eq List.632 List.633; + if List.634 then + let List.458 : {U64, Int1} = UnionAtIndex (Id 1) (Index 0) List.627; + let List.630 : U64 = 1i64; + let List.629 : U64 = CallByName Num.51 List.456 List.630; + jump List.624 List.453 List.458 List.455 List.629 List.457; else - dec List.439; - let List.445 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.629; - let List.633 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.445; - ret List.633; + dec List.453; + let List.459 : {U64, Int1} = UnionAtIndex (Id 0) (Index 0) List.627; + let List.631 : [C {U64, Int1}, C {U64, Int1}] = TagId(0) List.459; + ret List.631; else - dec List.439; - let List.627 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.440; - ret List.627; + dec List.453; + let List.625 : [C {U64, Int1}, C {U64, Int1}] = TagId(1) List.454; + ret List.625; in - jump List.626 #Derived_gen.8 #Derived_gen.9 #Derived_gen.10 #Derived_gen.11 #Derived_gen.12; + jump List.624 #Derived_gen.8 #Derived_gen.9 #Derived_gen.10 #Derived_gen.11 #Derived_gen.12; -procedure List.93 (List.436, List.437, List.438): - let List.551 : U64 = 0i64; - let List.552 : U64 = CallByName List.6 List.436; - let List.550 : {List U8, U64} = CallByName List.80 List.436 List.437 List.438 List.551 List.552; - ret List.550; +procedure List.86 (#Derived_gen.13, #Derived_gen.14, #Derived_gen.15, #Derived_gen.16, #Derived_gen.17): + joinpoint List.576 List.148 List.149 List.150 List.151 List.152: + let List.578 : Int1 = CallByName Num.22 List.151 List.152; + if List.578 then + let List.582 : U8 = CallByName List.66 List.148 List.151; + let List.153 : List U8 = CallByName TotallyNotJson.215 List.149 List.582; + let List.581 : U64 = 1i64; + let List.580 : U64 = CallByName Num.51 List.151 List.581; + jump List.576 List.148 List.153 List.150 List.580 List.152; + else + dec List.148; + ret List.149; + in + jump List.576 #Derived_gen.13 #Derived_gen.14 #Derived_gen.15 #Derived_gen.16 #Derived_gen.17; -procedure List.93 (List.436, List.437, List.438): - let List.571 : U64 = 0i64; - let List.572 : U64 = CallByName List.6 List.436; - let List.570 : List U8 = CallByName List.80 List.436 List.437 List.438 List.571 List.572; - ret List.570; +procedure List.86 (#Derived_gen.3, #Derived_gen.4, #Derived_gen.5, #Derived_gen.6, #Derived_gen.7): + joinpoint List.564 List.148 List.149 List.150 List.151 List.152: + let List.566 : Int1 = CallByName Num.22 List.151 List.152; + if List.566 then + let List.570 : Str = CallByName List.66 List.148 List.151; + inc List.570; + let List.153 : {List U8, U64} = CallByName TotallyNotJson.267 List.149 List.570 List.150; + let List.569 : U64 = 1i64; + let List.568 : U64 = CallByName Num.51 List.151 List.569; + jump List.564 List.148 List.153 List.150 List.568 List.152; + else + dec List.148; + ret List.149; + in + jump List.564 #Derived_gen.3 #Derived_gen.4 #Derived_gen.5 #Derived_gen.6 #Derived_gen.7; -procedure List.93 (List.436, List.437, List.438): - let List.624 : U64 = 0i64; - let List.625 : U64 = CallByName List.6 List.436; - let List.623 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.436 List.437 List.438 List.624 List.625; - ret List.623; +procedure List.96 (List.450, List.451, List.452): + let List.622 : U64 = 0i64; + let List.623 : U64 = CallByName List.6 List.450; + let List.621 : [C {U64, Int1}, C {U64, Int1}] = CallByName List.80 List.450 List.451 List.452 List.622 List.623; + ret List.621; procedure Num.127 (#Attr.2): let Num.299 : U8 = lowlevel NumIntCast #Attr.2; ret Num.299; procedure Num.19 (#Attr.2, #Attr.3): - let Num.308 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.308; + let Num.303 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; + ret Num.303; procedure Num.20 (#Attr.2, #Attr.3): - let Num.312 : U64 = lowlevel NumSub #Attr.2 #Attr.3; - ret Num.312; + let Num.300 : U64 = lowlevel NumSub #Attr.2 #Attr.3; + ret Num.300; procedure Num.21 (#Attr.2, #Attr.3): let Num.305 : U64 = lowlevel NumMul #Attr.2 #Attr.3; @@ -235,6 +219,14 @@ procedure Num.24 (#Attr.2, #Attr.3): let Num.313 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; ret Num.313; +procedure Num.51 (#Attr.2, #Attr.3): + let Num.308 : U64 = lowlevel NumAddWrap #Attr.2 #Attr.3; + ret Num.308; + +procedure Num.75 (#Attr.2, #Attr.3): + let Num.312 : U64 = lowlevel NumSubWrap #Attr.2 #Attr.3; + ret Num.312; + procedure Num.94 (#Attr.2, #Attr.3): let Num.304 : U64 = lowlevel NumDivCeilUnchecked #Attr.2 #Attr.3; ret Num.304; @@ -343,10 +335,6 @@ procedure TotallyNotJson.189 (TotallyNotJson.1270, TotallyNotJson.192): ret TotallyNotJson.1295; -procedure TotallyNotJson.2 (): - let TotallyNotJson.1172 : [C , C [], C , C , C , C ] = TagId(2) ; - ret TotallyNotJson.1172; - procedure TotallyNotJson.215 (TotallyNotJson.216, TotallyNotJson.217): let TotallyNotJson.1241 : List U8 = CallByName TotallyNotJson.27 TotallyNotJson.217; let TotallyNotJson.1240 : List U8 = CallByName List.8 TotallyNotJson.216 TotallyNotJson.1241; @@ -505,8 +493,12 @@ procedure TotallyNotJson.32 (TotallyNotJson.262, TotallyNotJson.263): let TotallyNotJson.1214 : {Str, List Str} = CallByName Encode.23 TotallyNotJson.1215; ret TotallyNotJson.1214; +procedure TotallyNotJson.8 (): + let TotallyNotJson.1172 : [C , C [], C , C , C , C ] = TagId(2) ; + ret TotallyNotJson.1172; + procedure Test.0 (): let Test.12 : {Str, Str} = CallByName Test.3; - let Test.13 : [C , C [], C , C , C , C ] = CallByName TotallyNotJson.2; + let Test.13 : [C , C [], C , C , C , C ] = CallByName TotallyNotJson.8; let Test.11 : List U8 = CallByName Encode.26 Test.12 Test.13; ret Test.11; diff --git a/crates/compiler/test_mono/generated/unspecialized_lambda_set_unification_keeps_all_concrete_types_without_unification_of_unifiable.txt b/crates/compiler/test_mono/generated/unspecialized_lambda_set_unification_keeps_all_concrete_types_without_unification_of_unifiable.txt index cf967c3b4d..6362b5c2e5 100644 --- a/crates/compiler/test_mono/generated/unspecialized_lambda_set_unification_keeps_all_concrete_types_without_unification_of_unifiable.txt +++ b/crates/compiler/test_mono/generated/unspecialized_lambda_set_unification_keeps_all_concrete_types_without_unification_of_unifiable.txt @@ -81,106 +81,86 @@ procedure Encode.26 (Encode.105, Encode.106): let Encode.108 : List U8 = CallByName Encode.24 Encode.109 Encode.110 Encode.106; ret Encode.108; -procedure List.145 (List.146, List.147, List.144): - let List.566 : {List U8, U64} = CallByName TotallyNotJson.267 List.146 List.147 List.144; - ret List.566; +procedure List.18 (List.145, List.146, List.147): + let List.562 : U64 = 0i64; + let List.563 : U64 = CallByName List.6 List.145; + let List.561 : {List U8, U64} = CallByName List.86 List.145 List.146 List.147 List.562 List.563; + ret List.561; -procedure List.145 (List.146, List.147, List.144): - let List.614 : {List U8, U64} = CallByName TotallyNotJson.267 List.146 List.147 List.144; - ret List.614; +procedure List.18 (List.145, List.146, List.147): + let List.602 : U64 = 0i64; + let List.603 : U64 = CallByName List.6 List.145; + let List.601 : {List U8, U64} = CallByName List.86 List.145 List.146 List.147 List.602 List.603; + ret List.601; -procedure List.18 (List.142, List.143, List.144): - let List.547 : {List U8, U64} = CallByName List.93 List.142 List.143 List.144; - ret List.547; - -procedure List.18 (List.142, List.143, List.144): - let List.595 : {List U8, U64} = CallByName List.93 List.142 List.143 List.144; - ret List.595; - -procedure List.4 (List.113, List.114): - let List.594 : U64 = 1i64; - let List.593 : List U8 = CallByName List.70 List.113 List.594; - let List.592 : List U8 = CallByName List.71 List.593 List.114; - ret List.592; +procedure List.4 (List.116, List.117): + let List.600 : U64 = 1i64; + let List.599 : List U8 = CallByName List.70 List.116 List.600; + let List.598 : List U8 = CallByName List.71 List.599 List.117; + ret List.598; procedure List.6 (#Attr.2): - let List.567 : U64 = lowlevel ListLen #Attr.2; - ret List.567; + let List.573 : U64 = lowlevel ListLen #Attr.2; + ret List.573; procedure List.6 (#Attr.2): - let List.615 : U64 = lowlevel ListLen #Attr.2; - ret List.615; + let List.613 : U64 = lowlevel ListLen #Attr.2; + ret List.613; procedure List.66 (#Attr.2, #Attr.3): - let List.563 : [C {}, C {}] = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.563; + let List.571 : [C {}, C {}] = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.571; procedure List.66 (#Attr.2, #Attr.3): let List.611 : [] = lowlevel ListGetUnsafe #Attr.2 #Attr.3; ret List.611; procedure List.70 (#Attr.2, #Attr.3): - let List.573 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; - ret List.573; + let List.579 : List U8 = lowlevel ListReserve #Attr.2 #Attr.3; + ret List.579; procedure List.71 (#Attr.2, #Attr.3): - let List.571 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; - ret List.571; + let List.577 : List U8 = lowlevel ListAppendUnsafe #Attr.2 #Attr.3; + ret List.577; procedure List.8 (#Attr.2, #Attr.3): - let List.616 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; - ret List.616; + let List.614 : List U8 = lowlevel ListConcat #Attr.2 #Attr.3; + ret List.614; -procedure List.80 (#Derived_gen.18, #Derived_gen.19, #Derived_gen.20, #Derived_gen.21, #Derived_gen.22): - joinpoint List.601 List.439 List.440 List.441 List.442 List.443: - let List.603 : Int1 = CallByName Num.22 List.442 List.443; - if List.603 then - let List.610 : [] = CallByName List.66 List.439 List.442; - let List.604 : {List U8, U64} = CallByName List.145 List.440 List.610 List.441; - let List.607 : U64 = 1i64; - let List.606 : U64 = CallByName Num.19 List.442 List.607; - jump List.601 List.439 List.604 List.441 List.606 List.443; +procedure List.86 (#Derived_gen.18, #Derived_gen.19, #Derived_gen.20, #Derived_gen.21, #Derived_gen.22): + joinpoint List.564 List.148 List.149 List.150 List.151 List.152: + let List.566 : Int1 = CallByName Num.22 List.151 List.152; + if List.566 then + let List.570 : [C {}, C {}] = CallByName List.66 List.148 List.151; + let List.153 : {List U8, U64} = CallByName TotallyNotJson.267 List.149 List.570 List.150; + let List.569 : U64 = 1i64; + let List.568 : U64 = CallByName Num.51 List.151 List.569; + jump List.564 List.148 List.153 List.150 List.568 List.152; else - dec List.439; - ret List.440; + dec List.148; + ret List.149; in - jump List.601 #Derived_gen.18 #Derived_gen.19 #Derived_gen.20 #Derived_gen.21 #Derived_gen.22; + jump List.564 #Derived_gen.18 #Derived_gen.19 #Derived_gen.20 #Derived_gen.21 #Derived_gen.22; -procedure List.80 (#Derived_gen.38, #Derived_gen.39, #Derived_gen.40, #Derived_gen.41, #Derived_gen.42): - joinpoint List.553 List.439 List.440 List.441 List.442 List.443: - let List.555 : Int1 = CallByName Num.22 List.442 List.443; - if List.555 then - let List.562 : [C {}, C {}] = CallByName List.66 List.439 List.442; - let List.556 : {List U8, U64} = CallByName List.145 List.440 List.562 List.441; - let List.559 : U64 = 1i64; - let List.558 : U64 = CallByName Num.19 List.442 List.559; - jump List.553 List.439 List.556 List.441 List.558 List.443; +procedure List.86 (#Derived_gen.32, #Derived_gen.33, #Derived_gen.34, #Derived_gen.35, #Derived_gen.36): + joinpoint List.604 List.148 List.149 List.150 List.151 List.152: + let List.606 : Int1 = CallByName Num.22 List.151 List.152; + if List.606 then + let List.610 : [] = CallByName List.66 List.148 List.151; + let List.153 : {List U8, U64} = CallByName TotallyNotJson.267 List.149 List.610 List.150; + let List.609 : U64 = 1i64; + let List.608 : U64 = CallByName Num.51 List.151 List.609; + jump List.604 List.148 List.153 List.150 List.608 List.152; else - dec List.439; - ret List.440; + dec List.148; + ret List.149; in - jump List.553 #Derived_gen.38 #Derived_gen.39 #Derived_gen.40 #Derived_gen.41 #Derived_gen.42; - -procedure List.93 (List.436, List.437, List.438): - let List.551 : U64 = 0i64; - let List.552 : U64 = CallByName List.6 List.436; - let List.550 : {List U8, U64} = CallByName List.80 List.436 List.437 List.438 List.551 List.552; - ret List.550; - -procedure List.93 (List.436, List.437, List.438): - let List.599 : U64 = 0i64; - let List.600 : U64 = CallByName List.6 List.436; - let List.598 : {List U8, U64} = CallByName List.80 List.436 List.437 List.438 List.599 List.600; - ret List.598; + jump List.604 #Derived_gen.32 #Derived_gen.33 #Derived_gen.34 #Derived_gen.35 #Derived_gen.36; procedure Num.127 (#Attr.2): let Num.311 : U8 = lowlevel NumIntCast #Attr.2; ret Num.311; -procedure Num.19 (#Attr.2, #Attr.3): - let Num.314 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.314; - procedure Num.20 (#Attr.2, #Attr.3): let Num.312 : U64 = lowlevel NumSub #Attr.2 #Attr.3; ret Num.312; @@ -193,6 +173,10 @@ procedure Num.24 (#Attr.2, #Attr.3): let Num.313 : Int1 = lowlevel NumGt #Attr.2 #Attr.3; ret Num.313; +procedure Num.51 (#Attr.2, #Attr.3): + let Num.314 : U64 = lowlevel NumAddWrap #Attr.2 #Attr.3; + ret Num.314; + procedure Str.12 (#Attr.2): let Str.290 : List U8 = lowlevel StrToUtf8 #Attr.2; ret Str.290; @@ -228,10 +212,6 @@ procedure Test.5 (Test.6, Test.7, Test.4): let Test.22 : {Str, List [C {}, C {}]} = CallByName TotallyNotJson.32 Test.24 Test.25; jump Test.23 Test.22; -procedure TotallyNotJson.2 (): - let TotallyNotJson.1172 : [C , C [], C , C , C , C ] = TagId(2) ; - ret TotallyNotJson.1172; - procedure TotallyNotJson.264 (TotallyNotJson.265, TotallyNotJson.1175, #Attr.12): let TotallyNotJson.263 : List [C {}, C {}] = StructAtIndex 1 #Attr.12; let TotallyNotJson.262 : Str = StructAtIndex 0 #Attr.12; @@ -346,8 +326,12 @@ procedure TotallyNotJson.32 (TotallyNotJson.262, TotallyNotJson.263): let TotallyNotJson.1257 : {Str, List []} = CallByName Encode.23 TotallyNotJson.1258; ret TotallyNotJson.1257; +procedure TotallyNotJson.8 (): + let TotallyNotJson.1172 : [C , C [], C , C , C , C ] = TagId(2) ; + ret TotallyNotJson.1172; + procedure Test.0 (): let Test.13 : {{}, {}} = CallByName Test.3; - let Test.14 : [C , C [], C , C , C , C ] = CallByName TotallyNotJson.2; + let Test.14 : [C , C [], C , C , C , C ] = CallByName TotallyNotJson.8; let Test.12 : List U8 = CallByName Encode.26 Test.13 Test.14; ret Test.12; diff --git a/crates/compiler/test_mono/generated/weakening_avoids_overspecialization.txt b/crates/compiler/test_mono/generated/weakening_avoids_overspecialization.txt index 1396a444e3..f5f32af4d8 100644 --- a/crates/compiler/test_mono/generated/weakening_avoids_overspecialization.txt +++ b/crates/compiler/test_mono/generated/weakening_avoids_overspecialization.txt @@ -2,97 +2,97 @@ procedure Bool.11 (#Attr.2, #Attr.3): let Bool.24 : Int1 = lowlevel Eq #Attr.2 #Attr.3; ret Bool.24; -procedure List.26 (List.159, List.160, List.161): - let List.536 : [C U64, C U64] = CallByName List.93 List.159 List.160 List.161; - let List.539 : U8 = 1i64; - let List.540 : U8 = GetTagId List.536; - let List.541 : Int1 = lowlevel Eq List.539 List.540; - if List.541 then - let List.162 : U64 = UnionAtIndex (Id 1) (Index 0) List.536; - ret List.162; +procedure List.26 (List.172, List.173, List.174): + let List.550 : [C U64, C U64] = CallByName List.96 List.172 List.173 List.174; + let List.553 : U8 = 1i64; + let List.554 : U8 = GetTagId List.550; + let List.555 : Int1 = lowlevel Eq List.553 List.554; + if List.555 then + let List.175 : U64 = UnionAtIndex (Id 1) (Index 0) List.550; + ret List.175; else - let List.163 : U64 = UnionAtIndex (Id 0) (Index 0) List.536; - ret List.163; + let List.176 : U64 = UnionAtIndex (Id 0) (Index 0) List.550; + ret List.176; -procedure List.29 (List.304, List.305): - let List.535 : U64 = CallByName List.6 List.304; - let List.306 : U64 = CallByName Num.77 List.535 List.305; - let List.521 : List U8 = CallByName List.43 List.304 List.306; - ret List.521; +procedure List.29 (List.317, List.318): + let List.549 : U64 = CallByName List.6 List.317; + let List.319 : U64 = CallByName Num.77 List.549 List.318; + let List.535 : List U8 = CallByName List.43 List.317 List.319; + ret List.535; -procedure List.43 (List.302, List.303): - let List.533 : U64 = CallByName List.6 List.302; - let List.532 : U64 = CallByName Num.77 List.533 List.303; - let List.523 : {U64, U64} = Struct {List.303, List.532}; - let List.522 : List U8 = CallByName List.49 List.302 List.523; - ret List.522; +procedure List.43 (List.315, List.316): + let List.547 : U64 = CallByName List.6 List.315; + let List.546 : U64 = CallByName Num.77 List.547 List.316; + let List.537 : {U64, U64} = Struct {List.316, List.546}; + let List.536 : List U8 = CallByName List.49 List.315 List.537; + ret List.536; -procedure List.49 (List.376, List.377): - let List.530 : U64 = StructAtIndex 0 List.377; - let List.531 : U64 = 0i64; - let List.528 : Int1 = CallByName Bool.11 List.530 List.531; - if List.528 then - dec List.376; - let List.529 : List U8 = Array []; - ret List.529; +procedure List.49 (List.390, List.391): + let List.544 : U64 = StructAtIndex 0 List.391; + let List.545 : U64 = 0i64; + let List.542 : Int1 = CallByName Bool.11 List.544 List.545; + if List.542 then + dec List.390; + let List.543 : List U8 = Array []; + ret List.543; else - let List.525 : U64 = StructAtIndex 1 List.377; - let List.526 : U64 = StructAtIndex 0 List.377; - let List.524 : List U8 = CallByName List.72 List.376 List.525 List.526; - ret List.524; + let List.539 : U64 = StructAtIndex 1 List.391; + let List.540 : U64 = StructAtIndex 0 List.391; + let List.538 : List U8 = CallByName List.72 List.390 List.539 List.540; + ret List.538; procedure List.6 (#Attr.2): - let List.534 : U64 = lowlevel ListLen #Attr.2; - ret List.534; + let List.548 : U64 = lowlevel ListLen #Attr.2; + ret List.548; procedure List.66 (#Attr.2, #Attr.3): - let List.557 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret List.557; + let List.571 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret List.571; procedure List.72 (#Attr.2, #Attr.3, #Attr.4): - let List.527 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; - ret List.527; + let List.541 : List U8 = lowlevel ListSublist #Attr.2 #Attr.3 #Attr.4; + ret List.541; procedure List.80 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3, #Derived_gen.4): - joinpoint List.545 List.439 List.440 List.441 List.442 List.443: - let List.547 : Int1 = CallByName Num.22 List.442 List.443; - if List.547 then - let List.556 : U8 = CallByName List.66 List.439 List.442; - let List.548 : [C U64, C U64] = CallByName Test.3 List.440 List.556; - let List.553 : U8 = 1i64; - let List.554 : U8 = GetTagId List.548; - let List.555 : Int1 = lowlevel Eq List.553 List.554; - if List.555 then - let List.444 : U64 = UnionAtIndex (Id 1) (Index 0) List.548; - let List.551 : U64 = 1i64; - let List.550 : U64 = CallByName Num.19 List.442 List.551; - jump List.545 List.439 List.444 List.441 List.550 List.443; + joinpoint List.559 List.453 List.454 List.455 List.456 List.457: + let List.561 : Int1 = CallByName Num.22 List.456 List.457; + if List.561 then + let List.570 : U8 = CallByName List.66 List.453 List.456; + let List.562 : [C U64, C U64] = CallByName Test.3 List.454 List.570; + let List.567 : U8 = 1i64; + let List.568 : U8 = GetTagId List.562; + let List.569 : Int1 = lowlevel Eq List.567 List.568; + if List.569 then + let List.458 : U64 = UnionAtIndex (Id 1) (Index 0) List.562; + let List.565 : U64 = 1i64; + let List.564 : U64 = CallByName Num.51 List.456 List.565; + jump List.559 List.453 List.458 List.455 List.564 List.457; else - dec List.439; - let List.445 : U64 = UnionAtIndex (Id 0) (Index 0) List.548; - let List.552 : [C U64, C U64] = TagId(0) List.445; - ret List.552; + dec List.453; + let List.459 : U64 = UnionAtIndex (Id 0) (Index 0) List.562; + let List.566 : [C U64, C U64] = TagId(0) List.459; + ret List.566; else - dec List.439; - let List.546 : [C U64, C U64] = TagId(1) List.440; - ret List.546; + dec List.453; + let List.560 : [C U64, C U64] = TagId(1) List.454; + ret List.560; in - jump List.545 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; + jump List.559 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4; -procedure List.93 (List.436, List.437, List.438): - let List.543 : U64 = 0i64; - let List.544 : U64 = CallByName List.6 List.436; - let List.542 : [C U64, C U64] = CallByName List.80 List.436 List.437 List.438 List.543 List.544; - ret List.542; - -procedure Num.19 (#Attr.2, #Attr.3): - let Num.294 : U64 = lowlevel NumAdd #Attr.2 #Attr.3; - ret Num.294; +procedure List.96 (List.450, List.451, List.452): + let List.557 : U64 = 0i64; + let List.558 : U64 = CallByName List.6 List.450; + let List.556 : [C U64, C U64] = CallByName List.80 List.450 List.451 List.452 List.557 List.558; + ret List.556; procedure Num.22 (#Attr.2, #Attr.3): let Num.295 : Int1 = lowlevel NumLt #Attr.2 #Attr.3; ret Num.295; +procedure Num.51 (#Attr.2, #Attr.3): + let Num.294 : U64 = lowlevel NumAddWrap #Attr.2 #Attr.3; + ret Num.294; + procedure Num.77 (#Attr.2, #Attr.3): let Num.293 : U64 = lowlevel NumSubSaturated #Attr.2 #Attr.3; ret Num.293; diff --git a/crates/compiler/test_mono/src/tests.rs b/crates/compiler/test_mono/src/tests.rs index 96574e82e5..41a0cf2234 100644 --- a/crates/compiler/test_mono/src/tests.rs +++ b/crates/compiler/test_mono/src/tests.rs @@ -1349,10 +1349,10 @@ fn specialize_ability_call() { r#" app "test" provides [main] to "./platform" - MHash has - hash : a -> U64 | a has MHash + MHash implements + hash : a -> U64 where a implements MHash - Id := U64 has [MHash {hash}] + Id := U64 implements [MHash {hash}] hash : Id -> U64 hash = \@Id n -> n @@ -1385,20 +1385,20 @@ fn encode() { r#" app "test" provides [myU8Bytes] to "./platform" - MEncoder fmt := List U8, fmt -> List U8 | fmt has Format + MEncoder fmt := List U8, fmt -> List U8 where fmt implements Format - MEncoding has - toEncoder : val -> MEncoder fmt | val has MEncoding, fmt has Format + MEncoding implements + toEncoder : val -> MEncoder fmt where val implements MEncoding, fmt implements Format - Format has - u8 : U8 -> MEncoder fmt | fmt has Format + Format implements + u8 : U8 -> MEncoder fmt where fmt implements Format - Linear := {} has [Format {u8}] + Linear := {} implements [Format {u8}] u8 = \n -> @MEncoder (\lst, @Linear {} -> List.append lst n) - MyU8 := U8 has [MEncoding {toEncoder}] + MyU8 := U8 implements [MEncoding {toEncoder}] toEncoder = \@MyU8 n -> u8 n @@ -2579,20 +2579,20 @@ fn unspecialized_lambda_set_unification_keeps_all_concrete_types_without_unifica r#" app "test" provides [main] to "./platform" - MEncoder fmt := List U8, fmt -> List U8 | fmt has Format + MEncoder fmt := List U8, fmt -> List U8 where fmt implements Format - MEncoding has - toEncoder : val -> MEncoder fmt | val has MEncoding, fmt has Format + MEncoding implements + toEncoder : val -> MEncoder fmt where val implements MEncoding, fmt implements Format - Format has - u8 : {} -> MEncoder fmt | fmt has Format - str : {} -> MEncoder fmt | fmt has Format - tag : MEncoder fmt -> MEncoder fmt | fmt has Format + Format implements + u8 : {} -> MEncoder fmt where fmt implements Format + str : {} -> MEncoder fmt where fmt implements Format + tag : MEncoder fmt -> MEncoder fmt where fmt implements Format - Linear := {} has [Format {u8: lU8, str: lStr, tag: lTag}] + Linear := {} implements [Format {u8: lU8, str: lStr, tag: lTag}] - MU8 := U8 has [MEncoding {toEncoder: toEncoderU8}] - MStr := Str has [MEncoding {toEncoder: toEncoderStr}] + MU8 := U8 implements [MEncoding {toEncoder: toEncoderU8}] + MStr := Str implements [MEncoding {toEncoder: toEncoderStr}] Q a b := { a: a, b: b } @@ -2642,7 +2642,7 @@ fn unspecialized_lambda_set_unification_keeps_all_concrete_types_without_unifica r#" app "test" imports [TotallyNotJson] provides [main] to "./platform" - Q a b := { a: a, b: b } has [Encoding {toEncoder: toEncoderQ}] + Q a b := { a: a, b: b } implements [Encoding {toEncoder: toEncoderQ}] toEncoderQ = \@Q t -> Encode.custom \bytes, fmt -> @@ -2680,7 +2680,7 @@ fn unspecialized_lambda_set_unification_does_not_duplicate_identical_concrete_ty r#" app "test" imports [TotallyNotJson] provides [main] to "./platform" - Q a b := { a: a, b: b } has [Encoding {toEncoder: toEncoderQ}] + Q a b := { a: a, b: b } implements [Encoding {toEncoder: toEncoderQ}] toEncoderQ = \@Q t -> Encode.custom \bytes, fmt -> diff --git a/crates/compiler/test_syntax/fuzz/dict.txt b/crates/compiler/test_syntax/fuzz/dict.txt index 805712e5ff..6368aa3e2d 100644 --- a/crates/compiler/test_syntax/fuzz/dict.txt +++ b/crates/compiler/test_syntax/fuzz/dict.txt @@ -6,7 +6,7 @@ "is" "expect" "dbg" -"has" +"implements" "app" "platform" diff --git a/crates/compiler/test_syntax/tests/snapshots/fail/ability_demand_value_has_args.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/fail/ability_demand_value_has_args.expr.result-ast index 3cb44e1fdf..1e781bb579 100644 --- a/crates/compiler/test_syntax/tests/snapshots/fail/ability_demand_value_has_args.expr.result-ast +++ b/crates/compiler/test_syntax/tests/snapshots/fail/ability_demand_value_has_args.expr.result-ast @@ -1 +1 @@ -Expr(Ability(DemandColon(@15), @7), @0) \ No newline at end of file +Expr(Ability(DemandColon(@22), @14), @0) \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/fail/ability_demand_value_has_args.expr.roc b/crates/compiler/test_syntax/tests/snapshots/fail/ability_demand_value_has_args.expr.roc index d6df16d287..1ae763fa66 100644 --- a/crates/compiler/test_syntax/tests/snapshots/fail/ability_demand_value_has_args.expr.roc +++ b/crates/compiler/test_syntax/tests/snapshots/fail/ability_demand_value_has_args.expr.roc @@ -1,4 +1,4 @@ -MEq has - eq b c : a, a -> U64 | a has MEq +MEq implements + eq b c : a, a -> U64 where a implements MEq 1 diff --git a/crates/compiler/test_syntax/tests/snapshots/fail/ability_demands_not_indented_with_first.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/fail/ability_demands_not_indented_with_first.expr.result-ast index b4df5acd38..4d5187ee9f 100644 --- a/crates/compiler/test_syntax/tests/snapshots/fail/ability_demands_not_indented_with_first.expr.result-ast +++ b/crates/compiler/test_syntax/tests/snapshots/fail/ability_demands_not_indented_with_first.expr.result-ast @@ -1 +1 @@ -Expr(Ability(DemandAlignment(4, @49), @40), @0) \ No newline at end of file +Expr(Ability(DemandAlignment(4, @67), @58), @0) \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/fail/ability_demands_not_indented_with_first.expr.roc b/crates/compiler/test_syntax/tests/snapshots/fail/ability_demands_not_indented_with_first.expr.roc index f07901e9cc..d4b478df18 100644 --- a/crates/compiler/test_syntax/tests/snapshots/fail/ability_demands_not_indented_with_first.expr.roc +++ b/crates/compiler/test_syntax/tests/snapshots/fail/ability_demands_not_indented_with_first.expr.roc @@ -1,5 +1,5 @@ -MEq has - eq : a, a -> U64 | a has MEq - neq : a, a -> U64 | a has MEq +MEq implements + eq : a, a -> U64 where a implements MEq + neq : a, a -> U64 where a implements MEq 1 diff --git a/crates/compiler/test_syntax/tests/snapshots/fail/ability_first_demand_not_indented_enough.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/fail/ability_first_demand_not_indented_enough.expr.result-ast index f069010c69..d3fb65ba18 100644 --- a/crates/compiler/test_syntax/tests/snapshots/fail/ability_first_demand_not_indented_enough.expr.result-ast +++ b/crates/compiler/test_syntax/tests/snapshots/fail/ability_first_demand_not_indented_enough.expr.result-ast @@ -1 +1 @@ -Expr(Ability(DemandAlignment(-1, @8), @7), @0) \ No newline at end of file +Expr(Ability(DemandAlignment(-1, @15), @14), @0) \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/fail/ability_first_demand_not_indented_enough.expr.roc b/crates/compiler/test_syntax/tests/snapshots/fail/ability_first_demand_not_indented_enough.expr.roc index 3b76e70bc2..fb55dc8219 100644 --- a/crates/compiler/test_syntax/tests/snapshots/fail/ability_first_demand_not_indented_enough.expr.roc +++ b/crates/compiler/test_syntax/tests/snapshots/fail/ability_first_demand_not_indented_enough.expr.roc @@ -1,4 +1,4 @@ -MEq has -eq : a, a -> U64 | a has MEq +MEq implements +eq : a, a -> U64 where a implements MEq 1 diff --git a/crates/compiler/test_syntax/tests/snapshots/fail/ability_non_signature_expression.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/fail/ability_non_signature_expression.expr.result-ast index a66a3a05e5..08763b5ffb 100644 --- a/crates/compiler/test_syntax/tests/snapshots/fail/ability_non_signature_expression.expr.result-ast +++ b/crates/compiler/test_syntax/tests/snapshots/fail/ability_non_signature_expression.expr.result-ast @@ -1 +1 @@ -Expr(Ability(DemandName(@12), @7), @0) \ No newline at end of file +Expr(Ability(DemandName(@19), @14), @0) \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/fail/ability_non_signature_expression.expr.roc b/crates/compiler/test_syntax/tests/snapshots/fail/ability_non_signature_expression.expr.roc index 0651010e94..02772c6ee7 100644 --- a/crates/compiler/test_syntax/tests/snapshots/fail/ability_non_signature_expression.expr.roc +++ b/crates/compiler/test_syntax/tests/snapshots/fail/ability_non_signature_expression.expr.roc @@ -1,4 +1,4 @@ -MEq has +MEq implements 123 1 diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/ability_demand_signature_is_multiline.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/ability_demand_signature_is_multiline.expr.formatted.roc index 9f2662a247..4056155950 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/ability_demand_signature_is_multiline.expr.formatted.roc +++ b/crates/compiler/test_syntax/tests/snapshots/pass/ability_demand_signature_is_multiline.expr.formatted.roc @@ -1,4 +1,4 @@ -Hash has +Hash implements hash : a -> U64 diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/ability_demand_signature_is_multiline.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/ability_demand_signature_is_multiline.expr.result-ast index 7f97d78500..03168073e5 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/ability_demand_signature_is_multiline.expr.result-ast +++ b/crates/compiler/test_syntax/tests/snapshots/pass/ability_demand_signature_is_multiline.expr.result-ast @@ -4,7 +4,7 @@ Defs( Index(0), ], regions: [ - @0-36, + @0-43, ], space_before: [ Slice(start = 0, length = 0), @@ -19,18 +19,18 @@ Defs( name: @0-4 "Hash", vars: [], }, - loc_has: @5-8 Has, + loc_implements: @5-15 Implements, members: [ AbilityMember { - name: @11-15 SpaceBefore( + name: @18-22 SpaceBefore( "hash", [ Newline, ], ), - typ: @18-36 Function( + typ: @25-43 Function( [ - @18-19 SpaceAfter( + @25-26 SpaceAfter( BoundVariable( "a", ), @@ -39,7 +39,7 @@ Defs( ], ), ], - @33-36 Apply( + @40-43 Apply( "", "U64", [], @@ -51,7 +51,7 @@ Defs( ], value_defs: [], }, - @38-39 SpaceBefore( + @45-46 SpaceBefore( Num( "1", ), diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/ability_demand_signature_is_multiline.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/ability_demand_signature_is_multiline.expr.roc index 5e218feb6e..02de08c9ec 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/ability_demand_signature_is_multiline.expr.roc +++ b/crates/compiler/test_syntax/tests/snapshots/pass/ability_demand_signature_is_multiline.expr.roc @@ -1,4 +1,4 @@ -Hash has +Hash implements hash : a -> U64 diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/ability_multi_line.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/ability_multi_line.expr.formatted.roc index 56efcb2abc..740886df35 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/ability_multi_line.expr.formatted.roc +++ b/crates/compiler/test_syntax/tests/snapshots/pass/ability_multi_line.expr.formatted.roc @@ -1,4 +1,4 @@ -Hash has +Hash implements hash : a -> U64 hash2 : a -> U64 diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/ability_multi_line.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/ability_multi_line.expr.result-ast index 35bbb58f04..9203211925 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/ability_multi_line.expr.result-ast +++ b/crates/compiler/test_syntax/tests/snapshots/pass/ability_multi_line.expr.result-ast @@ -4,7 +4,7 @@ Defs( Index(0), ], regions: [ - @0-45, + @0-52, ], space_before: [ Slice(start = 0, length = 0), @@ -19,22 +19,22 @@ Defs( name: @0-4 "Hash", vars: [], }, - loc_has: @5-8 Has, + loc_implements: @5-15 Implements, members: [ AbilityMember { - name: @11-15 SpaceBefore( + name: @18-22 SpaceBefore( "hash", [ Newline, ], ), - typ: @18-26 Function( + typ: @25-33 Function( [ - @18-19 BoundVariable( + @25-26 BoundVariable( "a", ), ], - @23-26 Apply( + @30-33 Apply( "", "U64", [], @@ -42,19 +42,19 @@ Defs( ), }, AbilityMember { - name: @29-34 SpaceBefore( + name: @36-41 SpaceBefore( "hash2", [ Newline, ], ), - typ: @37-45 Function( + typ: @44-52 Function( [ - @37-38 BoundVariable( + @44-45 BoundVariable( "a", ), ], - @42-45 Apply( + @49-52 Apply( "", "U64", [], @@ -66,7 +66,7 @@ Defs( ], value_defs: [], }, - @47-48 SpaceBefore( + @54-55 SpaceBefore( Num( "1", ), diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/ability_multi_line.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/ability_multi_line.expr.roc index 795c19bad6..43b178a6bd 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/ability_multi_line.expr.roc +++ b/crates/compiler/test_syntax/tests/snapshots/pass/ability_multi_line.expr.roc @@ -1,4 +1,4 @@ -Hash has +Hash implements hash : a -> U64 hash2 : a -> U64 diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/ability_single_line.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/ability_single_line.expr.result-ast index e450865a13..2847f04b1d 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/ability_single_line.expr.result-ast +++ b/crates/compiler/test_syntax/tests/snapshots/pass/ability_single_line.expr.result-ast @@ -4,7 +4,7 @@ Defs( Index(0), ], regions: [ - @0-37, + @0-55, ], space_before: [ Slice(start = 0, length = 0), @@ -19,28 +19,28 @@ Defs( name: @0-4 "Hash", vars: [], }, - loc_has: @5-8 Has, + loc_implements: @5-15 Implements, members: [ AbilityMember { - name: @9-13 "hash", - typ: @16-37 Where( - @16-24 Function( + name: @16-20 "hash", + typ: @23-55 Where( + @23-31 Function( [ - @16-17 BoundVariable( + @23-24 BoundVariable( "a", ), ], - @21-24 Apply( + @28-31 Apply( "", "U64", [], ), ), [ - @27-37 HasClause { - var: @27-28 "a", + @38-55 ImplementsClause { + var: @38-39 "a", abilities: [ - @33-37 Apply( + @51-55 Apply( "", "Hash", [], @@ -55,7 +55,7 @@ Defs( ], value_defs: [], }, - @39-40 SpaceBefore( + @57-58 SpaceBefore( Num( "1", ), diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/ability_single_line.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/ability_single_line.expr.roc index c3d8e53fab..85870f77c6 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/ability_single_line.expr.roc +++ b/crates/compiler/test_syntax/tests/snapshots/pass/ability_single_line.expr.roc @@ -1,3 +1,3 @@ -Hash has hash : a -> U64 | a has Hash +Hash implements hash : a -> U64 where a implements Hash 1 diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/ability_two_in_a_row.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/ability_two_in_a_row.expr.result-ast index cce2f989e2..d4285ec53d 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/ability_two_in_a_row.expr.result-ast +++ b/crates/compiler/test_syntax/tests/snapshots/pass/ability_two_in_a_row.expr.result-ast @@ -5,8 +5,8 @@ Defs( Index(1), ], regions: [ - @0-33, - @35-68, + @0-51, + @53-104, ], space_before: [ Slice(start = 0, length = 0), @@ -26,27 +26,27 @@ Defs( name: @0-3 "Ab1", vars: [], }, - loc_has: @4-7 Has, + loc_implements: @4-14 Implements, members: [ AbilityMember { - name: @8-11 "ab1", - typ: @14-33 Where( - @14-21 Function( + name: @15-18 "ab1", + typ: @21-51 Where( + @21-28 Function( [ - @14-15 BoundVariable( + @21-22 BoundVariable( "a", ), ], - @19-21 Record { + @26-28 Record { fields: [], ext: None, }, ), [ - @24-33 HasClause { - var: @24-25 "a", + @35-51 ImplementsClause { + var: @35-36 "a", abilities: [ - @30-33 Apply( + @48-51 Apply( "", "Ab1", [], @@ -60,30 +60,30 @@ Defs( }, Ability { header: TypeHeader { - name: @35-38 "Ab2", + name: @53-56 "Ab2", vars: [], }, - loc_has: @39-42 Has, + loc_implements: @57-67 Implements, members: [ AbilityMember { - name: @43-46 "ab2", - typ: @49-68 Where( - @49-56 Function( + name: @68-71 "ab2", + typ: @74-104 Where( + @74-81 Function( [ - @49-50 BoundVariable( + @74-75 BoundVariable( "a", ), ], - @54-56 Record { + @79-81 Record { fields: [], ext: None, }, ), [ - @59-68 HasClause { - var: @59-60 "a", + @88-104 ImplementsClause { + var: @88-89 "a", abilities: [ - @65-68 Apply( + @101-104 Apply( "", "Ab2", [], @@ -98,7 +98,7 @@ Defs( ], value_defs: [], }, - @70-71 SpaceBefore( + @106-107 SpaceBefore( Num( "1", ), diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/ability_two_in_a_row.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/ability_two_in_a_row.expr.roc index f747842c70..4f6f9c75e0 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/ability_two_in_a_row.expr.roc +++ b/crates/compiler/test_syntax/tests/snapshots/pass/ability_two_in_a_row.expr.roc @@ -1,5 +1,5 @@ -Ab1 has ab1 : a -> {} | a has Ab1 +Ab1 implements ab1 : a -> {} where a implements Ab1 -Ab2 has ab2 : a -> {} | a has Ab2 +Ab2 implements ab2 : a -> {} where a implements Ab2 1 diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/newline_in_packages.full.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/newline_in_packages.full.formatted.roc index 65594cfd38..cba8a15175 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/newline_in_packages.full.formatted.roc +++ b/crates/compiler/test_syntax/tests/snapshots/pass/newline_in_packages.full.formatted.roc @@ -1,7 +1,7 @@ app "hello" packages { pf: - "https://github.com/roc-lang/basic-cli/releases/download/0.4.0/DI4lqn7LIZs8ZrCDUgLK-tHHpQmxGF1ZrlevRKq5LXk.tar.br", + "https://github.com/roc-lang/basic-cli/releases/download/0.5.0/Cufzl36_SnJ4QbOoEmiJ5dIpUxBvdB3NEySvuH82Wio.tar.br", } imports [pf.Stdout] provides [main] to pf diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/newline_in_packages.full.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/newline_in_packages.full.result-ast index 54d44bb72a..975efca1c3 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/newline_in_packages.full.result-ast +++ b/crates/compiler/test_syntax/tests/snapshots/pass/newline_in_packages.full.result-ast @@ -24,7 +24,7 @@ Full { Newline, ], package_name: @31-145 PackageName( - "https://github.com/roc-lang/basic-cli/releases/download/0.4.0/DI4lqn7LIZs8ZrCDUgLK-tHHpQmxGF1ZrlevRKq5LXk.tar.br", + "https://github.com/roc-lang/basic-cli/releases/download/0.5.0/Cufzl36_SnJ4QbOoEmiJ5dIpUxBvdB3NEySvuH82Wio.tar.br", ), }, [ diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/newline_in_packages.full.roc b/crates/compiler/test_syntax/tests/snapshots/pass/newline_in_packages.full.roc index aebf7bf46a..58dcb520fc 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/newline_in_packages.full.roc +++ b/crates/compiler/test_syntax/tests/snapshots/pass/newline_in_packages.full.roc @@ -1,6 +1,6 @@ app "hello" packages { pf: -"https://github.com/roc-lang/basic-cli/releases/download/0.4.0/DI4lqn7LIZs8ZrCDUgLK-tHHpQmxGF1ZrlevRKq5LXk.tar.br" +"https://github.com/roc-lang/basic-cli/releases/download/0.5.0/Cufzl36_SnJ4QbOoEmiJ5dIpUxBvdB3NEySvuH82Wio.tar.br" } imports [pf.Stdout] provides [main] to pf diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/opaque_has_abilities.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/opaque_has_abilities.expr.formatted.roc index 768b1dab9d..bc1b9655e7 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/opaque_has_abilities.expr.formatted.roc +++ b/crates/compiler/test_syntax/tests/snapshots/pass/opaque_has_abilities.expr.formatted.roc @@ -1,24 +1,24 @@ -A := U8 has [Eq, Hash] +A := U8 implements [Eq, Hash] -A := a | a has Other - has [Eq, Hash] +A := a where a implements Other + implements [Eq, Hash] -A := a | a has Other - has [Eq, Hash] +A := a where a implements Other + implements [Eq, Hash] -A := U8 has [Eq { eq }, Hash { hash }] +A := U8 implements [Eq { eq }, Hash { hash }] -A := U8 has [Eq { eq, eq1 }] +A := U8 implements [Eq { eq, eq1 }] -A := U8 has [Eq { eq, eq1 }, Hash] +A := U8 implements [Eq { eq, eq1 }, Hash] -A := U8 has [Hash, Eq { eq, eq1 }] +A := U8 implements [Hash, Eq { eq, eq1 }] -A := U8 has [] +A := U8 implements [] -A := a | a has Other - has [Eq { eq }, Hash { hash }] +A := a where a implements Other + implements [Eq { eq }, Hash { hash }] -A := U8 has [Eq {}] +A := U8 implements [Eq {}] 0 \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/opaque_has_abilities.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/opaque_has_abilities.expr.result-ast index b9a9bf4520..6426fd40e6 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/opaque_has_abilities.expr.result-ast +++ b/crates/compiler/test_syntax/tests/snapshots/pass/opaque_has_abilities.expr.result-ast @@ -14,15 +14,15 @@ Defs( ], regions: [ @0-7, - @24-44, - @61-81, - @103-110, - @139-146, - @167-174, - @201-208, - @235-242, - @251-271, - @305-312, + @31-62, + @86-117, + @146-153, + @189-196, + @224-231, + @265-272, + @306-313, + @329-360, + @401-408, ], space_before: [ Slice(start = 0, length = 0), @@ -80,18 +80,18 @@ Defs( [], ), derived: Some( - @12-22 Has( + @19-29 Implements( [ - @13-15 HasAbility { - ability: @13-15 Apply( + @20-22 ImplementsAbility { + ability: @20-22 Apply( "", "Eq", [], ), impls: None, }, - @17-21 HasAbility { - ability: @17-21 Apply( + @24-28 ImplementsAbility { + ability: @24-28 Apply( "", "Hash", [], @@ -104,18 +104,18 @@ Defs( }, Opaque { header: TypeHeader { - name: @24-25 "A", + name: @31-32 "A", vars: [], }, - typ: @29-44 Where( - @29-30 BoundVariable( + typ: @36-62 Where( + @36-37 BoundVariable( "a", ), [ - @33-44 HasClause { - var: @33-34 "a", + @44-62 ImplementsClause { + var: @44-45 "a", abilities: [ - @39-44 Apply( + @57-62 Apply( "", "Other", [], @@ -125,18 +125,18 @@ Defs( ], ), derived: Some( - @49-59 Has( + @74-84 Implements( [ - @50-52 HasAbility { - ability: @50-52 Apply( + @75-77 ImplementsAbility { + ability: @75-77 Apply( "", "Eq", [], ), impls: None, }, - @54-58 HasAbility { - ability: @54-58 Apply( + @79-83 ImplementsAbility { + ability: @79-83 Apply( "", "Hash", [], @@ -149,18 +149,18 @@ Defs( }, Opaque { header: TypeHeader { - name: @61-62 "A", + name: @86-87 "A", vars: [], }, - typ: @66-81 Where( - @66-67 BoundVariable( + typ: @91-117 Where( + @91-92 BoundVariable( "a", ), [ - @70-81 HasClause { - var: @70-71 "a", + @99-117 ImplementsClause { + var: @99-100 "a", abilities: [ - @76-81 Apply( + @112-117 Apply( "", "Other", [], @@ -170,19 +170,19 @@ Defs( ], ), derived: Some( - @91-101 SpaceBefore( - Has( + @134-144 SpaceBefore( + Implements( [ - @92-94 HasAbility { - ability: @92-94 Apply( + @135-137 ImplementsAbility { + ability: @135-137 Apply( "", "Eq", [], ), impls: None, }, - @96-100 HasAbility { - ability: @96-100 Apply( + @139-143 ImplementsAbility { + ability: @139-143 Apply( "", "Hash", [], @@ -199,44 +199,44 @@ Defs( }, Opaque { header: TypeHeader { - name: @103-104 "A", + name: @146-147 "A", vars: [], }, - typ: @108-110 Apply( + typ: @151-153 Apply( "", "U8", [], ), derived: Some( - @115-137 Has( + @165-187 Implements( [ - @116-123 HasAbility { - ability: @116-118 Apply( + @166-173 ImplementsAbility { + ability: @166-168 Apply( "", "Eq", [], ), impls: Some( - @119-123 HasImpls( + @169-173 AbilityImpls( [ - @120-122 LabelOnly( - @120-122 "eq", + @170-172 LabelOnly( + @170-172 "eq", ), ], ), ), }, - @125-136 HasAbility { - ability: @125-129 Apply( + @175-186 ImplementsAbility { + ability: @175-179 Apply( "", "Hash", [], ), impls: Some( - @130-136 HasImpls( + @180-186 AbilityImpls( [ - @131-135 LabelOnly( - @131-135 "hash", + @181-185 LabelOnly( + @181-185 "hash", ), ], ), @@ -248,31 +248,31 @@ Defs( }, Opaque { header: TypeHeader { - name: @139-140 "A", + name: @189-190 "A", vars: [], }, - typ: @144-146 Apply( + typ: @194-196 Apply( "", "U8", [], ), derived: Some( - @151-165 Has( + @208-222 Implements( [ - @152-164 HasAbility { - ability: @152-154 Apply( + @209-221 ImplementsAbility { + ability: @209-211 Apply( "", "Eq", [], ), impls: Some( - @155-164 HasImpls( + @212-221 AbilityImpls( [ - @156-158 LabelOnly( - @156-158 "eq", + @213-215 LabelOnly( + @213-215 "eq", ), - @160-163 LabelOnly( - @160-163 "eq1", + @217-220 LabelOnly( + @217-220 "eq1", ), ], ), @@ -284,38 +284,38 @@ Defs( }, Opaque { header: TypeHeader { - name: @167-168 "A", + name: @224-225 "A", vars: [], }, - typ: @172-174 Apply( + typ: @229-231 Apply( "", "U8", [], ), derived: Some( - @179-199 Has( + @243-263 Implements( [ - @180-192 HasAbility { - ability: @180-182 Apply( + @244-256 ImplementsAbility { + ability: @244-246 Apply( "", "Eq", [], ), impls: Some( - @183-192 HasImpls( + @247-256 AbilityImpls( [ - @184-186 LabelOnly( - @184-186 "eq", + @248-250 LabelOnly( + @248-250 "eq", ), - @188-191 LabelOnly( - @188-191 "eq1", + @252-255 LabelOnly( + @252-255 "eq1", ), ], ), ), }, - @194-198 HasAbility { - ability: @194-198 Apply( + @258-262 ImplementsAbility { + ability: @258-262 Apply( "", "Hash", [], @@ -328,39 +328,39 @@ Defs( }, Opaque { header: TypeHeader { - name: @201-202 "A", + name: @265-266 "A", vars: [], }, - typ: @206-208 Apply( + typ: @270-272 Apply( "", "U8", [], ), derived: Some( - @213-233 Has( + @284-304 Implements( [ - @214-218 HasAbility { - ability: @214-218 Apply( + @285-289 ImplementsAbility { + ability: @285-289 Apply( "", "Hash", [], ), impls: None, }, - @220-232 HasAbility { - ability: @220-222 Apply( + @291-303 ImplementsAbility { + ability: @291-293 Apply( "", "Eq", [], ), impls: Some( - @223-232 HasImpls( + @294-303 AbilityImpls( [ - @224-226 LabelOnly( - @224-226 "eq", + @295-297 LabelOnly( + @295-297 "eq", ), - @228-231 LabelOnly( - @228-231 "eq1", + @299-302 LabelOnly( + @299-302 "eq1", ), ], ), @@ -372,34 +372,34 @@ Defs( }, Opaque { header: TypeHeader { - name: @235-236 "A", + name: @306-307 "A", vars: [], }, - typ: @240-242 Apply( + typ: @311-313 Apply( "", "U8", [], ), derived: Some( - @247-249 Has( + @325-327 Implements( [], ), ), }, Opaque { header: TypeHeader { - name: @251-252 "A", + name: @329-330 "A", vars: [], }, - typ: @256-271 Where( - @256-257 BoundVariable( + typ: @334-360 Where( + @334-335 BoundVariable( "a", ), [ - @260-271 HasClause { - var: @260-261 "a", + @342-360 ImplementsClause { + var: @342-343 "a", abilities: [ - @266-271 Apply( + @355-360 Apply( "", "Other", [], @@ -409,36 +409,36 @@ Defs( ], ), derived: Some( - @281-303 SpaceBefore( - Has( + @377-399 SpaceBefore( + Implements( [ - @282-289 HasAbility { - ability: @282-284 Apply( + @378-385 ImplementsAbility { + ability: @378-380 Apply( "", "Eq", [], ), impls: Some( - @285-289 HasImpls( + @381-385 AbilityImpls( [ - @286-288 LabelOnly( - @286-288 "eq", + @382-384 LabelOnly( + @382-384 "eq", ), ], ), ), }, - @291-302 HasAbility { - ability: @291-295 Apply( + @387-398 ImplementsAbility { + ability: @387-391 Apply( "", "Hash", [], ), impls: Some( - @296-302 HasImpls( + @392-398 AbilityImpls( [ - @297-301 LabelOnly( - @297-301 "hash", + @393-397 LabelOnly( + @393-397 "hash", ), ], ), @@ -454,25 +454,25 @@ Defs( }, Opaque { header: TypeHeader { - name: @305-306 "A", + name: @401-402 "A", vars: [], }, - typ: @310-312 Apply( + typ: @406-408 Apply( "", "U8", [], ), derived: Some( - @317-324 Has( + @420-427 Implements( [ - @318-323 HasAbility { - ability: @318-320 Apply( + @421-426 ImplementsAbility { + ability: @421-423 Apply( "", "Eq", [], ), impls: Some( - @321-323 HasImpls( + @424-426 AbilityImpls( [], ), ), @@ -484,7 +484,7 @@ Defs( ], value_defs: [], }, - @326-327 SpaceBefore( + @429-430 SpaceBefore( Num( "0", ), diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/opaque_has_abilities.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/opaque_has_abilities.expr.roc index f8f0fe9e29..0a329cbbdc 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/opaque_has_abilities.expr.roc +++ b/crates/compiler/test_syntax/tests/snapshots/pass/opaque_has_abilities.expr.roc @@ -1,23 +1,23 @@ -A := U8 has [Eq, Hash] +A := U8 implements [Eq, Hash] -A := a | a has Other has [Eq, Hash] +A := a where a implements Other implements [Eq, Hash] -A := a | a has Other - has [Eq, Hash] +A := a where a implements Other + implements [Eq, Hash] -A := U8 has [Eq {eq}, Hash {hash}] +A := U8 implements [Eq {eq}, Hash {hash}] -A := U8 has [Eq {eq, eq1}] +A := U8 implements [Eq {eq, eq1}] -A := U8 has [Eq {eq, eq1}, Hash] +A := U8 implements [Eq {eq, eq1}, Hash] -A := U8 has [Hash, Eq {eq, eq1}] +A := U8 implements [Hash, Eq {eq, eq1}] -A := U8 has [] +A := U8 implements [] -A := a | a has Other - has [Eq {eq}, Hash {hash}] +A := a where a implements Other + implements [Eq {eq}, Hash {hash}] -A := U8 has [Eq {}] +A := U8 implements [Eq {}] 0 diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_function.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_function.expr.result-ast index f06dab0871..02f717dfdf 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_function.expr.result-ast +++ b/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_function.expr.result-ast @@ -4,7 +4,7 @@ Defs( Index(2147483648), ], regions: [ - @0-27, + @0-38, ], space_before: [ Slice(start = 0, length = 0), @@ -19,7 +19,7 @@ Defs( @0-1 Identifier( "f", ), - @4-27 Where( + @4-38 Where( @4-16 Function( [ @4-5 BoundVariable( @@ -38,10 +38,10 @@ Defs( ), ), [ - @20-27 HasClause { - var: @20-21 "a", + @24-38 ImplementsClause { + var: @24-25 "a", abilities: [ - @26-27 Apply( + @37-38 Apply( "", "A", [], @@ -53,7 +53,7 @@ Defs( ), ], }, - @29-30 SpaceBefore( + @40-41 SpaceBefore( Var { module_name: "", ident: "f", diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_function.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_function.expr.roc index ede845156a..8406a9d704 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_function.expr.roc +++ b/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_function.expr.roc @@ -1,3 +1,3 @@ -f : a -> (b -> c) | a has A +f : a -> (b -> c) where a implements A f diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_bound_abilities.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_bound_abilities.expr.formatted.roc index 333e60e19b..15ab48af35 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_bound_abilities.expr.formatted.roc +++ b/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_bound_abilities.expr.formatted.roc @@ -1,5 +1,5 @@ -f : a -> b | a has Hash & Eq, b has Eq & Hash & Display +f : a -> b where a implements Hash & Eq, b implements Eq & Hash & Display -f : a -> b | a has Hash & Eq, b has Hash & Display & Eq +f : a -> b where a implements Hash & Eq, b implements Hash & Display & Eq f \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_bound_abilities.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_bound_abilities.expr.result-ast index c68f1217e9..fd2cc42467 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_bound_abilities.expr.result-ast +++ b/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_bound_abilities.expr.result-ast @@ -5,8 +5,8 @@ Defs( Index(2147483649), ], regions: [ - @0-55, - @57-118, + @0-73, + @75-154, ], space_before: [ Slice(start = 0, length = 0), @@ -26,7 +26,7 @@ Defs( @0-1 Identifier( "f", ), - @4-55 Where( + @4-73 Where( @4-10 Function( [ @4-5 BoundVariable( @@ -38,35 +38,35 @@ Defs( ), ), [ - @13-28 HasClause { - var: @13-14 "a", + @17-39 ImplementsClause { + var: @17-18 "a", abilities: [ - @19-23 Apply( + @30-34 Apply( "", "Hash", [], ), - @26-28 Apply( + @37-39 Apply( "", "Eq", [], ), ], }, - @30-55 HasClause { - var: @30-31 "b", + @41-73 ImplementsClause { + var: @41-42 "b", abilities: [ - @36-38 Apply( + @54-56 Apply( "", "Eq", [], ), - @41-45 Apply( + @59-63 Apply( "", "Hash", [], ), - @48-55 Apply( + @66-73 Apply( "", "Display", [], @@ -77,18 +77,18 @@ Defs( ), ), Annotation( - @57-58 Identifier( + @75-76 Identifier( "f", ), - @61-118 Where( - @61-67 SpaceAfter( + @79-154 Where( + @79-85 SpaceAfter( Function( [ - @61-62 BoundVariable( + @79-80 BoundVariable( "a", ), ], - @66-67 BoundVariable( + @84-85 BoundVariable( "b", ), ), @@ -97,40 +97,40 @@ Defs( ], ), [ - @72-87 HasClause { - var: @72-73 "a", + @94-116 ImplementsClause { + var: @94-95 "a", abilities: [ - @78-82 Apply( + @107-111 Apply( "", "Hash", [], ), - @85-87 Apply( + @114-116 Apply( "", "Eq", [], ), ], }, - @93-118 HasClause { - var: @93-94 SpaceBefore( + @122-154 ImplementsClause { + var: @122-123 SpaceBefore( "b", [ Newline, ], ), abilities: [ - @99-103 Apply( + @135-139 Apply( "", "Hash", [], ), - @106-113 Apply( + @142-149 Apply( "", "Display", [], ), - @116-118 Apply( + @152-154 Apply( "", "Eq", [], @@ -142,7 +142,7 @@ Defs( ), ], }, - @120-121 SpaceBefore( + @156-157 SpaceBefore( Var { module_name: "", ident: "f", diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_bound_abilities.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_bound_abilities.expr.roc index 29f4f89026..c77b4c76e5 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_bound_abilities.expr.roc +++ b/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_bound_abilities.expr.roc @@ -1,7 +1,7 @@ -f : a -> b | a has Hash & Eq, b has Eq & Hash & Display +f : a -> b where a implements Hash & Eq, b implements Eq & Hash & Display f : a -> b - | a has Hash & Eq, - b has Hash & Display & Eq + where a implements Hash & Eq, + b implements Hash & Display & Eq f diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_has.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_has.expr.result-ast index 05f6b2b66d..e252c64ff9 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_has.expr.result-ast +++ b/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_has.expr.result-ast @@ -4,7 +4,7 @@ Defs( Index(2147483648), ], regions: [ - @0-48, + @0-73, ], space_before: [ Slice(start = 0, length = 0), @@ -19,7 +19,7 @@ Defs( @0-1 Identifier( "f", ), - @4-48 Where( + @4-73 Where( @4-16 Function( [ @4-5 BoundVariable( @@ -38,30 +38,30 @@ Defs( ), ), [ - @20-27 HasClause { - var: @20-21 "a", + @24-38 ImplementsClause { + var: @24-25 "a", abilities: [ - @26-27 Apply( + @37-38 Apply( "", "A", [], ), ], }, - @29-37 HasClause { - var: @29-30 "b", + @40-55 ImplementsClause { + var: @40-41 "b", abilities: [ - @35-37 Apply( + @53-55 Apply( "", "Eq", [], ), ], }, - @39-48 HasClause { - var: @39-40 "c", + @57-73 ImplementsClause { + var: @57-58 "c", abilities: [ - @45-48 Apply( + @70-73 Apply( "", "Ord", [], @@ -73,7 +73,7 @@ Defs( ), ], }, - @50-51 SpaceBefore( + @75-76 SpaceBefore( Var { module_name: "", ident: "f", diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_has.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_has.expr.roc index a56e9fb184..8122c5e15b 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_has.expr.roc +++ b/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_has.expr.roc @@ -1,3 +1,3 @@ -f : a -> (b -> c) | a has A, b has Eq, c has Ord +f : a -> (b -> c) where a implements A, b implements Eq, c implements Ord f diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_has_across_newlines.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_has_across_newlines.expr.formatted.roc index 8ca6701ffc..9076cc336a 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_has_across_newlines.expr.formatted.roc +++ b/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_has_across_newlines.expr.formatted.roc @@ -1,3 +1,3 @@ -f : a -> (b -> c) | a has Hash, b has Eq, c has Ord +f : a -> (b -> c) where a implements Hash, b implements Eq, c implements Ord f \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_has_across_newlines.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_has_across_newlines.expr.result-ast index 8ea27a6af7..d29d1e2569 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_has_across_newlines.expr.result-ast +++ b/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_has_across_newlines.expr.result-ast @@ -4,7 +4,7 @@ Defs( Index(2147483648), ], regions: [ - @0-67, + @0-92, ], space_before: [ Slice(start = 0, length = 0), @@ -19,7 +19,7 @@ Defs( @0-1 Identifier( "f", ), - @4-67 Where( + @4-92 Where( @4-16 SpaceAfter( Function( [ @@ -43,40 +43,40 @@ Defs( ], ), [ - @24-34 HasClause { - var: @24-25 "a", + @28-45 ImplementsClause { + var: @28-29 "a", abilities: [ - @30-34 Apply( + @41-45 Apply( "", "Hash", [], ), ], }, - @42-50 HasClause { - var: @42-43 SpaceBefore( + @53-68 ImplementsClause { + var: @53-54 SpaceBefore( "b", [ Newline, ], ), abilities: [ - @48-50 Apply( + @66-68 Apply( "", "Eq", [], ), ], }, - @58-67 HasClause { - var: @58-59 SpaceBefore( + @76-92 ImplementsClause { + var: @76-77 SpaceBefore( "c", [ Newline, ], ), abilities: [ - @64-67 Apply( + @89-92 Apply( "", "Ord", [], @@ -88,7 +88,7 @@ Defs( ), ], }, - @69-70 SpaceBefore( + @94-95 SpaceBefore( Var { module_name: "", ident: "f", diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_has_across_newlines.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_has_across_newlines.expr.roc index a5e89f075f..8a999d8baa 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_has_across_newlines.expr.roc +++ b/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_multiple_has_across_newlines.expr.roc @@ -1,6 +1,6 @@ f : a -> (b -> c) - | a has Hash, - b has Eq, - c has Ord + where a implements Hash, + b implements Eq, + c implements Ord f diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_non_function.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_non_function.expr.result-ast index 862b258bf8..30486cee67 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_non_function.expr.result-ast +++ b/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_non_function.expr.result-ast @@ -4,7 +4,7 @@ Defs( Index(2147483648), ], regions: [ - @0-15, + @0-26, ], space_before: [ Slice(start = 0, length = 0), @@ -19,15 +19,15 @@ Defs( @0-1 Identifier( "f", ), - @4-15 Where( + @4-26 Where( @4-5 BoundVariable( "a", ), [ - @8-15 HasClause { - var: @8-9 "a", + @12-26 ImplementsClause { + var: @12-13 "a", abilities: [ - @14-15 Apply( + @25-26 Apply( "", "A", [], @@ -39,7 +39,7 @@ Defs( ), ], }, - @17-18 SpaceBefore( + @28-29 SpaceBefore( Var { module_name: "", ident: "f", diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_non_function.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_non_function.expr.roc index eb3374f992..6fdaa51b78 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_non_function.expr.roc +++ b/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_non_function.expr.roc @@ -1,3 +1,3 @@ -f : a | a has A +f : a where a implements A f diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_on_newline.expr.formatted.roc b/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_on_newline.expr.formatted.roc index fb742eac39..1b14b8c6b4 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_on_newline.expr.formatted.roc +++ b/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_on_newline.expr.formatted.roc @@ -1,3 +1,3 @@ -f : a -> U64 | a has Hash +f : a -> U64 where a implements Hash f \ No newline at end of file diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_on_newline.expr.result-ast b/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_on_newline.expr.result-ast index ad552875ed..ca97aea704 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_on_newline.expr.result-ast +++ b/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_on_newline.expr.result-ast @@ -4,7 +4,7 @@ Defs( Index(2147483648), ], regions: [ - @0-29, + @0-40, ], space_before: [ Slice(start = 0, length = 0), @@ -19,7 +19,7 @@ Defs( @0-1 Identifier( "f", ), - @4-29 Where( + @4-40 Where( @4-12 SpaceAfter( Function( [ @@ -38,10 +38,10 @@ Defs( ], ), [ - @19-29 HasClause { - var: @19-20 "a", + @23-40 ImplementsClause { + var: @23-24 "a", abilities: [ - @25-29 Apply( + @36-40 Apply( "", "Hash", [], @@ -53,7 +53,7 @@ Defs( ), ], }, - @31-32 SpaceBefore( + @42-43 SpaceBefore( Var { module_name: "", ident: "f", diff --git a/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_on_newline.expr.roc b/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_on_newline.expr.roc index 7f29c770d3..c147869078 100644 --- a/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_on_newline.expr.roc +++ b/crates/compiler/test_syntax/tests/snapshots/pass/where_clause_on_newline.expr.roc @@ -1,4 +1,4 @@ f : a -> U64 - | a has Hash + where a implements Hash f diff --git a/crates/compiler/test_syntax/tests/test_fmt.rs b/crates/compiler/test_syntax/tests/test_fmt.rs index 847832782f..f824a22065 100644 --- a/crates/compiler/test_syntax/tests/test_fmt.rs +++ b/crates/compiler/test_syntax/tests/test_fmt.rs @@ -1979,11 +1979,11 @@ mod test_fmt { expr_formats_to( indoc!( r#" - succeed { + succeed { a: <- get "a" |> map (\x -> x * 2) - |> batch, + |> batch, b: <- get "b" |> batch, - c: items + c: items |> List.map \x -> x * 2 } "# @@ -2032,7 +2032,7 @@ mod test_fmt { indoc!( r#" succeed { a: <- get "a" |> batch, - b: <- get "b" |> batch, + b: <- get "b" |> batch, } "# ), @@ -2049,10 +2049,10 @@ mod test_fmt { expr_formats_to( indoc!( r#" - succeed - { + succeed + { a: <- get "a" |> batch, - b: <- get "b" |> batch, + b: <- get "b" |> batch, } "# ), @@ -2072,7 +2072,7 @@ mod test_fmt { expr_formats_to( indoc!( r#" - succeed { a: <- get "a" } + succeed { a: <- get "a" } { b: <- get "b" } "# ), @@ -5421,10 +5421,10 @@ mod test_fmt { } #[test] - fn opaque_has_clause() { + fn opaque_implements_clause() { expr_formats_same(indoc!( r#" - A := U8 has [Eq, Hash] + A := U8 implements [Eq, Hash] 0 "# @@ -5435,7 +5435,7 @@ mod test_fmt { r#" A := U8 - has [Eq, Hash] + implements [Eq, Hash] 0 "# @@ -5443,7 +5443,7 @@ mod test_fmt { indoc!( r#" A := U8 - has [Eq, Hash] + implements [Eq, Hash] 0 "# @@ -5453,15 +5453,15 @@ mod test_fmt { expr_formats_to( indoc!( r#" - A := a | a has Hash has [ Eq, Hash ] + A := a where a implements Hash implements [ Eq, Hash ] 0 "# ), indoc!( r#" - A := a | a has Hash - has [Eq, Hash] + A := a where a implements Hash + implements [Eq, Hash] 0 "# @@ -5471,14 +5471,14 @@ mod test_fmt { expr_formats_to( indoc!( r#" - A := U8 has [] + A := U8 implements [] 0 "# ), indoc!( r#" - A := U8 has [] + A := U8 implements [] 0 "# @@ -5518,10 +5518,10 @@ mod test_fmt { } #[test] - fn opaque_has_with_impls() { + fn opaque_implements_with_impls() { expr_formats_same(indoc!( r#" - A := U8 has [Eq { eq }, Hash { hash }] + A := U8 implements [Eq { eq }, Hash { hash }] 0 "# @@ -5529,7 +5529,7 @@ mod test_fmt { expr_formats_same(indoc!( r#" - A := U8 has [Eq { eq, eq1 }] + A := U8 implements [Eq { eq, eq1 }] 0 "# @@ -5538,8 +5538,8 @@ mod test_fmt { expr_formats_to( indoc!( r#" - A := U8 has [Eq { eq, eq1 }] - A := U8 has [Eq { + A := U8 implements [Eq { eq, eq1 }] + A := U8 implements [Eq { eq, eq1 }] @@ -5549,8 +5549,8 @@ mod test_fmt { ), indoc!( r#" - A := U8 has [Eq { eq, eq1 }] - A := U8 has [ + A := U8 implements [Eq { eq, eq1 }] + A := U8 implements [ Eq { eq, eq1, @@ -5564,8 +5564,8 @@ mod test_fmt { expr_formats_same(indoc!( r#" - A := a | a has Other - has [Eq { eq }, Hash { hash }] + A := a where a implements Other + implements [Eq { eq }, Hash { hash }] 0 "# @@ -5573,7 +5573,7 @@ mod test_fmt { expr_formats_same(indoc!( r#" - A := U8 has [Eq {}] + A := U8 implements [Eq {}] 0 "# @@ -5621,7 +5621,7 @@ mod test_fmt { dataIndices : List Nat, data : List (T k v), size : Nat, - } | k has Hash & Eq + } where k implements Hash & Eq a "# @@ -5833,12 +5833,12 @@ mod test_fmt { r#" interface Foo exposes [] imports [] - A has + A implements ## This is member ab - ab : a -> a | a has A + ab : a -> a where a implements A ## This is member de - de : a -> a | a has A + de : a -> a where a implements A f = g "# @@ -5880,7 +5880,7 @@ mod test_fmt { fn clauses_with_multiple_abilities() { expr_formats_same(indoc!( r#" - f : {} -> a | a has Eq & Hash & Decode + f : {} -> a where a implements Eq & Hash & Decode f "# @@ -5889,8 +5889,8 @@ mod test_fmt { expr_formats_to( indoc!( r#" - f : {} -> a | a has Eq & Hash & Decode, - b has Eq & Hash + f : {} -> a where a implements Eq & Hash & Decode, + b implements Eq & Hash f "# @@ -5898,10 +5898,10 @@ mod test_fmt { indoc!( // TODO: ideally, this would look a bit nicer - consider // f : {} -> a - // | a has Eq & Hash & Decode, - // b has Eq & Hash + // where a implements Eq & Hash & Decode, + // b implements Eq & Hash r#" - f : {} -> a | a has Eq & Hash & Decode, b has Eq & Hash + f : {} -> a where a implements Eq & Hash & Decode, b implements Eq & Hash f "# diff --git a/crates/compiler/types/Cargo.toml b/crates/compiler/types/Cargo.toml index bb727200ea..535490107e 100644 --- a/crates/compiler/types/Cargo.toml +++ b/crates/compiler/types/Cargo.toml @@ -14,6 +14,7 @@ roc_error_macros = { path = "../../error_macros" } roc_module = { path = "../module" } roc_region = { path = "../region" } roc_serialize = { path = "../serialize" } +roc_parse = { path = "../parse" } ven_pretty = { path = "../../vendor/pretty" } diff --git a/crates/compiler/types/src/pretty_print.rs b/crates/compiler/types/src/pretty_print.rs index 350e4bcfd2..1fba3b82bd 100644 --- a/crates/compiler/types/src/pretty_print.rs +++ b/crates/compiler/types/src/pretty_print.rs @@ -136,8 +136,8 @@ fn find_names_needed( if !root_appearances.contains_key(&root) { roots.push(root); } - // Able vars are always printed at least twice (in the signature, and in the "has" - // clause set). + // Able vars are always printed at least twice (in the signature, and in the + // "implements" clause set). root_appearances.insert(root, Appearances::Multiple); } RecursionVar { @@ -606,9 +606,16 @@ fn variable_to_string( ctx.able_variables.sort(); ctx.able_variables.dedup(); for (i, (var, abilities)) in ctx.able_variables.into_iter().enumerate() { - buf.push_str(if i == 0 { " | " } else { ", " }); + if i == 0 { + buf.push(' '); + buf.push_str(roc_parse::keyword::WHERE) + } else { + buf.push(','); + } + buf.push(' '); buf.push_str(var); - buf.push_str(" has"); + buf.push(' '); + buf.push_str(roc_parse::keyword::IMPLEMENTS); for (i, ability) in abilities.into_sorted_iter().enumerate() { if i > 0 { buf.push_str(" &"); diff --git a/crates/compiler/types/src/subs.rs b/crates/compiler/types/src/subs.rs index cef1fcbff2..e4fdb9cb70 100644 --- a/crates/compiler/types/src/subs.rs +++ b/crates/compiler/types/src/subs.rs @@ -2381,7 +2381,7 @@ pub enum Content { /// This can only happen when unified with a [Self::RigidAbleVar]. FlexAbleVar(Option>, SubsSlice), /// Like a [Self::RigidVar], but is also bound to 1+ abilities. - /// For example, "a has Hash". + /// For example, "a implements Hash". RigidAbleVar(SubsIndex, SubsSlice), /// name given to a recursion variable RecursionVar { diff --git a/crates/compiler/types/src/types.rs b/crates/compiler/types/src/types.rs index f01837bbd6..39b6349da3 100644 --- a/crates/compiler/types/src/types.rs +++ b/crates/compiler/types/src/types.rs @@ -398,11 +398,6 @@ pub enum TypeTag { shared: Index, actual: Index, }, - HostExposedAlias { - shared: Index, - actual_type: Index, - actual_variable: Variable, - }, Apply { symbol: Symbol, @@ -998,41 +993,6 @@ impl Types { self.set_type_tag(index, tag, type_arguments_slice) } - Type::HostExposedAlias { - name, - type_arguments, - lambda_set_variables, - actual_var, - actual, - } => { - let type_arguments_slice = self.from_old_type_slice(type_arguments.iter()); - - let lambda_set_slice = { - let slice = self.reserve_type_tags(lambda_set_variables.len()); - - for (index, argument) in slice.into_iter().zip(lambda_set_variables) { - self.from_old_type_at(index, &argument.0); - } - - Slice::new(slice.start() as _, slice.len() as _) - }; - - let alias_shared = AliasShared { - symbol: *name, - type_argument_abilities: Slice::default(), - type_argument_regions: Slice::default(), - lambda_set_variables: lambda_set_slice, - infer_ext_in_output_variables: Slice::default(), - }; - - let tag = TypeTag::HostExposedAlias { - shared: Index::push_new(&mut self.aliases, alias_shared), - actual_type: self.from_old_type(actual), - actual_variable: *actual_var, - }; - - self.set_type_tag(index, tag, type_arguments_slice) - } Type::Variable(var) => { self.set_type_tag(index, TypeTag::Variable(*var), Slice::default()) } @@ -1217,27 +1177,6 @@ impl Types { new_type_arguments, ) } - HostExposedAlias { - shared, - actual_type, - actual_variable, - } => { - let type_arguments = self.get_type_arguments(typ); - - let new_type_arguments = defer_slice!(type_arguments); - let new_shared = do_shared!(shared); - let new_actual_type = defer!(actual_type); - let new_actual_variable = subst!(actual_variable); - - ( - HostExposedAlias { - shared: new_shared, - actual_type: new_actual_type, - actual_variable: new_actual_variable, - }, - new_type_arguments, - ) - } Apply { symbol, type_argument_regions, @@ -1432,12 +1371,7 @@ mod debug_types { maybe_paren!(Free, p, alias(types, f, tag, shared)) } TypeTag::StructuralAlias { shared, actual } - | TypeTag::OpaqueAlias { shared, actual } - | TypeTag::HostExposedAlias { - shared, - actual_type: actual, - actual_variable: _, - } => maybe_paren!( + | TypeTag::OpaqueAlias { shared, actual } => maybe_paren!( Free, p, alias(types, f, tag, shared) @@ -1743,13 +1677,6 @@ pub enum Type { actual: Box, kind: AliasKind, }, - HostExposedAlias { - name: Symbol, - type_arguments: Vec, - lambda_set_variables: Vec, - actual_var: Variable, - actual: Box, - }, RecursiveTagUnion(Variable, Vec<(TagName, Vec)>, TypeExtension), /// Applying a type to some arguments (e.g. Dict.Dict String Int) Apply(Symbol, Vec>, Region), @@ -1760,7 +1687,7 @@ pub enum Type { } /// A lambda set under an arrow in a ability member signature. For example, in -/// Default has default : {} -> a | a has Default +/// Default has default : {} -> a where a implements Default /// the unspecialized lambda set for the arrow "{} -> a" would be `a:default:1`. /// /// Lambda sets in member signatures are never known until those members are specialized at a @@ -1836,19 +1763,6 @@ impl Clone for Type { actual: actual.clone(), kind: *kind, }, - Self::HostExposedAlias { - name, - type_arguments, - lambda_set_variables, - actual_var, - actual, - } => Self::HostExposedAlias { - name: *name, - type_arguments: type_arguments.clone(), - lambda_set_variables: lambda_set_variables.clone(), - actual_var: *actual_var, - actual: actual.clone(), - }, Self::RecursiveTagUnion(arg0, arg1, arg2) => { Self::RecursiveTagUnion(*arg0, arg1.clone(), arg2.clone()) } @@ -2054,22 +1968,6 @@ impl fmt::Debug for Type { Ok(()) } - Type::HostExposedAlias { - name, - type_arguments: arguments, - .. - } => { - write!(f, "HostExposedAlias {name:?}")?; - - for arg in arguments { - write!(f, " {arg:?}")?; - } - - // Sometimes it's useful to see the expansion of the alias - // write!(f, "[ but actually {:?} ]", _actual)?; - - Ok(()) - } Type::Record(fields, ext) => { write!(f, "{{")?; @@ -2384,22 +2282,6 @@ impl Type { stack.push(actual); } - HostExposedAlias { - type_arguments, - lambda_set_variables, - actual: actual_type, - .. - } => { - for value in type_arguments.iter_mut() { - stack.push(value); - } - - for lambda_set in lambda_set_variables.iter_mut() { - stack.push(lambda_set.as_inner_mut()); - } - - stack.push(actual_type); - } Apply(_, args, _) => { stack.extend(args.iter_mut().map(|t| &mut t.value)); } @@ -2522,22 +2404,6 @@ impl Type { stack.push(actual); } - HostExposedAlias { - type_arguments, - lambda_set_variables, - actual: actual_type, - .. - } => { - for value in type_arguments.iter_mut() { - stack.push(value); - } - - for lambda_set in lambda_set_variables.iter_mut() { - stack.push(lambda_set.as_inner_mut()); - } - - stack.push(actual_type); - } Apply(_, args, _) => { stack.extend(args.iter_mut().map(|t| &mut t.value)); } @@ -2640,10 +2506,6 @@ impl Type { } alias_actual.substitute_alias(rep_symbol, rep_args, actual) } - HostExposedAlias { - actual: actual_type, - .. - } => actual_type.substitute_alias(rep_symbol, rep_args, actual), Apply(symbol, args, region) if *symbol == rep_symbol => { if args.len() == rep_args.len() && args @@ -2727,9 +2589,6 @@ impl Type { actual: actual_type, .. } => alias_symbol == &rep_symbol || actual_type.contains_symbol(rep_symbol), - HostExposedAlias { name, actual, .. } => { - name == &rep_symbol || actual.contains_symbol(rep_symbol) - } Apply(symbol, _, _) if *symbol == rep_symbol => true, Apply(_, args, _) => args.iter().any(|arg| arg.value.contains_symbol(rep_symbol)), RangedNumber(_) => false, @@ -2793,7 +2652,6 @@ impl Type { actual: actual_type, .. } => actual_type.contains_variable(rep_variable), - HostExposedAlias { actual, .. } => actual.contains_variable(rep_variable), Apply(_, args, _) => args .iter() .any(|arg| arg.value.contains_variable(rep_variable)), @@ -2996,22 +2854,6 @@ fn instantiate_aliases<'a, F>( .iter_mut() .for_each(|t| instantiate_aliases(&mut t.value.typ, region, aliases, ctx)); } - HostExposedAlias { - type_arguments: type_args, - lambda_set_variables, - actual: actual_type, - .. - } => { - for arg in type_args { - instantiate_aliases(arg, region, aliases, ctx); - } - - for arg in lambda_set_variables { - arg.instantiate_aliases(region, aliases, ctx); - } - - instantiate_aliases(&mut *actual_type, region, aliases, ctx); - } Alias { type_arguments: type_args, lambda_set_variables, @@ -3170,12 +3012,6 @@ fn symbols_help(initial: &Type) -> Vec { output.push(*alias_symbol); stack.push(actual_type); } - HostExposedAlias { name, actual, .. } => { - // because the type parameters are inlined in the actual type, we don't need to look - // at the type parameters here - output.push(*name); - stack.push(actual); - } Apply(symbol, args, _) => { output.push(*symbol); stack.extend(args.iter().map(|t| &t.value)); @@ -3301,16 +3137,6 @@ fn variables_help(tipe: &Type, accum: &mut ImSet) { } variables_help(actual, accum); } - HostExposedAlias { - type_arguments: arguments, - actual, - .. - } => { - for arg in arguments { - variables_help(arg, accum); - } - variables_help(actual, accum); - } RangedNumber(_) => {} Apply(_, args, _) => { for x in args { @@ -3453,16 +3279,6 @@ fn variables_help_detailed(tipe: &Type, accum: &mut VariableDetail) { } variables_help_detailed(actual, accum); } - HostExposedAlias { - type_arguments: arguments, - actual, - .. - } => { - for arg in arguments { - variables_help_detailed(arg, accum); - } - variables_help_detailed(actual, accum); - } RangedNumber(_) => {} Apply(_, args, _) => { for x in args { @@ -4003,7 +3819,7 @@ fn write_debug_error_type_help(error_type: ErrorType, buf: &mut String, parens: buf.push('('); } buf.push_str(name.as_str()); - write!(buf, "has {symbol:?}").unwrap(); + write!(buf, "{} {:?}", roc_parse::keyword::IMPLEMENTS, symbol).unwrap(); if write_parens { buf.push(')'); } @@ -4653,20 +4469,6 @@ fn instantiate_lambda_sets_as_unspecialized( stack.push(actual); stack.extend(type_arguments.iter_mut().rev().map(|t| &mut t.typ)); } - Type::HostExposedAlias { - name: _, - type_arguments, - lambda_set_variables, - actual_var: _, - actual, - } => { - for lambda_set in lambda_set_variables.iter_mut() { - debug_assert!(matches!(lambda_set.0, Type::Variable(_))); - lambda_set.0 = new_uls(); - } - stack.push(actual); - stack.extend(type_arguments.iter_mut().rev()); - } Type::Apply(_sym, args, _region) => { stack.extend(args.iter_mut().rev().map(|t| &mut t.value)); } diff --git a/crates/compiler/uitest/tests/ability/bounds/expand_able_variables_in_type_alias.txt b/crates/compiler/uitest/tests/ability/bounds/expand_able_variables_in_type_alias.txt index 8efd15d88d..894ded1fa3 100644 --- a/crates/compiler/uitest/tests/ability/bounds/expand_able_variables_in_type_alias.txt +++ b/crates/compiler/uitest/tests/ability/bounds/expand_able_variables_in_type_alias.txt @@ -1,7 +1,7 @@ # +opt infer:print_only_under_alias app "test" provides [main] to "./platform" -F a : a | a has Hash +F a : a where a implements Hash main : F a -> F a -#^^^^{-1} a -[[main(0)]]-> a | a has Hash +#^^^^{-1} a -[[main(0)]]-> a where a implements Hash diff --git a/crates/compiler/uitest/tests/ability/bounds/multiple_variables_bound_to_an_ability_from_type_def.txt b/crates/compiler/uitest/tests/ability/bounds/multiple_variables_bound_to_an_ability_from_type_def.txt index 5379b86d50..32f23d7db0 100644 --- a/crates/compiler/uitest/tests/ability/bounds/multiple_variables_bound_to_an_ability_from_type_def.txt +++ b/crates/compiler/uitest/tests/ability/bounds/multiple_variables_bound_to_an_ability_from_type_def.txt @@ -1,7 +1,7 @@ # +opt infer:print_only_under_alias app "test" provides [main] to "./platform" -F a : a | a has Hash & Eq & Decoding +F a : a where a implements Hash & Eq & Decoding main : F a -> F a -#^^^^{-1} a -[[main(0)]]-> a | a has Hash & Decoding & Eq +#^^^^{-1} a -[[main(0)]]-> a where a implements Hash & Decoding & Eq diff --git a/crates/compiler/uitest/tests/ability/bounds/rigid_able_bounds_are_superset_of_flex_bounds_admitted.txt b/crates/compiler/uitest/tests/ability/bounds/rigid_able_bounds_are_superset_of_flex_bounds_admitted.txt index f262ca2265..490c265512 100644 --- a/crates/compiler/uitest/tests/ability/bounds/rigid_able_bounds_are_superset_of_flex_bounds_admitted.txt +++ b/crates/compiler/uitest/tests/ability/bounds/rigid_able_bounds_are_superset_of_flex_bounds_admitted.txt @@ -1,8 +1,8 @@ app "test" provides [main] to "./platform" -f : x -> x | x has Hash -g : x -> x | x has Decoding & Encoding +f : x -> x where x implements Hash +g : x -> x where x implements Decoding & Encoding -main : x -> x | x has Hash & Decoding & Encoding +main : x -> x where x implements Hash & Decoding & Encoding main = \x -> x |> f |> g -#^^^^{-1} x -[[main(0)]]-> x | x has Hash & Encoding & Decoding +#^^^^{-1} x -[[main(0)]]-> x where x implements Hash & Encoding & Decoding diff --git a/crates/compiler/uitest/tests/ability/generalize_inferred_opaque_variable_bound_to_ability_issue_4408.txt b/crates/compiler/uitest/tests/ability/generalize_inferred_opaque_variable_bound_to_ability_issue_4408.txt index da1662ffa2..4bb2874aa7 100644 --- a/crates/compiler/uitest/tests/ability/generalize_inferred_opaque_variable_bound_to_ability_issue_4408.txt +++ b/crates/compiler/uitest/tests/ability/generalize_inferred_opaque_variable_bound_to_ability_issue_4408.txt @@ -1,6 +1,6 @@ app "test" provides [top] to "./platform" -MDict u := (List u) | u has Hash & Eq +MDict u := (List u) where u implements Hash & Eq bot : MDict k -> MDict k bot = \@MDict data -> @@ -9,4 +9,4 @@ bot = \@MDict data -> top : MDict v -> MDict v top = \x -> bot x -#^^^{-1} MDict v -[[top(0)]]-> MDict v | v has Hash & Eq +#^^^{-1} MDict v -[[top(0)]]-> MDict v where v implements Hash & Eq diff --git a/crates/compiler/uitest/tests/ability/impl_ability_for_opaque_with_lambda_sets.txt b/crates/compiler/uitest/tests/ability/impl_ability_for_opaque_with_lambda_sets.txt index 57d44ca289..3198cd1bf3 100644 --- a/crates/compiler/uitest/tests/ability/impl_ability_for_opaque_with_lambda_sets.txt +++ b/crates/compiler/uitest/tests/ability/impl_ability_for_opaque_with_lambda_sets.txt @@ -1,6 +1,6 @@ app "test" provides [isEqQ] to "./platform" -Q := [ F (Str -> Str), G ] has [Eq { isEq: isEqQ }] +Q := [ F (Str -> Str), G ] implements [Eq { isEq: isEqQ }] isEqQ = \@Q q1, @Q q2 -> when T q1 q2 is #^^^^^{-1} Q, Q -[[isEqQ(0)]]-> Bool diff --git a/crates/compiler/uitest/tests/ability/impl_ability_for_opaque_with_lambda_sets_material.txt b/crates/compiler/uitest/tests/ability/impl_ability_for_opaque_with_lambda_sets_material.txt index a0a9335f0b..b47c5af154 100644 --- a/crates/compiler/uitest/tests/ability/impl_ability_for_opaque_with_lambda_sets_material.txt +++ b/crates/compiler/uitest/tests/ability/impl_ability_for_opaque_with_lambda_sets_material.txt @@ -1,7 +1,7 @@ # +opt infer:print_only_under_alias app "test" provides [main] to "./platform" -Q := ({} -> Str) has [Eq {isEq: isEqQ}] +Q := ({} -> Str) implements [Eq {isEq: isEqQ}] isEqQ = \@Q f1, @Q f2 -> (f1 {} == f2 {}) #^^^^^{-1} ({} -[[]]-> Str), ({} -[[]]-> Str) -[[isEqQ(2)]]-> [False, True] diff --git a/crates/compiler/uitest/tests/ability/smoke/decoder.txt b/crates/compiler/uitest/tests/ability/smoke/decoder.txt index de7b54136f..085d98c493 100644 --- a/crates/compiler/uitest/tests/ability/smoke/decoder.txt +++ b/crates/compiler/uitest/tests/ability/smoke/decoder.txt @@ -2,19 +2,19 @@ app "test" provides [myU8] to "./platform" MDecodeError : [TooShort, Leftover (List U8)] -MDecoder val fmt := List U8, fmt -> { result: Result val MDecodeError, rest: List U8 } | fmt has MDecoderFormatting +MDecoder val fmt := List U8, fmt -> { result: Result val MDecodeError, rest: List U8 } where fmt implements MDecoderFormatting -MDecoding has - decoder : MDecoder val fmt | val has MDecoding, fmt has MDecoderFormatting +MDecoding implements + decoder : MDecoder val fmt where val implements MDecoding, fmt implements MDecoderFormatting -MDecoderFormatting has - u8 : MDecoder U8 fmt | fmt has MDecoderFormatting +MDecoderFormatting implements + u8 : MDecoder U8 fmt where fmt implements MDecoderFormatting -decodeWith : List U8, MDecoder val fmt, fmt -> { result: Result val MDecodeError, rest: List U8 } | fmt has MDecoderFormatting +decodeWith : List U8, MDecoder val fmt, fmt -> { result: Result val MDecodeError, rest: List U8 } where fmt implements MDecoderFormatting decodeWith = \lst, (@MDecoder doDecode), fmt -> doDecode lst fmt fromBytes : List U8, fmt -> Result val MDecodeError - | fmt has MDecoderFormatting, val has MDecoding + where fmt implements MDecoderFormatting, val implements MDecoding fromBytes = \lst, fmt -> when decodeWith lst decoder fmt is { result, rest } -> @@ -23,7 +23,7 @@ fromBytes = \lst, fmt -> Err e -> Err e -Linear := {} has [MDecoderFormatting {u8}] +Linear := {} implements [MDecoderFormatting {u8}] u8 = @MDecoder \lst, @Linear {} -> #^^{-1} Linear#u8(11): MDecoder U8 Linear @@ -31,10 +31,10 @@ u8 = @MDecoder \lst, @Linear {} -> Ok n -> { result: Ok n, rest: List.dropFirst lst } Err _ -> { result: Err TooShort, rest: [] } -MyU8 := U8 has [MDecoding {decoder}] +MyU8 := U8 implements [MDecoding {decoder}] decoder = @MDecoder \lst, fmt -> -#^^^^^^^{-1} MyU8#decoder(12): MDecoder MyU8 fmt | fmt has MDecoderFormatting +#^^^^^^^{-1} MyU8#decoder(12): MDecoder MyU8 fmt where fmt implements MDecoderFormatting when decodeWith lst u8 fmt is { result, rest } -> { result: Result.map result (\n -> @MyU8 n), rest } diff --git a/crates/compiler/uitest/tests/ability/smoke/encoder.txt b/crates/compiler/uitest/tests/ability/smoke/encoder.txt index 57c37aef4c..12f639bf02 100644 --- a/crates/compiler/uitest/tests/ability/smoke/encoder.txt +++ b/crates/compiler/uitest/tests/ability/smoke/encoder.txt @@ -1,29 +1,29 @@ app "test" provides [myU8Bytes] to "./platform" -MEncoder fmt := List U8, fmt -> List U8 | fmt has Format +MEncoder fmt := List U8, fmt -> List U8 where fmt implements Format -MEncoding has - toEncoder : val -> MEncoder fmt | val has MEncoding, fmt has Format +MEncoding implements + toEncoder : val -> MEncoder fmt where val implements MEncoding, fmt implements Format -Format has - u8 : U8 -> MEncoder fmt | fmt has Format +Format implements + u8 : U8 -> MEncoder fmt where fmt implements Format -appendWith : List U8, MEncoder fmt, fmt -> List U8 | fmt has Format +appendWith : List U8, MEncoder fmt, fmt -> List U8 where fmt implements Format appendWith = \lst, (@MEncoder doFormat), fmt -> doFormat lst fmt -toBytes : val, fmt -> List U8 | val has MEncoding, fmt has Format +toBytes : val, fmt -> List U8 where val implements MEncoding, fmt implements Format toBytes = \val, fmt -> appendWith [] (toEncoder val) fmt -Linear := {} has [Format {u8}] +Linear := {} implements [Format {u8}] u8 = \n -> @MEncoder (\lst, @Linear {} -> List.append lst n) #^^{-1} Linear#u8(10): U8 -[[u8(10)]]-> MEncoder Linear -MyU8 := U8 has [MEncoding {toEncoder}] +MyU8 := U8 implements [MEncoding {toEncoder}] toEncoder = \@MyU8 n -> u8 n -#^^^^^^^^^{-1} MyU8#toEncoder(11): MyU8 -[[toEncoder(11)]]-> MEncoder fmt | fmt has Format +#^^^^^^^^^{-1} MyU8#toEncoder(11): MyU8 -[[toEncoder(11)]]-> MEncoder fmt where fmt implements Format myU8Bytes = toBytes (@MyU8 15) (@Linear {}) #^^^^^^^^^{-1} List U8 diff --git a/crates/compiler/uitest/tests/ability/specialize/bool_decoder.txt b/crates/compiler/uitest/tests/ability/specialize/bool_decoder.txt index ac21c79e7a..0d66b5f47a 100644 --- a/crates/compiler/uitest/tests/ability/specialize/bool_decoder.txt +++ b/crates/compiler/uitest/tests/ability/specialize/bool_decoder.txt @@ -3,4 +3,4 @@ app "test" provides [main] to "./platform" main : Decoder Bool _ main = Decode.custom \bytes, fmt -> Decode.decodeWith bytes Decode.decoder fmt - # ^^^^^^^^^^^^^^ Decoding#Decode.decoder(4): Decoder Bool fmt | fmt has DecoderFormatting + # ^^^^^^^^^^^^^^ Decoding#Decode.decoder(4): Decoder Bool fmt where fmt implements DecoderFormatting diff --git a/crates/compiler/uitest/tests/ability/specialize/bool_hash.txt b/crates/compiler/uitest/tests/ability/specialize/bool_hash.txt index 2c03583a11..00a42f8a7e 100644 --- a/crates/compiler/uitest/tests/ability/specialize/bool_hash.txt +++ b/crates/compiler/uitest/tests/ability/specialize/bool_hash.txt @@ -2,4 +2,4 @@ app "test" provides [main] to "./platform" main = \h -> Hash.hash h Bool.true - # ^^^^^^^^^ Hash#Hash.hash(1): a, Bool -[[Hash.hashBool(9)]]-> a | a has Hasher + # ^^^^^^^^^ Hash#Hash.hash(1): a, Bool -[[Hash.hashBool(9)]]-> a where a implements Hasher diff --git a/crates/compiler/uitest/tests/ability/specialize/bool_to_encoder.txt b/crates/compiler/uitest/tests/ability/specialize/bool_to_encoder.txt index b08a6a8325..72fd873b89 100644 --- a/crates/compiler/uitest/tests/ability/specialize/bool_to_encoder.txt +++ b/crates/compiler/uitest/tests/ability/specialize/bool_to_encoder.txt @@ -1,4 +1,4 @@ app "test" provides [main] to "./platform" main = Encode.toEncoder Bool.true -# ^^^^^^^^^^^^^^^^ Encoding#Encode.toEncoder(2): Bool -[[] + fmt:Encode.bool(17):1]-> Encoder fmt | fmt has EncoderFormatting +# ^^^^^^^^^^^^^^^^ Encoding#Encode.toEncoder(2): Bool -[[] + fmt:Encode.bool(17):1]-> Encoder fmt where fmt implements EncoderFormatting diff --git a/crates/compiler/uitest/tests/ability/specialize/dec_hash.txt b/crates/compiler/uitest/tests/ability/specialize/dec_hash.txt index facc13c6ae..a69b5c6722 100644 --- a/crates/compiler/uitest/tests/ability/specialize/dec_hash.txt +++ b/crates/compiler/uitest/tests/ability/specialize/dec_hash.txt @@ -2,4 +2,4 @@ app "test" provides [main] to "./platform" main = \h -> Hash.hash h 1.1dec - # ^^^^^^^^^ Hash#Hash.hash(1): a, Dec -[[Hash.hashDec(17)]]-> a | a has Hasher + # ^^^^^^^^^ Hash#Hash.hash(1): a, Dec -[[Hash.hashDec(17)]]-> a where a implements Hasher diff --git a/crates/compiler/uitest/tests/ability/specialize/opaque_decoder_derive.txt b/crates/compiler/uitest/tests/ability/specialize/opaque_decoder_derive.txt index 65a68da3a4..9ea64135f1 100644 --- a/crates/compiler/uitest/tests/ability/specialize/opaque_decoder_derive.txt +++ b/crates/compiler/uitest/tests/ability/specialize/opaque_decoder_derive.txt @@ -1,9 +1,9 @@ # +opt infer:print_only_under_alias app "test" provides [main] to "./platform" -N := U8 has [Decoding] +N := U8 implements [Decoding] main : Decoder N _ main = Decode.custom \bytes, fmt -> Decode.decodeWith bytes Decode.decoder fmt -# ^^^^^^^^^^^^^^ N#Decode.decoder(3): List U8, fmt -[[7]]-> { rest : List U8, result : [Err [TooShort], Ok U8] } | fmt has DecoderFormatting +# ^^^^^^^^^^^^^^ N#Decode.decoder(3): List U8, fmt -[[7]]-> { rest : List U8, result : [Err [TooShort], Ok U8] } where fmt implements DecoderFormatting diff --git a/crates/compiler/uitest/tests/ability/specialize/opaque_encoder_derive.txt b/crates/compiler/uitest/tests/ability/specialize/opaque_encoder_derive.txt index 0deb0fef59..6e1b247dc6 100644 --- a/crates/compiler/uitest/tests/ability/specialize/opaque_encoder_derive.txt +++ b/crates/compiler/uitest/tests/ability/specialize/opaque_encoder_derive.txt @@ -1,6 +1,6 @@ app "test" provides [main] to "./platform" -N := U8 has [Encoding] +N := U8 implements [Encoding] main = Encode.toEncoder (@N 15) -# ^^^^^^^^^^^^^^^^ N#Encode.toEncoder(3): N -[[#N_toEncoder(3)]]-> Encoder fmt | fmt has EncoderFormatting +# ^^^^^^^^^^^^^^^^ N#Encode.toEncoder(3): N -[[#N_toEncoder(3)]]-> Encoder fmt where fmt implements EncoderFormatting diff --git a/crates/compiler/uitest/tests/ability/specialize/opaque_eq_custom.txt b/crates/compiler/uitest/tests/ability/specialize/opaque_eq_custom.txt index 9d83310b13..8cb1c64cc7 100644 --- a/crates/compiler/uitest/tests/ability/specialize/opaque_eq_custom.txt +++ b/crates/compiler/uitest/tests/ability/specialize/opaque_eq_custom.txt @@ -1,6 +1,6 @@ app "test" provides [main] to "./platform" -Trivial := {} has [Eq {isEq}] +Trivial := {} implements [Eq {isEq}] isEq = \@Trivial {}, @Trivial {} -> Bool.true diff --git a/crates/compiler/uitest/tests/ability/specialize/opaque_eq_derive.txt b/crates/compiler/uitest/tests/ability/specialize/opaque_eq_derive.txt index cb840d7d28..173fd0674d 100644 --- a/crates/compiler/uitest/tests/ability/specialize/opaque_eq_derive.txt +++ b/crates/compiler/uitest/tests/ability/specialize/opaque_eq_derive.txt @@ -1,6 +1,6 @@ app "test" provides [main] to "./platform" -N := U8 has [Eq] +N := U8 implements [Eq] main = Bool.isEq (@N 15) (@N 23) # ^^^^^^^^^ N#Bool.isEq(3): N, N -[[#N_isEq(3)]]-> Bool diff --git a/crates/compiler/uitest/tests/ability/specialize/opaque_hash_custom.txt b/crates/compiler/uitest/tests/ability/specialize/opaque_hash_custom.txt index 4fb63b7df7..a1260a48fd 100644 --- a/crates/compiler/uitest/tests/ability/specialize/opaque_hash_custom.txt +++ b/crates/compiler/uitest/tests/ability/specialize/opaque_hash_custom.txt @@ -1,8 +1,8 @@ app "test" provides [main] to "./platform" -Noop := {} has [Hash {hash}] +Noop := {} implements [Hash {hash}] hash = \hasher, @Noop {} -> hasher main = \hasher -> hash hasher (@Noop {}) -#^^^^{-1} hasher -[[main(0)]]-> hasher | hasher has Hasher +#^^^^{-1} hasher -[[main(0)]]-> hasher where hasher implements Hasher diff --git a/crates/compiler/uitest/tests/ability/specialize/opaque_hash_derive.txt b/crates/compiler/uitest/tests/ability/specialize/opaque_hash_derive.txt index 250e788a1c..bf0f35a607 100644 --- a/crates/compiler/uitest/tests/ability/specialize/opaque_hash_derive.txt +++ b/crates/compiler/uitest/tests/ability/specialize/opaque_hash_derive.txt @@ -1,6 +1,6 @@ app "test" provides [main] to "./platform" -N := U8 has [Hash] +N := U8 implements [Hash] main = \hasher, @N n -> Hash.hash hasher (@N n) -# ^^^^^^^^^ N#Hash.hash(3): a, N -[[#N_hash(3)]]-> a | a has Hasher +# ^^^^^^^^^ N#Hash.hash(3): a, N -[[#N_hash(3)]]-> a where a implements Hasher diff --git a/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization.txt b/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization.txt index 010746a21b..a9b7ba5ceb 100644 --- a/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization.txt +++ b/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization.txt @@ -1,13 +1,13 @@ app "test" provides [main] to "./platform" -F has f : a -> (b -> {}) | a has F, b has G -G has g : b -> {} | b has G +F implements f : a -> (b -> {}) where a implements F, b implements G +G implements g : b -> {} where b implements G -Fo := {} has [F {f}] +Fo := {} implements [F {f}] f = \@Fo {} -> g -#^{-1} Fo#f(7): Fo -[[f(7)]]-> (b -[[] + b:g(4):1]-> {}) | b has G +#^{-1} Fo#f(7): Fo -[[f(7)]]-> (b -[[] + b:g(4):1]-> {}) where b implements G -Go := {} has [G {g}] +Go := {} implements [G {g}] g = \@Go {} -> {} #^{-1} Go#g(8): Go -[[g(8)]]-> {} diff --git a/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization_bound_output.txt b/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization_bound_output.txt index ab0dac137f..fcedaca3cf 100644 --- a/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization_bound_output.txt +++ b/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization_bound_output.txt @@ -1,13 +1,13 @@ app "test" provides [main] to "./platform" -F has f : a -> ({} -> b) | a has F, b has G -G has g : {} -> b | b has G +F implements f : a -> ({} -> b) where a implements F, b implements G +G implements g : {} -> b where b implements G -Fo := {} has [F {f}] +Fo := {} implements [F {f}] f = \@Fo {} -> g -#^{-1} Fo#f(7): Fo -[[f(7)]]-> ({} -[[] + b:g(4):1]-> b) | b has G +#^{-1} Fo#f(7): Fo -[[f(7)]]-> ({} -[[] + b:g(4):1]-> b) where b implements G -Go := {} has [G {g}] +Go := {} implements [G {g}] g = \{} -> @Go {} #^{-1} Go#g(8): {} -[[g(8)]]-> Go diff --git a/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization_branching_over_single_variable.txt b/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization_branching_over_single_variable.txt index 242be08499..abc75f0c2e 100644 --- a/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization_branching_over_single_variable.txt +++ b/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization_branching_over_single_variable.txt @@ -1,15 +1,15 @@ app "test" provides [f] to "./platform" -J has j : j -> (k -> {}) | j has J, k has K -K has k : k -> {} | k has K +J implements j : j -> (k -> {}) where j implements J, k implements K +K implements k : k -> {} where k implements K -C := {} has [J {j: jC}] +C := {} implements [J {j: jC}] jC = \@C _ -> k -D := {} has [J {j: jD}] +D := {} implements [J {j: jD}] jD = \@D _ -> k -E := {} has [K {k}] +E := {} implements [K {k}] k = \@E _ -> {} f = \flag, a, c -> @@ -18,5 +18,5 @@ f = \flag, a, c -> A -> j a B -> j a it c -# ^ k | k has K -# ^^ k -[[] + j:j(2):2]-> {} | j has J, k has K +# ^ k where k implements K +# ^^ k -[[] + j:j(2):2]-> {} where j implements J, k implements K diff --git a/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization_varying_over_multiple_variables.txt b/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization_varying_over_multiple_variables.txt index a71e0898aa..1d3192d532 100644 --- a/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization_varying_over_multiple_variables.txt +++ b/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization_varying_over_multiple_variables.txt @@ -1,32 +1,32 @@ app "test" provides [main] to "./platform" -J has j : j -> (k -> {}) | j has J, k has K -K has k : k -> {} | k has K +J implements j : j -> (k -> {}) where j implements J, k implements K +K implements k : k -> {} where k implements K -C := {} has [J {j: jC}] +C := {} implements [J {j: jC}] jC = \@C _ -> k -#^^{-1} C -[[jC(8)]]-> (k -[[] + k:k(4):1]-> {}) | k has K +#^^{-1} C -[[jC(8)]]-> (k -[[] + k:k(4):1]-> {}) where k implements K -D := {} has [J {j: jD}] +D := {} implements [J {j: jD}] jD = \@D _ -> k -#^^{-1} D -[[jD(9)]]-> (k -[[] + k:k(4):1]-> {}) | k has K +#^^{-1} D -[[jD(9)]]-> (k -[[] + k:k(4):1]-> {}) where k implements K -E := {} has [K {k}] +E := {} implements [K {k}] k = \@E _ -> {} #^{-1} E#k(10): E -[[k(10)]]-> {} f = \flag, a, b -> -# ^ j | j has J -# ^ j | j has J +# ^ j where j implements J +# ^ j where j implements J it = -# ^^ k -[[] + j:j(2):2 + j1:j(2):2]-> {} | j has J, j1 has J, k has K +# ^^ k -[[] + j:j(2):2 + j1:j(2):2]-> {} where j implements J, j1 implements J, k implements K when flag is A -> j a - # ^ J#j(2): j -[[] + j:j(2):1]-> (k -[[] + j:j(2):2 + j1:j(2):2]-> {}) | j has J, j1 has J, k has K + # ^ J#j(2): j -[[] + j:j(2):1]-> (k -[[] + j:j(2):2 + j1:j(2):2]-> {}) where j implements J, j1 implements J, k implements K B -> j b - # ^ J#j(2): j -[[] + j:j(2):1]-> (k -[[] + j1:j(2):2 + j:j(2):2]-> {}) | j has J, j1 has J, k has K + # ^ J#j(2): j -[[] + j:j(2):1]-> (k -[[] + j1:j(2):2 + j:j(2):2]-> {}) where j implements J, j1 implements J, k implements K it -# ^^ k -[[] + j:j(2):2 + j1:j(2):2]-> {} | j has J, j1 has J, k has K +# ^^ k -[[] + j:j(2):2 + j1:j(2):2]-> {} where j implements J, j1 implements J, k implements K main = (f A (@C {}) (@D {})) (@E {}) # ^ [A, B], C, D -[[f(11)]]-> (E -[[k(10)]]-> {}) diff --git a/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization_varying_over_multiple_variables_two_results.txt b/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization_varying_over_multiple_variables_two_results.txt index 34a84a5d11..5cf0feadae 100644 --- a/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization_varying_over_multiple_variables_two_results.txt +++ b/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization_varying_over_multiple_variables_two_results.txt @@ -1,43 +1,43 @@ app "test" provides [main] to "./platform" -J has j : j -> (k -> {}) | j has J, k has K -K has k : k -> {} | k has K +J implements j : j -> (k -> {}) where j implements J, k implements K +K implements k : k -> {} where k implements K -C := {} has [J {j: jC}] +C := {} implements [J {j: jC}] jC = \@C _ -> k -#^^{-1} C -[[jC(9)]]-> (k -[[] + k:k(4):1]-> {}) | k has K +#^^{-1} C -[[jC(9)]]-> (k -[[] + k:k(4):1]-> {}) where k implements K -D := {} has [J {j: jD}] +D := {} implements [J {j: jD}] jD = \@D _ -> k -#^^{-1} D -[[jD(10)]]-> (k -[[] + k:k(4):1]-> {}) | k has K +#^^{-1} D -[[jD(10)]]-> (k -[[] + k:k(4):1]-> {}) where k implements K -E := {} has [K {k: kE}] +E := {} implements [K {k: kE}] kE = \@E _ -> {} #^^{-1} E -[[kE(11)]]-> {} -F := {} has [K {k: kF}] +F := {} implements [K {k: kF}] kF = \@F _ -> {} #^^{-1} F -[[kF(12)]]-> {} f = \flag, a, b -> -# ^ j | j has J -# ^ j | j has J +# ^ j where j implements J +# ^ j where j implements J it = -# ^^ k -[[] + j:j(2):2 + j1:j(2):2]-> {} | j has J, j1 has J, k has K +# ^^ k -[[] + j:j(2):2 + j1:j(2):2]-> {} where j implements J, j1 implements J, k implements K when flag is A -> j a - # ^ J#j(2): j -[[] + j:j(2):1]-> (k -[[] + j:j(2):2 + j1:j(2):2]-> {}) | j has J, j1 has J, k has K + # ^ J#j(2): j -[[] + j:j(2):1]-> (k -[[] + j:j(2):2 + j1:j(2):2]-> {}) where j implements J, j1 implements J, k implements K B -> j b - # ^ J#j(2): j -[[] + j:j(2):1]-> (k -[[] + j1:j(2):2 + j:j(2):2]-> {}) | j has J, j1 has J, k has K + # ^ J#j(2): j -[[] + j:j(2):1]-> (k -[[] + j1:j(2):2 + j:j(2):2]-> {}) where j implements J, j1 implements J, k implements K it -# ^^ k -[[] + j:j(2):2 + j1:j(2):2]-> {} | j has J, j1 has J, k has K +# ^^ k -[[] + j:j(2):2 + j1:j(2):2]-> {} where j implements J, j1 implements J, k implements K main = #^^^^{-1} {} it = \x -> -# ^^ k -[[it(21)]]-> {} | k has K +# ^^ k -[[it(21)]]-> {} where k implements K (f A (@C {}) (@D {})) x -# ^ [A, B], C, D -[[f(13)]]-> (k -[[] + k:k(4):1]-> {}) | k has K +# ^ [A, B], C, D -[[f(13)]]-> (k -[[] + k:k(4):1]-> {}) where k implements K if Bool.true then it (@E {}) # ^^ E -[[it(21)]]-> {} diff --git a/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization_with_deep_specialization_and_capture.txt b/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization_with_deep_specialization_and_capture.txt index 1d1ab51d65..3040768282 100644 --- a/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization_with_deep_specialization_and_capture.txt +++ b/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization_with_deep_specialization_and_capture.txt @@ -1,13 +1,13 @@ app "test" provides [main] to "./platform" -F has f : a, b -> ({} -> ({} -> {})) | a has F, b has G -G has g : b -> ({} -> {}) | b has G +F implements f : a, b -> ({} -> ({} -> {})) where a implements F, b implements G +G implements g : b -> ({} -> {}) where b implements G -Fo := {} has [F {f}] +Fo := {} implements [F {f}] f = \@Fo {}, b -> \{} -> g b -#^{-1} Fo#f(7): Fo, b -[[f(7)]]-> ({} -[[13 b]]-> ({} -[[] + b:g(4):2]-> {})) | b has G +#^{-1} Fo#f(7): Fo, b -[[f(7)]]-> ({} -[[13 b]]-> ({} -[[] + b:g(4):2]-> {})) where b implements G -Go := {} has [G {g}] +Go := {} implements [G {g}] g = \@Go {} -> \{} -> {} #^{-1} Go#g(8): Go -[[g(8)]]-> ({} -[[14]]-> {}) diff --git a/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization_with_let_weakened.txt b/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization_with_let_weakened.txt index fb24dd6496..d52dd50232 100644 --- a/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization_with_let_weakened.txt +++ b/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization_with_let_weakened.txt @@ -1,13 +1,13 @@ app "test" provides [main] to "./platform" -F has f : a -> (b -> {}) | a has F, b has G -G has g : b -> {} | b has G +F implements f : a -> (b -> {}) where a implements F, b implements G +G implements g : b -> {} where b implements G -Fo := {} has [F {f}] +Fo := {} implements [F {f}] f = \@Fo {} -> g -#^{-1} Fo#f(7): Fo -[[f(7)]]-> (b -[[] + b:g(4):1]-> {}) | b has G +#^{-1} Fo#f(7): Fo -[[f(7)]]-> (b -[[] + b:g(4):1]-> {}) where b implements G -Go := {} has [G {g}] +Go := {} implements [G {g}] g = \@Go {} -> {} #^{-1} Go#g(8): Go -[[g(8)]]-> {} diff --git a/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization_with_let_weakened_unapplied.txt b/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization_with_let_weakened_unapplied.txt index 31cb72dd0f..6a0e2b3e98 100644 --- a/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization_with_let_weakened_unapplied.txt +++ b/crates/compiler/uitest/tests/ability/specialize/polymorphic_lambda_set_specialization_with_let_weakened_unapplied.txt @@ -1,19 +1,19 @@ app "test" provides [main] to "./platform" -F has f : a -> (b -> {}) | a has F, b has G -G has g : b -> {} | b has G +F implements f : a -> (b -> {}) where a implements F, b implements G +G implements g : b -> {} where b implements G -Fo := {} has [F {f}] +Fo := {} implements [F {f}] f = \@Fo {} -> g -#^{-1} Fo#f(7): Fo -[[f(7)]]-> (b -[[] + b:g(4):1]-> {}) | b has G +#^{-1} Fo#f(7): Fo -[[f(7)]]-> (b -[[] + b:g(4):1]-> {}) where b implements G -Go := {} has [G {g}] +Go := {} implements [G {g}] g = \@Go {} -> {} #^{-1} Go#g(8): Go -[[g(8)]]-> {} main = -#^^^^{-1} b -[[] + b:g(4):1]-> {} | b has G +#^^^^{-1} b -[[] + b:g(4):1]-> {} where b implements G h = f (@Fo {}) -# ^ Fo#f(7): Fo -[[f(7)]]-> (b -[[] + b:g(4):1]-> {}) | b has G -# ^ b -[[] + b:g(4):1]-> {} | b has G +# ^ Fo#f(7): Fo -[[f(7)]]-> (b -[[] + b:g(4):1]-> {}) where b implements G +# ^ b -[[] + b:g(4):1]-> {} where b implements G h diff --git a/crates/compiler/uitest/tests/ability/specialize/ranged_num_hash.txt b/crates/compiler/uitest/tests/ability/specialize/ranged_num_hash.txt index fa65790b1f..0cfad58ac9 100644 --- a/crates/compiler/uitest/tests/ability/specialize/ranged_num_hash.txt +++ b/crates/compiler/uitest/tests/ability/specialize/ranged_num_hash.txt @@ -2,4 +2,4 @@ app "test" provides [main] to "./platform" main = \h -> Hash.hash h 7 - # ^^^^^^^^^ Hash#Hash.hash(1): a, I64 -[[Hash.hashI64(13)]]-> a | a has Hasher + # ^^^^^^^^^ Hash#Hash.hash(1): a, I64 -[[Hash.hashI64(13)]]-> a where a implements Hasher diff --git a/crates/compiler/uitest/tests/ability/specialize/record_to_encoder.txt b/crates/compiler/uitest/tests/ability/specialize/record_to_encoder.txt index ac6dc4d265..e3b4e8cdc8 100644 --- a/crates/compiler/uitest/tests/ability/specialize/record_to_encoder.txt +++ b/crates/compiler/uitest/tests/ability/specialize/record_to_encoder.txt @@ -3,4 +3,4 @@ app "test" provides [main] to "./platform" main = toEncoder { a: "" } - # ^^^^^^^^^ Encoding#toEncoder(2): { a : Str } -[[#Derived.toEncoder_{a}(0)]]-> Encoder fmt | fmt has EncoderFormatting + # ^^^^^^^^^ Encoding#toEncoder(2): { a : Str } -[[#Derived.toEncoder_{a}(0)]]-> Encoder fmt where fmt implements EncoderFormatting diff --git a/crates/compiler/uitest/tests/ability/specialize/record_to_encoder_with_nested_custom_impl.txt b/crates/compiler/uitest/tests/ability/specialize/record_to_encoder_with_nested_custom_impl.txt index df9d14d788..769296f3cf 100644 --- a/crates/compiler/uitest/tests/ability/specialize/record_to_encoder_with_nested_custom_impl.txt +++ b/crates/compiler/uitest/tests/ability/specialize/record_to_encoder_with_nested_custom_impl.txt @@ -2,8 +2,8 @@ app "test" imports [Encode.{ toEncoder, custom }] provides [main] to "./platform" -A := {} has [Encoding {toEncoder}] +A := {} implements [Encoding {toEncoder}] toEncoder = \@A _ -> custom \b, _ -> b main = toEncoder { a: @A {} } - # ^^^^^^^^^ Encoding#toEncoder(2): { a : A } -[[#Derived.toEncoder_{a}(0)]]-> Encoder fmt | fmt has EncoderFormatting + # ^^^^^^^^^ Encoding#toEncoder(2): { a : A } -[[#Derived.toEncoder_{a}(0)]]-> Encoder fmt where fmt implements EncoderFormatting diff --git a/crates/compiler/uitest/tests/ability/specialize/resolve_lambda_set_ability_chain.txt b/crates/compiler/uitest/tests/ability/specialize/resolve_lambda_set_ability_chain.txt index 68dfcf4582..23705beb8e 100644 --- a/crates/compiler/uitest/tests/ability/specialize/resolve_lambda_set_ability_chain.txt +++ b/crates/compiler/uitest/tests/ability/specialize/resolve_lambda_set_ability_chain.txt @@ -1,9 +1,9 @@ app "test" provides [main] to "./platform" -Id1 has id1 : a -> a | a has Id1 -Id2 has id2 : a -> a | a has Id2 +Id1 implements id1 : a -> a where a implements Id1 +Id2 implements id2 : a -> a where a implements Id2 -A := {} has [Id1 {id1}, Id2 {id2}] +A := {} implements [Id1 {id1}, Id2 {id2}] id1 = \@A {} -> @A {} #^^^{-1} A#id1(6): A -[[id1(6)]]-> A diff --git a/crates/compiler/uitest/tests/ability/specialize/resolve_lambda_set_branches_ability_vs_non_ability.txt b/crates/compiler/uitest/tests/ability/specialize/resolve_lambda_set_branches_ability_vs_non_ability.txt index 358f3fa021..d7c226d7d2 100644 --- a/crates/compiler/uitest/tests/ability/specialize/resolve_lambda_set_branches_ability_vs_non_ability.txt +++ b/crates/compiler/uitest/tests/ability/specialize/resolve_lambda_set_branches_ability_vs_non_ability.txt @@ -1,8 +1,8 @@ app "test" provides [main] to "./platform" -Id has id : a -> a | a has Id +Id implements id : a -> a where a implements Id -A := {} has [Id {id}] +A := {} implements [Id {id}] id = \@A {} -> @A {} #^^{-1} A#id(4): A -[[id(4)]]-> A diff --git a/crates/compiler/uitest/tests/ability/specialize/resolve_lambda_set_branches_same_ability.txt b/crates/compiler/uitest/tests/ability/specialize/resolve_lambda_set_branches_same_ability.txt index 497b4a981c..ecaef311f1 100644 --- a/crates/compiler/uitest/tests/ability/specialize/resolve_lambda_set_branches_same_ability.txt +++ b/crates/compiler/uitest/tests/ability/specialize/resolve_lambda_set_branches_same_ability.txt @@ -1,8 +1,8 @@ app "test" provides [main] to "./platform" -Id has id : a -> a | a has Id +Id implements id : a -> a where a implements Id -A := {} has [Id {id}] +A := {} implements [Id {id}] id = \@A {} -> @A {} #^^{-1} A#id(4): A -[[id(4)]]-> A diff --git a/crates/compiler/uitest/tests/ability/specialize/resolve_lambda_set_generalized_ability_alias.txt b/crates/compiler/uitest/tests/ability/specialize/resolve_lambda_set_generalized_ability_alias.txt index 541a32b3ca..90a6ab84fe 100644 --- a/crates/compiler/uitest/tests/ability/specialize/resolve_lambda_set_generalized_ability_alias.txt +++ b/crates/compiler/uitest/tests/ability/specialize/resolve_lambda_set_generalized_ability_alias.txt @@ -1,16 +1,16 @@ app "test" provides [main] to "./platform" -Id has id : a -> a | a has Id +Id implements id : a -> a where a implements Id -A := {} has [Id {id}] +A := {} implements [Id {id}] id = \@A {} -> @A {} #^^{-1} A#id(4): A -[[id(4)]]-> A main = alias1 = \x -> id x - # ^^ Id#id(2): a -[[] + a:id(2):1]-> a | a has Id + # ^^ Id#id(2): a -[[] + a:id(2):1]-> a where a implements Id alias2 = \x -> alias1 x - # ^^^^^^ a -[[alias1(6)]]-> a | a has Id + # ^^^^^^ a -[[alias1(6)]]-> a where a implements Id a : A a = alias2 (@A {}) diff --git a/crates/compiler/uitest/tests/ability/specialize/resolve_lambda_set_weakened_ability_alias.txt b/crates/compiler/uitest/tests/ability/specialize/resolve_lambda_set_weakened_ability_alias.txt index af8b3f017a..e90cf3ebae 100644 --- a/crates/compiler/uitest/tests/ability/specialize/resolve_lambda_set_weakened_ability_alias.txt +++ b/crates/compiler/uitest/tests/ability/specialize/resolve_lambda_set_weakened_ability_alias.txt @@ -1,8 +1,8 @@ app "test" provides [main] to "./platform" -Id has id : a -> a | a has Id +Id implements id : a -> a where a implements Id -A := {} has [Id {id}] +A := {} implements [Id {id}] id = \@A {} -> @A {} #^^{-1} A#id(4): A -[[id(4)]]-> A diff --git a/crates/compiler/uitest/tests/ability/specialize/resolve_mutually_recursive_ability_lambda_sets.txt b/crates/compiler/uitest/tests/ability/specialize/resolve_mutually_recursive_ability_lambda_sets.txt index 91f70d7f7c..3daf251c37 100644 --- a/crates/compiler/uitest/tests/ability/specialize/resolve_mutually_recursive_ability_lambda_sets.txt +++ b/crates/compiler/uitest/tests/ability/specialize/resolve_mutually_recursive_ability_lambda_sets.txt @@ -1,10 +1,10 @@ app "test" provides [main] to "./platform" -Bounce has - ping : a -> a | a has Bounce - pong : a -> a | a has Bounce +Bounce implements + ping : a -> a where a implements Bounce + pong : a -> a where a implements Bounce -A := {} has [Bounce {ping: pingA, pong: pongA}] +A := {} implements [Bounce {ping: pingA, pong: pongA}] pingA = \@A {} -> pong (@A {}) # ^^^^ A#pong(6): A -[[pongA(6)]]-> A diff --git a/crates/compiler/uitest/tests/ability/specialize/resolve_mutually_recursive_ability_lambda_sets_inferred.txt b/crates/compiler/uitest/tests/ability/specialize/resolve_mutually_recursive_ability_lambda_sets_inferred.txt index 22b25a9adb..560ead417c 100644 --- a/crates/compiler/uitest/tests/ability/specialize/resolve_mutually_recursive_ability_lambda_sets_inferred.txt +++ b/crates/compiler/uitest/tests/ability/specialize/resolve_mutually_recursive_ability_lambda_sets_inferred.txt @@ -1,10 +1,10 @@ app "test" provides [main] to "./platform" -Bounce has - ping : a -> a | a has Bounce - pong : a -> a | a has Bounce +Bounce implements + ping : a -> a where a implements Bounce + pong : a -> a where a implements Bounce -A := {} has [Bounce {ping, pong}] +A := {} implements [Bounce {ping, pong}] ping = \@A {} -> pong (@A {}) # ^^^^ A#pong(6): A -[[pong(6)]]-> A diff --git a/crates/compiler/uitest/tests/ability/specialize/resolve_recursive_ability_lambda_set.txt b/crates/compiler/uitest/tests/ability/specialize/resolve_recursive_ability_lambda_set.txt index 6060616d70..993454a1b6 100644 --- a/crates/compiler/uitest/tests/ability/specialize/resolve_recursive_ability_lambda_set.txt +++ b/crates/compiler/uitest/tests/ability/specialize/resolve_recursive_ability_lambda_set.txt @@ -1,8 +1,8 @@ app "test" provides [main] to "./platform" -Diverge has diverge : a -> a | a has Diverge +Diverge implements diverge : a -> a where a implements Diverge -A := {} has [Diverge {diverge}] +A := {} implements [Diverge {diverge}] diverge : A -> A diverge = \@A {} -> diverge (@A {}) diff --git a/crates/compiler/uitest/tests/ability/specialize/resolve_two_unspecialized_lambda_sets_in_one_lambda_set.txt b/crates/compiler/uitest/tests/ability/specialize/resolve_two_unspecialized_lambda_sets_in_one_lambda_set.txt index 4e85e6905c..3d6991faa9 100644 --- a/crates/compiler/uitest/tests/ability/specialize/resolve_two_unspecialized_lambda_sets_in_one_lambda_set.txt +++ b/crates/compiler/uitest/tests/ability/specialize/resolve_two_unspecialized_lambda_sets_in_one_lambda_set.txt @@ -3,9 +3,9 @@ app "test" provides [main] to "./platform" Thunk a : {} -> a -Id has id : a -> Thunk a | a has Id +Id implements id : a -> Thunk a where a implements Id -A := {} has [Id {id}] +A := {} implements [Id {id}] id = \@A {} -> \{} -> @A {} #^^{-1} A#id(5): {} -[[id(5)]]-> ({} -[[8]]-> {}) diff --git a/crates/compiler/uitest/tests/ability/specialize/resolve_unspecialized_lambda_set_behind_alias.txt b/crates/compiler/uitest/tests/ability/specialize/resolve_unspecialized_lambda_set_behind_alias.txt index b08f4795a2..e8056b8340 100644 --- a/crates/compiler/uitest/tests/ability/specialize/resolve_unspecialized_lambda_set_behind_alias.txt +++ b/crates/compiler/uitest/tests/ability/specialize/resolve_unspecialized_lambda_set_behind_alias.txt @@ -3,15 +3,15 @@ app "test" provides [main] to "./platform" Thunk a : {} -> a -Id has id : a -> Thunk a | a has Id +Id implements id : a -> Thunk a where a implements Id -A := {} has [Id {id}] +A := {} implements [Id {id}] id = \@A {} -> \{} -> @A {} #^^{-1} A#id(5): {} -[[id(5)]]-> ({} -[[8]]-> {}) main = alias = \x -> id x - # ^^ Id#id(3): a -[[] + a:id(3):1]-> ({} -[[] + a:id(3):2]-> a) | a has Id + # ^^ Id#id(3): a -[[] + a:id(3):1]-> ({} -[[] + a:id(3):2]-> a) where a implements Id a : A a = (alias (@A {})) {} diff --git a/crates/compiler/uitest/tests/ability/specialize/resolve_unspecialized_lambda_set_behind_opaque.txt b/crates/compiler/uitest/tests/ability/specialize/resolve_unspecialized_lambda_set_behind_opaque.txt index ab960558bc..aa7ff8e6a7 100644 --- a/crates/compiler/uitest/tests/ability/specialize/resolve_unspecialized_lambda_set_behind_opaque.txt +++ b/crates/compiler/uitest/tests/ability/specialize/resolve_unspecialized_lambda_set_behind_opaque.txt @@ -3,9 +3,9 @@ app "test" provides [main] to "./platform" Thunk a := {} -> a -Id has id : a -> Thunk a | a has Id +Id implements id : a -> Thunk a where a implements Id -A := {} has [Id {id}] +A := {} implements [Id {id}] id = \@A {} -> @Thunk (\{} -> @A {}) #^^{-1} A#id(5): {} -[[id(5)]]-> ({} -[[8]]-> {}) diff --git a/crates/compiler/uitest/tests/ability/specialize/static_specialization.txt b/crates/compiler/uitest/tests/ability/specialize/static_specialization.txt index 5ec8b64c60..ab53585cf3 100644 --- a/crates/compiler/uitest/tests/ability/specialize/static_specialization.txt +++ b/crates/compiler/uitest/tests/ability/specialize/static_specialization.txt @@ -1,8 +1,8 @@ app "test" provides [main] to "./platform" -Default has default : {} -> a | a has Default +Default implements default : {} -> a where a implements Default -A := {} has [Default {default}] +A := {} implements [Default {default}] default = \{} -> @A {} main = diff --git a/crates/compiler/uitest/tests/instantiate/call_generic_ability_member.txt b/crates/compiler/uitest/tests/instantiate/call_generic_ability_member.txt index a0c045ee64..e1cdbcce81 100644 --- a/crates/compiler/uitest/tests/instantiate/call_generic_ability_member.txt +++ b/crates/compiler/uitest/tests/instantiate/call_generic_ability_member.txt @@ -1,19 +1,19 @@ app "test" provides [main] to "./platform" -X has - consume : a -> {} | a has X +X implements + consume : a -> {} where a implements X -O := {} has [X {consume: consumeO}] +O := {} implements [X {consume: consumeO}] consumeO = \@O {} -> {} -P := {} has [X {consume: consumeP}] +P := {} implements [X {consume: consumeP}] consumeP = \@P {} -> {} caller = \x -> consume x -# ^ a | a has X -# ^^^^^^^ X#consume(2): a -[[] + a:consume(2):1]-> {} | a has X +# ^ a where a implements X +# ^^^^^^^ X#consume(2): a -[[] + a:consume(2):1]-> {} where a implements X main = { a: caller (@O {}), diff --git a/crates/compiler/uitest/tests/recursion/generalization_among_large_recursive_group.txt b/crates/compiler/uitest/tests/recursion/generalization_among_large_recursive_group.txt index 2a62926c8f..6238bd9ad1 100644 --- a/crates/compiler/uitest/tests/recursion/generalization_among_large_recursive_group.txt +++ b/crates/compiler/uitest/tests/recursion/generalization_among_large_recursive_group.txt @@ -3,22 +3,22 @@ app "test" provides [main] to "./platform" f = \{} -> -#^{-1} <1600><117>{} -<120>[[f(1)]]-> <116>[Ok <1608>{}]<80>* +#^{-1} <1874><117>{} -<120>[[f(1)]]-> <116>[Ok <1882>{}]<80>* when g {} is -# ^ <1590><1608>{} -<1598>[[g(2)]]-> <72>[Ok <1608>{}]<102>* +# ^ <1864><1882>{} -<1872>[[g(2)]]-> <72>[Ok <1882>{}]<102>* _ -> Ok {} g = \{} -> -#^{-1} <1590><1608>{} -<1598>[[g(2)]]-> <72>[Ok <1608>{}]<102>* +#^{-1} <1864><1882>{} -<1872>[[g(2)]]-> <72>[Ok <1882>{}]<102>* when h {} is -# ^ <1595><1608>{} -<1603>[[h(3)]]-> <94>[Ok <1608>{}]<124>* +# ^ <1869><1882>{} -<1877>[[h(3)]]-> <94>[Ok <1882>{}]<124>* _ -> Ok {} h = \{} -> -#^{-1} <1595><1608>{} -<1603>[[h(3)]]-> <94>[Ok <1608>{}]<124>* +#^{-1} <1869><1882>{} -<1877>[[h(3)]]-> <94>[Ok <1882>{}]<124>* when f {} is -# ^ <1600><117>{} -<120>[[f(1)]]-> <116>[Ok <1608>{}]<80>* +# ^ <1874><117>{} -<120>[[f(1)]]-> <116>[Ok <1882>{}]<80>* _ -> Ok {} main = f {} -# ^ <1610><133>{} -<136>[[f(1)]]-> <138>[Ok <1608>{}]<1609>w_a +# ^ <1884><133>{} -<136>[[f(1)]]-> <138>[Ok <1882>{}]<1883>w_a diff --git a/crates/compiler/uitest/tests/solve/ability_checked_specialization_with_annotation_only.txt b/crates/compiler/uitest/tests/solve/ability_checked_specialization_with_annotation_only.txt index 35e7b3d362..366d156d8b 100644 --- a/crates/compiler/uitest/tests/solve/ability_checked_specialization_with_annotation_only.txt +++ b/crates/compiler/uitest/tests/solve/ability_checked_specialization_with_annotation_only.txt @@ -1,9 +1,9 @@ app "test" provides [hash] to "./platform" -MHash has - hash : a -> U64 | a has MHash +MHash implements + hash : a -> U64 where a implements MHash -Id := U64 has [MHash {hash}] +Id := U64 implements [MHash {hash}] hash : Id -> U64 #^^^^{-1} Id#hash(3): Id -[[hash(3)]]-> U64 diff --git a/crates/compiler/uitest/tests/solve/ability_checked_specialization_with_typed_body.txt b/crates/compiler/uitest/tests/solve/ability_checked_specialization_with_typed_body.txt index ecbe8c2922..db85fb9c61 100644 --- a/crates/compiler/uitest/tests/solve/ability_checked_specialization_with_typed_body.txt +++ b/crates/compiler/uitest/tests/solve/ability_checked_specialization_with_typed_body.txt @@ -1,9 +1,9 @@ app "test" provides [hash] to "./platform" -MHash has - hash : a -> U64 | a has MHash +MHash implements + hash : a -> U64 where a implements MHash -Id := U64 has [MHash {hash}] +Id := U64 implements [MHash {hash}] hash : Id -> U64 hash = \@Id n -> n diff --git a/crates/compiler/uitest/tests/solve/ability_constrained_in_non_member_check.txt b/crates/compiler/uitest/tests/solve/ability_constrained_in_non_member_check.txt index cdb461a6f2..72f5a2fe3d 100644 --- a/crates/compiler/uitest/tests/solve/ability_constrained_in_non_member_check.txt +++ b/crates/compiler/uitest/tests/solve/ability_constrained_in_non_member_check.txt @@ -1,8 +1,8 @@ app "test" provides [hashEq] to "./platform" -MHash has - hash : a -> U64 | a has MHash +MHash implements + hash : a -> U64 where a implements MHash -hashEq : a, a -> Bool | a has MHash +hashEq : a, a -> Bool where a implements MHash hashEq = \x, y -> hash x == hash y -#^^^^^^{-1} a, a -[[hashEq(0)]]-> Bool | a has MHash +#^^^^^^{-1} a, a -[[hashEq(0)]]-> Bool where a implements MHash diff --git a/crates/compiler/uitest/tests/solve/ability_constrained_in_non_member_infer.txt b/crates/compiler/uitest/tests/solve/ability_constrained_in_non_member_infer.txt index caf1681ba5..2344a9922c 100644 --- a/crates/compiler/uitest/tests/solve/ability_constrained_in_non_member_infer.txt +++ b/crates/compiler/uitest/tests/solve/ability_constrained_in_non_member_infer.txt @@ -1,7 +1,7 @@ app "test" provides [hashEq] to "./platform" -MHash has - hash : a -> U64 | a has MHash +MHash implements + hash : a -> U64 where a implements MHash hashEq = \x, y -> hash x == hash y -#^^^^^^{-1} a, a1 -[[hashEq(0)]]-> Bool | a has MHash, a1 has MHash +#^^^^^^{-1} a, a1 -[[hashEq(0)]]-> Bool where a implements MHash, a1 implements MHash diff --git a/crates/compiler/uitest/tests/solve/ability_constrained_in_non_member_infer_usage.txt b/crates/compiler/uitest/tests/solve/ability_constrained_in_non_member_infer_usage.txt index 18d9d56846..4e55a6ded3 100644 --- a/crates/compiler/uitest/tests/solve/ability_constrained_in_non_member_infer_usage.txt +++ b/crates/compiler/uitest/tests/solve/ability_constrained_in_non_member_infer_usage.txt @@ -1,11 +1,11 @@ app "test" provides [result] to "./platform" -MHash has - hash : a -> U64 | a has MHash +MHash implements + hash : a -> U64 where a implements MHash hashEq = \x, y -> hash x == hash y -Id := U64 has [MHash {hash}] +Id := U64 implements [MHash {hash}] hash = \@Id n -> n result = hashEq (@Id 100) (@Id 101) diff --git a/crates/compiler/uitest/tests/solve/ability_constrained_in_non_member_multiple_specializations.txt b/crates/compiler/uitest/tests/solve/ability_constrained_in_non_member_multiple_specializations.txt index cd2e96ba48..34e014097c 100644 --- a/crates/compiler/uitest/tests/solve/ability_constrained_in_non_member_multiple_specializations.txt +++ b/crates/compiler/uitest/tests/solve/ability_constrained_in_non_member_multiple_specializations.txt @@ -1,14 +1,14 @@ app "test" provides [result] to "./platform" -MHash has - hash : a -> U64 | a has MHash +MHash implements + hash : a -> U64 where a implements MHash mulMHashes = \x, y -> hash x * hash y -Id := U64 has [MHash { hash: hashId }] +Id := U64 implements [MHash { hash: hashId }] hashId = \@Id n -> n -Three := {} has [MHash { hash: hashThree }] +Three := {} implements [MHash { hash: hashThree }] hashThree = \@Three _ -> 3 result = mulMHashes (@Id 100) (@Three {}) diff --git a/crates/compiler/uitest/tests/solve/ability_specialization_called.txt b/crates/compiler/uitest/tests/solve/ability_specialization_called.txt index e88496dfda..632b5eac6c 100644 --- a/crates/compiler/uitest/tests/solve/ability_specialization_called.txt +++ b/crates/compiler/uitest/tests/solve/ability_specialization_called.txt @@ -1,9 +1,9 @@ app "test" provides [zero] to "./platform" -MHash has - hash : a -> U64 | a has MHash +MHash implements + hash : a -> U64 where a implements MHash -Id := U64 has [MHash {hash}] +Id := U64 implements [MHash {hash}] hash = \@Id n -> n diff --git a/crates/compiler/uitest/tests/solve/alias_ability_member.txt b/crates/compiler/uitest/tests/solve/alias_ability_member.txt index e552bf692e..550365d066 100644 --- a/crates/compiler/uitest/tests/solve/alias_ability_member.txt +++ b/crates/compiler/uitest/tests/solve/alias_ability_member.txt @@ -1,9 +1,9 @@ app "test" provides [thething] to "./platform" -MHash has - hash : a -> U64 | a has MHash +MHash implements + hash : a -> U64 where a implements MHash thething = -#^^^^^^^^{-1} a -[[] + a:hash(2):1]-> U64 | a has MHash +#^^^^^^^^{-1} a -[[] + a:hash(2):1]-> U64 where a implements MHash itis = hash itis diff --git a/crates/compiler/uitest/tests/solve/alias_propagates_able_var.txt b/crates/compiler/uitest/tests/solve/alias_propagates_able_var.txt index 6696025603..f4719ca9c7 100644 --- a/crates/compiler/uitest/tests/solve/alias_propagates_able_var.txt +++ b/crates/compiler/uitest/tests/solve/alias_propagates_able_var.txt @@ -1,8 +1,8 @@ app "test" provides [zeroEncoder] to "./platform" -MEncoder fmt := List U8, fmt -> List U8 | fmt has Format +MEncoder fmt := List U8, fmt -> List U8 where fmt implements Format -Format has it : fmt -> {} | fmt has Format +Format implements it : fmt -> {} where fmt implements Format zeroEncoder = @MEncoder \lst, _ -> lst -#^^^^^^^^^^^{-1} MEncoder a | a has Format +#^^^^^^^^^^^{-1} MEncoder a where a implements Format diff --git a/crates/compiler/uitest/tests/solve/exposed_ability_name.txt b/crates/compiler/uitest/tests/solve/exposed_ability_name.txt index 3563c02521..f22850b009 100644 --- a/crates/compiler/uitest/tests/solve/exposed_ability_name.txt +++ b/crates/compiler/uitest/tests/solve/exposed_ability_name.txt @@ -1,6 +1,6 @@ app "test" provides [main] to "./platform" -MHash has hash : a -> U64 | a has MHash +MHash implements hash : a -> U64 where a implements MHash main = hash -# ^^^^ MHash#hash(2): a -[[] + a:hash(2):1]-> U64 | a has MHash +# ^^^^ MHash#hash(2): a -[[] + a:hash(2):1]-> U64 where a implements MHash diff --git a/crates/compiler/uitest/tests/solve/multiple_abilities_multiple_members_specializations.txt b/crates/compiler/uitest/tests/solve/multiple_abilities_multiple_members_specializations.txt index d124bd1687..adddd308cb 100644 --- a/crates/compiler/uitest/tests/solve/multiple_abilities_multiple_members_specializations.txt +++ b/crates/compiler/uitest/tests/solve/multiple_abilities_multiple_members_specializations.txt @@ -1,14 +1,14 @@ app "test" provides [hash, hash32, eq, le] to "./platform" -MHash has - hash : a -> U64 | a has MHash - hash32 : a -> U32 | a has MHash +MHash implements + hash : a -> U64 where a implements MHash + hash32 : a -> U32 where a implements MHash -Ord has - eq : a, a -> Bool | a has Ord - le : a, a -> Bool | a has Ord +Ord implements + eq : a, a -> Bool where a implements Ord + le : a, a -> Bool where a implements Ord -Id := U64 has [MHash {hash, hash32}, Ord {eq, le}] +Id := U64 implements [MHash {hash, hash32}, Ord {eq, le}] hash = \@Id n -> n #^^^^{-1} Id#hash(7): Id -[[hash(7)]]-> U64 diff --git a/crates/compiler/uitest/tests/solve/single_ability_multiple_members_specializations.txt b/crates/compiler/uitest/tests/solve/single_ability_multiple_members_specializations.txt index 7b73ffa9ff..5738eebcd6 100644 --- a/crates/compiler/uitest/tests/solve/single_ability_multiple_members_specializations.txt +++ b/crates/compiler/uitest/tests/solve/single_ability_multiple_members_specializations.txt @@ -1,10 +1,10 @@ app "test" provides [hash, hash32] to "./platform" -MHash has - hash : a -> U64 | a has MHash - hash32 : a -> U32 | a has MHash +MHash implements + hash : a -> U64 where a implements MHash + hash32 : a -> U32 where a implements MHash -Id := U64 has [MHash {hash, hash32}] +Id := U64 implements [MHash {hash, hash32}] hash = \@Id n -> n #^^^^{-1} Id#hash(4): Id -[[hash(4)]]-> U64 diff --git a/crates/compiler/uitest/tests/solve/single_ability_single_member_specializations.txt b/crates/compiler/uitest/tests/solve/single_ability_single_member_specializations.txt index 33e30ed971..a49c763de5 100644 --- a/crates/compiler/uitest/tests/solve/single_ability_single_member_specializations.txt +++ b/crates/compiler/uitest/tests/solve/single_ability_single_member_specializations.txt @@ -1,8 +1,8 @@ app "test" provides [hash] to "./platform" -MHash has hash : a -> U64 | a has MHash +MHash implements hash : a -> U64 where a implements MHash -Id := U64 has [MHash {hash}] +Id := U64 implements [MHash {hash}] hash = \@Id n -> n #^^^^{-1} Id#hash(3): Id -[[hash(3)]]-> U64 diff --git a/crates/compiler/uitest/tests/solve/stdlib_encode_json.txt b/crates/compiler/uitest/tests/solve/stdlib_encode_json.txt index 86fccd4b5b..c799d0bc99 100644 --- a/crates/compiler/uitest/tests/solve/stdlib_encode_json.txt +++ b/crates/compiler/uitest/tests/solve/stdlib_encode_json.txt @@ -2,7 +2,7 @@ app "test" imports [TotallyNotJson] provides [main] to "./platform" -HelloWorld := {} has [Encoding {toEncoder}] +HelloWorld := {} implements [Encoding {toEncoder}] toEncoder = \@HelloWorld {} -> Encode.custom \bytes, fmt -> diff --git a/crates/compiler/unify/src/unify.rs b/crates/compiler/unify/src/unify.rs index 779f8d999f..32444cac1c 100644 --- a/crates/compiler/unify/src/unify.rs +++ b/crates/compiler/unify/src/unify.rs @@ -1235,7 +1235,7 @@ fn extract_specialization_lambda_set( // lambda set does not line up with one required by the ability member prototype. // As an example, consider // - // Q := [ F (Str -> Str) ] has [Eq {isEq}] + // Q := [ F (Str -> Str) ] implements [Eq {isEq}] // // isEq = \@Q _, @Q _ -> Bool.false // diff --git a/crates/docs/src/lib.rs b/crates/docs/src/lib.rs index cbf6fb0251..031a05c830 100644 --- a/crates/docs/src/lib.rs +++ b/crates/docs/src/lib.rs @@ -11,6 +11,7 @@ use roc_load::{ExecutionMode, LoadConfig, LoadedModule, LoadingProblem, Threadin use roc_module::symbol::{Interns, Symbol}; use roc_packaging::cache::{self, RocCacheDir}; use roc_parse::ident::{parse_ident, Accessor, Ident}; +use roc_parse::keyword; use roc_parse::state::State; use roc_region::all::Region; use std::fs; @@ -260,7 +261,13 @@ fn render_module_documentation( let type_ann = &doc_def.type_annotation; if !matches!(type_ann, TypeAnnotation::NoTypeAnn) { - content.push_str(" : "); + // Ability declarations don't have ":" after the name, just `implements` + if !matches!(type_ann, TypeAnnotation::Ability { .. }) { + content.push_str(" :"); + } + + content.push(' '); + type_annotation_to_html(0, &mut content, type_ann, false); } @@ -626,6 +633,7 @@ fn type_annotation_to_html( TypeAnnotation::Function { args, output } => { let mut paren_is_open = false; let mut peekable_args = args.iter().peekable(); + while let Some(arg) = peekable_args.next() { if is_multiline { if !should_be_multiline(arg) { @@ -638,8 +646,7 @@ fn type_annotation_to_html( paren_is_open = true; } - let child_needs_parens = - matches!(arg, TypeAnnotation::Function { args: _, output: _ }); + let child_needs_parens = matches!(arg, TypeAnnotation::Function { .. }); type_annotation_to_html(indent_level, buf, arg, child_needs_parens); if peekable_args.peek().is_some() { @@ -650,9 +657,11 @@ fn type_annotation_to_html( if is_multiline { new_line(buf); indent(buf, indent_level + 1); + } else { + buf.push(' '); } - buf.push_str(" -> "); + buf.push_str("-> "); let mut next_indent_level = indent_level; @@ -665,8 +674,54 @@ fn type_annotation_to_html( buf.push(')'); } } - TypeAnnotation::Ability { members: _ } => { - // TODO(abilities): fill me in + TypeAnnotation::Ability { members } => { + buf.push_str(keyword::IMPLEMENTS); + + for member in members { + new_line(buf); + indent(buf, indent_level + 1); + + // TODO use member.docs somehow. This doesn't look good though: + // if let Some(docs) = &member.docs { + // buf.push_str("## "); + // buf.push_str(docs); + + // new_line(buf); + // indent(buf, indent_level + 1); + // } + + buf.push_str(&member.name); + buf.push_str(" : "); + + type_annotation_to_html(indent_level + 1, buf, &member.type_annotation, false); + + if !member.able_variables.is_empty() { + new_line(buf); + indent(buf, indent_level + 2); + buf.push_str(keyword::WHERE); + + for (index, (name, type_anns)) in member.able_variables.iter().enumerate() { + if index != 0 { + buf.push(','); + } + + buf.push(' '); + buf.push_str(name); + buf.push(' '); + buf.push_str(keyword::IMPLEMENTS); + + for (index, ann) in type_anns.iter().enumerate() { + if index != 0 { + buf.push_str(" &"); + } + + buf.push(' '); + + type_annotation_to_html(indent_level + 2, buf, ann, false); + } + } + } + } } TypeAnnotation::ObscuredTagUnion => { buf.push_str("[@..]"); @@ -676,77 +731,146 @@ fn type_annotation_to_html( } TypeAnnotation::NoTypeAnn => {} TypeAnnotation::Wildcard => buf.push('*'), + TypeAnnotation::Tuple { elems, extension } => { + let elems_len = elems.len(); + let tuple_indent = indent_level + 1; + + if is_multiline { + new_line(buf); + indent(buf, tuple_indent); + } + + buf.push('('); + + if is_multiline { + new_line(buf); + } + + let next_indent_level = tuple_indent + 1; + + for (index, elem) in elems.iter().enumerate() { + if is_multiline { + indent(buf, next_indent_level); + } + + type_annotation_to_html(next_indent_level, buf, elem, false); + + if is_multiline { + if index < (elems_len - 1) { + buf.push(','); + } + + new_line(buf); + } + } + + if is_multiline { + indent(buf, tuple_indent); + } + + buf.push(')'); + + type_annotation_to_html(indent_level, buf, extension, true); + } + TypeAnnotation::Where { ann, implements } => { + type_annotation_to_html(indent_level, buf, ann, false); + + new_line(buf); + indent(buf, indent_level + 1); + + buf.push_str(keyword::WHERE); + + let multiline_implements = implements + .iter() + .any(|imp| imp.abilities.iter().any(should_be_multiline)); + + for (index, imp) in implements.iter().enumerate() { + if index != 0 { + buf.push(','); + } + + if multiline_implements { + new_line(buf); + indent(buf, indent_level + 2); + } else { + buf.push(' ') + } + + buf.push_str(&imp.name); + buf.push(' '); + buf.push_str(keyword::IMPLEMENTS); + buf.push(' '); + + for (index, ability) in imp.abilities.iter().enumerate() { + if index != 0 { + buf.push_str(" & "); + } + + type_annotation_to_html(indent_level, buf, ability, false); + } + } + } + TypeAnnotation::As { ann, name, vars } => { + type_annotation_to_html(indent_level, buf, ann, true); + buf.push(' '); + buf.push_str(name); + + for var in vars { + buf.push(' '); + buf.push_str(var); + } + } } } fn should_be_multiline(type_ann: &TypeAnnotation) -> bool { match type_ann { TypeAnnotation::TagUnion { tags, extension } => { - let mut is_multiline = should_be_multiline(extension) || tags.len() > 1; - - for tag in tags { - for value in &tag.values { - if is_multiline { - break; - } - is_multiline = should_be_multiline(value); - } - } - - is_multiline + tags.len() > 1 + || should_be_multiline(extension) + || tags + .iter() + .any(|tag| tag.values.iter().any(should_be_multiline)) } TypeAnnotation::Function { args, output } => { - let mut is_multiline = should_be_multiline(output) || args.len() > 2; - - for arg in args { - if is_multiline { - break; - } - - is_multiline = should_be_multiline(arg); - } - - is_multiline + args.len() > 2 || should_be_multiline(output) || args.iter().any(should_be_multiline) } TypeAnnotation::ObscuredTagUnion => false, TypeAnnotation::ObscuredRecord => false, TypeAnnotation::BoundVariable(_) => false, - TypeAnnotation::Apply { parts, .. } => { - let mut is_multiline = false; - - for part in parts { - is_multiline = should_be_multiline(part); - - if is_multiline { - break; - } - } - - is_multiline - } + TypeAnnotation::Apply { parts, .. } => parts.iter().any(should_be_multiline), TypeAnnotation::Record { fields, extension } => { - let mut is_multiline = should_be_multiline(extension) || fields.len() > 1; - - for field in fields { - if is_multiline { - break; - } - match field { + fields.len() > 1 + || should_be_multiline(extension) + || fields.iter().any(|field| match field { RecordField::RecordField { type_annotation, .. - } => is_multiline = should_be_multiline(type_annotation), + } => should_be_multiline(type_annotation), RecordField::OptionalField { type_annotation, .. - } => is_multiline = should_be_multiline(type_annotation), - RecordField::LabelOnly { .. } => {} - } - } - - is_multiline + } => should_be_multiline(type_annotation), + RecordField::LabelOnly { .. } => false, + }) } TypeAnnotation::Ability { .. } => true, TypeAnnotation::Wildcard => false, TypeAnnotation::NoTypeAnn => false, + TypeAnnotation::Tuple { elems, extension } => { + elems.len() > 1 + || should_be_multiline(extension) + || elems.iter().any(should_be_multiline) + } + TypeAnnotation::Where { ann, implements } => { + should_be_multiline(ann) + || implements + .iter() + .any(|imp| imp.abilities.iter().any(should_be_multiline)) + } + TypeAnnotation::As { + ann, + name: _, + vars: _, + } => should_be_multiline(ann), } } diff --git a/crates/glue/platform/Types.roc b/crates/glue/platform/Types.roc index 9d2f4d3819..eca34dc9fc 100644 --- a/crates/glue/platform/Types.roc +++ b/crates/glue/platform/Types.roc @@ -33,11 +33,10 @@ entryPoints = \@Types { entrypoints } -> entrypoints walkShapes : Types, state, (state, Shape, TypeId -> state) -> state walkShapes = \@Types { types: shapes }, originalState, update -> - List.walk shapes { index: 0, state: originalState } \{ index, state }, elem -> + List.walkWithIndex shapes originalState \state, elem, index -> id = InternalTypeId.fromNat index - { index: index + 1, state: update state elem id } - |> .state + update state elem id shape : Types, TypeId -> Shape shape = \@Types types, id -> diff --git a/crates/glue/src/RustGlue.roc b/crates/glue/src/RustGlue.roc index 482e3a9047..5b3c1123bb 100644 --- a/crates/glue/src/RustGlue.roc +++ b/crates/glue/src/RustGlue.roc @@ -1,7 +1,10 @@ app "rust-glue" packages { pf: "../platform/main.roc" } imports [ - pf.Types.{ Types }, pf.Shape.{ Shape, RocFn }, pf.File.{ File }, pf.TypeId.{ TypeId }, + pf.Types.{ Types }, + pf.Shape.{ Shape, RocFn }, + pf.File.{ File }, + pf.TypeId.{ TypeId }, "../static/Cargo.toml" as rocAppCargoToml : Str, "../../roc_std/Cargo.toml" as rocStdCargoToml : Str, "../../roc_std/src/lib.rs" as rocStdLib : Str, @@ -39,18 +42,17 @@ makeGlue = \typesByArch -> ## These are always included, and don't depend on the specifics of the app. staticFiles : List File -staticFiles = - [ - { name: "roc_app/Cargo.toml", content: rocAppCargoToml }, - { name: "roc_std/Cargo.toml", content: rocStdCargoToml }, - { name: "roc_std/src/lib.rs", content: rocStdLib }, - { name: "roc_std/src/roc_box.rs", content: rocStdBox }, - { name: "roc_std/src/roc_list.rs", content: rocStdList }, - { name: "roc_std/src/roc_dict.rs", content: rocStdDict }, - { name: "roc_std/src/roc_set.rs", content: rocStdSet }, - { name: "roc_std/src/roc_str.rs", content: rocStdStr }, - { name: "roc_std/src/storage.rs", content: rocStdStorage }, - ] +staticFiles = [ + { name: "roc_app/Cargo.toml", content: rocAppCargoToml }, + { name: "roc_std/Cargo.toml", content: rocStdCargoToml }, + { name: "roc_std/src/lib.rs", content: rocStdLib }, + { name: "roc_std/src/roc_box.rs", content: rocStdBox }, + { name: "roc_std/src/roc_list.rs", content: rocStdList }, + { name: "roc_std/src/roc_dict.rs", content: rocStdDict }, + { name: "roc_std/src/roc_set.rs", content: rocStdSet }, + { name: "roc_std/src/roc_str.rs", content: rocStdStr }, + { name: "roc_std/src/storage.rs", content: rocStdStorage }, +] convertTypesToFile : Types -> File convertTypesToFile = \types -> @@ -339,7 +341,7 @@ generateEnumeration = \buf, types, enumType, name, tags, tagBytes -> buf |> generateDeriveStr types enumType ExcludeDebug |> Str.concat "#[repr(u\(reprBits))]\npub enum \(escapedName) {\n" - |> \b -> walkWithIndex tags b generateEnumTags + |> \b -> List.walkWithIndex tags b generateEnumTags |> # Enums require a custom debug impl to ensure naming is identical on all platforms. Str.concat @@ -354,7 +356,7 @@ generateEnumeration = \buf, types, enumType, name, tags, tagBytes -> |> \b -> List.walk tags b (generateEnumTagsDebug name) |> Str.concat "\(indent)\(indent)}\n\(indent)}\n}\n\n" -generateEnumTags = \accum, index, name -> +generateEnumTags = \accum, name, index -> indexStr = Num.toStr index Str.concat accum "\(indent)\(name) = \(indexStr),\n" @@ -426,107 +428,122 @@ deriveDebugTagUnion = \buf, types, tagUnionType, tags -> } """ -deriveEqTagUnion : Str, Str -> Str -deriveEqTagUnion = \buf, tagUnionType -> - """ - \(buf) +deriveEqTagUnion : Str, Types, Shape, Str -> Str +deriveEqTagUnion = \buf, types, shape, tagUnionType -> + if canSupportEqHashOrd types shape then + """ + \(buf) - impl Eq for \(tagUnionType) {} - """ + impl Eq for \(tagUnionType) {} + """ + else + buf -derivePartialEqTagUnion : Str, Str, List { name : Str, payload : [Some TypeId, None] } -> Str -derivePartialEqTagUnion = \buf, tagUnionType, tags -> - checks = - List.walk tags "" \accum, { name: tagName } -> - """ - \(accum) - \(tagName) => self.payload.\(tagName) == other.payload.\(tagName), - """ +derivePartialEqTagUnion : Str, Types, Shape, Str, List { name : Str, payload : [Some TypeId, None] } -> Str +derivePartialEqTagUnion = \buf, types, shape, tagUnionType, tags -> + if canSupportPartialEqOrd types shape then + checks = + List.walk tags "" \accum, { name: tagName } -> + """ + \(accum) + \(tagName) => self.payload.\(tagName) == other.payload.\(tagName), + """ - """ - \(buf) + """ + \(buf) - impl PartialEq for \(tagUnionType) { - fn eq(&self, other: &Self) -> bool { - use discriminant_\(tagUnionType)::*; + impl PartialEq for \(tagUnionType) { + fn eq(&self, other: &Self) -> bool { + use discriminant_\(tagUnionType)::*; - if self.discriminant != other.discriminant { - return false; - } - - unsafe { - match self.discriminant {\(checks) + if self.discriminant != other.discriminant { + return false; } - } - } - } - """ -deriveOrdTagUnion : Str, Str -> Str -deriveOrdTagUnion = \buf, tagUnionType -> - """ - \(buf) - - impl Ord for \(tagUnionType) { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.partial_cmp(other).unwrap() - } - } - """ - -derivePartialOrdTagUnion : Str, Str, List { name : Str, payload : [Some TypeId, None] } -> Str -derivePartialOrdTagUnion = \buf, tagUnionType, tags -> - checks = - List.walk tags "" \accum, { name: tagName } -> - """ - \(accum) - \(tagName) => self.payload.\(tagName).partial_cmp(&other.payload.\(tagName)), - """ - - """ - \(buf) - - impl PartialOrd for \(tagUnionType) { - fn partial_cmp(&self, other: &Self) -> Option { - use discriminant_\(tagUnionType)::*; - - use std::cmp::Ordering::*; - - match self.discriminant.cmp(&other.discriminant) { - Less => Option::Some(Less), - Greater => Option::Some(Greater), - Equal => unsafe { + unsafe { match self.discriminant {\(checks) } - }, - } - } - } - """ - -deriveHashTagUnion : Str, Str, List { name : Str, payload : [Some TypeId, None] } -> Str -deriveHashTagUnion = \buf, tagUnionType, tags -> - checks = - List.walk tags "" \accum, { name: tagName } -> - """ - \(accum) - \(tagName) => self.payload.\(tagName).hash(state), - """ - - """ - \(buf) - - impl core::hash::Hash for \(tagUnionType) { - fn hash(&self, state: &mut H) { - use discriminant_\(tagUnionType)::*; - - unsafe { - match self.discriminant {\(checks) } } } - } - """ + """ + else + buf + +deriveOrdTagUnion : Str, Types, Shape, Str -> Str +deriveOrdTagUnion = \buf, types, shape, tagUnionType -> + if canSupportEqHashOrd types shape then + """ + \(buf) + + impl Ord for \(tagUnionType) { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.partial_cmp(other).unwrap() + } + } + """ + else + buf + +derivePartialOrdTagUnion : Str, Types, Shape, Str, List { name : Str, payload : [Some TypeId, None] } -> Str +derivePartialOrdTagUnion = \buf, types, shape, tagUnionType, tags -> + if canSupportPartialEqOrd types shape then + checks = + List.walk tags "" \accum, { name: tagName } -> + """ + \(accum) + \(tagName) => self.payload.\(tagName).partial_cmp(&other.payload.\(tagName)), + """ + + """ + \(buf) + + impl PartialOrd for \(tagUnionType) { + fn partial_cmp(&self, other: &Self) -> Option { + use discriminant_\(tagUnionType)::*; + + use std::cmp::Ordering::*; + + match self.discriminant.cmp(&other.discriminant) { + Less => Option::Some(Less), + Greater => Option::Some(Greater), + Equal => unsafe { + match self.discriminant {\(checks) + } + }, + } + } + } + """ + else + buf + +deriveHashTagUnion : Str, Types, Shape, Str, List { name : Str, payload : [Some TypeId, None] } -> Str +deriveHashTagUnion = \buf, types, shape, tagUnionType, tags -> + if canSupportEqHashOrd types shape then + checks = + List.walk tags "" \accum, { name: tagName } -> + """ + \(accum) + \(tagName) => self.payload.\(tagName).hash(state), + """ + + """ + \(buf) + + impl core::hash::Hash for \(tagUnionType) { + fn hash(&self, state: &mut H) { + use discriminant_\(tagUnionType)::*; + + unsafe { + match self.discriminant {\(checks) + } + } + } + } + """ + else + buf generateConstructorFunctions : Str, Types, Str, List { name : Str, payload : [Some TypeId, None] } -> Str generateConstructorFunctions = \buf, types, tagUnionType, tags -> @@ -646,6 +663,7 @@ generateNonRecursiveTagUnion = \buf, types, id, name, tags, discriminantSize, di sizeOfSelf = Num.toStr (Types.size types id) alignOfSelf = Num.toStr (Types.alignment types id) + shape = Types.shape types id # TODO: this value can be different than the alignment of `id` align = @@ -701,16 +719,16 @@ generateNonRecursiveTagUnion = \buf, types, id, name, tags, discriminantSize, di """ |> deriveCloneTagUnion escapedName tags |> deriveDebugTagUnion types escapedName tags - |> deriveEqTagUnion escapedName - |> derivePartialEqTagUnion escapedName tags - |> deriveOrdTagUnion escapedName - |> derivePartialOrdTagUnion escapedName tags - |> deriveHashTagUnion escapedName tags + |> deriveEqTagUnion types shape escapedName + |> derivePartialEqTagUnion types shape escapedName tags + |> deriveOrdTagUnion types shape escapedName + |> derivePartialOrdTagUnion types shape escapedName tags + |> deriveHashTagUnion types shape escapedName tags |> generateDestructorFunctions types escapedName tags |> generateConstructorFunctions types escapedName tags |> \b -> type = Types.shape types id - if cannotDeriveCopy types type then + if cannotSupportCopy types type then # A custom drop impl is only needed when we can't derive copy. b |> Str.concat @@ -829,6 +847,32 @@ generateRecursiveTagUnion = \buf, types, id, tagUnionName, tags, discriminantSiz None -> [] + fieldGetters = + List.walk payloadFields { i: 0, accum: "" } \{ i, accum }, fieldTypeId -> + fieldTypeName = typeName types fieldTypeId + fieldIndex = Num.toStr i + + { + i: i + 1, + accum: + """ + \(accum) + pub fn get_\(tagName)_f\(fieldIndex)(&self) -> &\(fieldTypeName) { + debug_assert!(self.is_\(tagName)()); + + // extern "C" { + // fn foobar(tag_id: u16, field_index: usize) -> usize; + // } + + // let offset = unsafe { foobar(\(fieldIndex)) }; + let offset = 0; + unsafe { &*self.unmasked_pointer().add(offset).cast() } + } + + """, + } + |> .accum + payloadFieldNames = commaSeparated "" payloadFields \_, i -> n = Num.toStr i @@ -880,6 +924,7 @@ generateRecursiveTagUnion = \buf, types, id, tagUnionName, tags, discriminantSiz Self((ptr as usize | tag_id as usize) as *mut _) } + \(fieldGetters) pub fn get_\(tagName)(mut self) -> \(escapedName)_\(tagName) { debug_assert!(self.is_\(tagName)()); @@ -942,7 +987,7 @@ generateRecursiveTagUnion = \buf, types, id, tagUnionName, tags, discriminantSiz |> Str.joinWith "\n" partialEqImpl = - if canDerivePartialEq types (Types.shape types id) then + if canSupportPartialEqOrd types (Types.shape types id) then """ impl PartialEq for \(escapedName) { fn eq(&self, other: &Self) -> bool { @@ -1024,10 +1069,8 @@ generateRecursiveTagUnion = \buf, types, id, tagUnionName, tags, discriminantSiz |> List.mapWithIndex hashCase |> Str.joinWith "\n" - - hashImpl = - if canDerivePartialEq types (Types.shape types id) then + if canSupportPartialEqOrd types (Types.shape types id) then """ impl core::hash::Hash for \(escapedName) { fn hash(&self, state: &mut H) { @@ -1067,7 +1110,7 @@ generateRecursiveTagUnion = \buf, types, id, tagUnionName, tags, discriminantSiz |> Str.joinWith "\n" partialOrdImpl = - if canDerivePartialEq types (Types.shape types id) then + if canSupportPartialEqOrd types (Types.shape types id) then """ impl PartialOrd for \(escapedName) { fn partial_cmp(&self, other: &Self) -> Option { @@ -1128,7 +1171,7 @@ generateRecursiveTagUnion = \buf, types, id, tagUnionName, tags, discriminantSiz } } - unsafe fn ptr_read_union(&self) -> core::mem::ManuallyDrop { + fn unmasked_pointer(&self) -> *mut union_\(escapedName) { debug_assert!(!self.0.is_null()); let mask = match std::mem::size_of::() { @@ -1137,7 +1180,11 @@ generateRecursiveTagUnion = \buf, types, id, tagUnionName, tags, discriminantSiz _ => unreachable!(), }; - let ptr = ((self.0 as usize) & mask) as *mut union_\(escapedName); + ((self.0 as usize) & mask) as *mut union_\(escapedName) + } + + unsafe fn ptr_read_union(&self) -> core::mem::ManuallyDrop { + let ptr = self.unmasked_pointer(); core::mem::ManuallyDrop::new(unsafe { std::ptr::read(ptr) }) } @@ -1198,7 +1245,7 @@ generateTagUnionDropPayload = \buf, types, selfMut, tags, discriminantName, disc buf |> writeTagImpls tags discriminantName indents \name, payload -> when payload is - Some id if cannotDeriveCopy types (Types.shape types id) -> + Some id if cannotSupportCopy types (Types.shape types id) -> "unsafe { core::mem::ManuallyDrop::drop(&mut \(selfMut).payload.\(name)) }," _ -> @@ -1272,7 +1319,7 @@ generateUnionField = \types -> type = Types.shape types id fullTypeStr = - if cannotDeriveCopy types type then + if cannotSupportCopy types type then # types with pointers need ManuallyDrop # because rust unions don't (and can't) # know how to drop them automatically! @@ -1673,54 +1720,58 @@ generateDeriveStr = \buf, types, type, includeDebug -> buf |> Str.concat "#[derive(Clone, " - |> condWrite (!(cannotDeriveCopy types type)) "Copy, " - |> condWrite (!(cannotDeriveDefault types type)) "Default, " + |> condWrite (!(cannotSupportCopy types type)) "Copy, " + |> condWrite (!(cannotSupportDefault types type)) "Default, " |> condWrite deriveDebug "Debug, " - |> condWrite (canDerivePartialEq types type) "PartialEq, PartialOrd, " - |> condWrite (!(hasFloat types type) && (canDerivePartialEq types type)) "Eq, Ord, Hash, " + |> condWrite (canSupportPartialEqOrd types type) "PartialEq, PartialOrd, " + |> condWrite (canSupportEqHashOrd types type) "Eq, Ord, Hash, " |> Str.concat ")]\n" -canDerivePartialEq : Types, Shape -> Bool -canDerivePartialEq = \types, type -> +canSupportEqHashOrd : Types, Shape -> Bool +canSupportEqHashOrd = \types, type -> + !(hasFloat types type) && (canSupportPartialEqOrd types type) + +canSupportPartialEqOrd : Types, Shape -> Bool +canSupportPartialEqOrd = \types, type -> when type is Function rocFn -> runtimeRepresentation = Types.shape types rocFn.lambdaSet - canDerivePartialEq types runtimeRepresentation + canSupportPartialEqOrd types runtimeRepresentation Unsized -> Bool.false Unit | EmptyTagUnion | Bool | Num _ | TagUnion (Enumeration _) -> Bool.true RocStr -> Bool.true RocList inner | RocSet inner | RocBox inner -> innerType = Types.shape types inner - canDerivePartialEq types innerType + canSupportPartialEqOrd types innerType RocDict k v -> kType = Types.shape types k vType = Types.shape types v - canDerivePartialEq types kType && canDerivePartialEq types vType + canSupportPartialEqOrd types kType && canSupportPartialEqOrd types vType TagUnion (Recursive { tags }) -> List.all tags \{ payload } -> when payload is None -> Bool.true - Some id -> canDerivePartialEq types (Types.shape types id) + Some id -> canSupportPartialEqOrd types (Types.shape types id) TagUnion (NullableWrapped { tags }) -> List.all tags \{ payload } -> when payload is None -> Bool.true - Some id -> canDerivePartialEq types (Types.shape types id) + Some id -> canSupportPartialEqOrd types (Types.shape types id) TagUnion (NonNullableUnwrapped { payload }) -> - canDerivePartialEq types (Types.shape types payload) + canSupportPartialEqOrd types (Types.shape types payload) TagUnion (NullableUnwrapped { nonNullPayload }) -> - canDerivePartialEq types (Types.shape types nonNullPayload) + canSupportPartialEqOrd types (Types.shape types nonNullPayload) RecursivePointer _ -> Bool.true TagUnion (SingleTagStruct { payload: HasNoClosure fields }) -> - List.all fields \{ id } -> canDerivePartialEq types (Types.shape types id) + List.all fields \{ id } -> canSupportPartialEqOrd types (Types.shape types id) TagUnion (SingleTagStruct { payload: HasClosure _ }) -> Bool.false @@ -1728,23 +1779,23 @@ canDerivePartialEq = \types, type -> TagUnion (NonRecursive { tags }) -> List.all tags \{ payload } -> when payload is - Some id -> canDerivePartialEq types (Types.shape types id) + Some id -> canSupportPartialEqOrd types (Types.shape types id) None -> Bool.true RocResult okId errId -> okShape = Types.shape types okId errShape = Types.shape types errId - canDerivePartialEq types okShape && canDerivePartialEq types errShape + canSupportPartialEqOrd types okShape && canSupportPartialEqOrd types errShape Struct { fields: HasNoClosure fields } | TagUnionPayload { fields: HasNoClosure fields } -> - List.all fields \{ id } -> canDerivePartialEq types (Types.shape types id) + List.all fields \{ id } -> canSupportPartialEqOrd types (Types.shape types id) Struct { fields: HasClosure fields } | TagUnionPayload { fields: HasClosure fields } -> - List.all fields \{ id } -> canDerivePartialEq types (Types.shape types id) + List.all fields \{ id } -> canSupportPartialEqOrd types (Types.shape types id) -cannotDeriveCopy : Types, Shape -> Bool -cannotDeriveCopy = \types, type -> +cannotSupportCopy : Types, Shape -> Bool +cannotSupportCopy = \types, type -> !(canDeriveCopy types type) canDeriveCopy : Types, Shape -> Bool @@ -1780,22 +1831,21 @@ canDeriveCopy = \types, type -> Struct { fields: HasClosure fields } | TagUnionPayload { fields: HasClosure fields } -> List.all fields \{ id } -> canDeriveCopy types (Types.shape types id) -cannotDeriveDefault = \types, type -> +cannotSupportDefault = \types, type -> when type is Unit | Unsized | EmptyTagUnion | TagUnion _ | RocResult _ _ | RecursivePointer _ | Function _ -> Bool.true - RocStr | Bool | Num _ -> Bool.false + RocStr | Bool | Num _ -> Bool.false RocList id | RocSet id | RocBox id -> - cannotDeriveDefault types (Types.shape types id) + cannotSupportDefault types (Types.shape types id) TagUnionPayload { fields: HasClosure _ } -> Bool.true - RocDict keyId valId -> - cannotDeriveCopy types (Types.shape types keyId) - || cannotDeriveCopy types (Types.shape types valId) + cannotSupportCopy types (Types.shape types keyId) + || cannotSupportCopy types (Types.shape types valId) Struct { fields: HasClosure _ } -> Bool.true Struct { fields: HasNoClosure fields } | TagUnionPayload { fields: HasNoClosure fields } -> - List.any fields \{ id } -> cannotDeriveDefault types (Types.shape types id) + List.any fields \{ id } -> cannotSupportDefault types (Types.shape types id) hasFloat = \types, type -> hasFloatHelp types type (Set.empty {}) @@ -1949,15 +1999,6 @@ roundUpToAlignment = \width, alignment -> else width -walkWithIndex = \list, originalState, f -> - stateWithId = - List.walk list { id: 0nat, state: originalState } \{ id, state }, elem -> - nextState = f state id elem - - { id: id + 1, state: nextState } - - stateWithId.state - archName = \arch -> when arch is Aarch32 -> @@ -2070,7 +2111,6 @@ nextMultipleOf = \lhs, rhs -> 0 -> lhs r -> lhs + (rhs - r) - isUnit : Shape -> Bool isUnit = \shape -> when shape is @@ -2079,23 +2119,18 @@ isUnit = \shape -> toArgStr : List TypeId, Types, (TypeId, Shape, Nat -> Str) -> Str toArgStr = \args, types, fmt -> - answer = List.walk args { state: "", index: 0 } \{ state, index }, argId -> - newState = - shape = Types.shape types argId + List.walkWithIndex args "" \state, argId, index -> + shape = Types.shape types argId - # Drop `()` args; they aren't FFI-safe, and nothing will get passed anyway. - if isUnit shape then - state + # Drop `()` args; they aren't FFI-safe, and nothing will get passed anyway. + if isUnit shape then + state + else + argStr = fmt argId shape index + + if Str.isEmpty state then + argStr # Don't prepend a comma if this is the first one else - argStr = fmt argId shape index - - if Str.isEmpty state then - argStr # Don't prepend a comma if this is the first one - else - state - |> Str.concat ", " - |> Str.concat argStr - - { state: newState, index: index + 1 } - - answer.state + state + |> Str.concat ", " + |> Str.concat argStr diff --git a/crates/glue/src/types.rs b/crates/glue/src/types.rs index d1580b123d..2a030f4203 100644 --- a/crates/glue/src/types.rs +++ b/crates/glue/src/types.rs @@ -111,8 +111,7 @@ impl Types { target, ); - let variables: Vec<_> = entry_points.values().copied().collect(); - for var in variables { + for (_symbol, var) in entry_points.clone() { env.lambda_set_ids = env.find_lambda_sets(var); let id = env.add_toplevel_type(var, &mut types); @@ -1223,8 +1222,7 @@ impl<'a> Env<'a> { } fn find_lambda_sets(&self, root: Variable) -> MutMap { - let stack = bumpalo::vec![in self.arena; root]; - roc_mono::ir::find_lambda_sets_help(self.subs, stack) + roc_mono::ir::find_lambda_sets(self.arena, self.subs, root) } fn add_toplevel_type(&mut self, var: Variable, types: &mut Types) -> TypeId { @@ -1268,8 +1266,13 @@ fn add_function_type<'a>( let name = format!("RocFunction_{closure_var:?}"); - let id = env.lambda_set_ids.get(&closure_var).unwrap(); - let extern_name = format!("roc__mainForHost_{}_caller", id.0); + let extern_name = match env.lambda_set_ids.get(&closure_var) { + Some(id) => format!("roc__mainForHost_{}_caller", id.0), + None => { + debug_assert!(is_toplevel); + String::from("this_extern_should_not_be_used_this_is_a_bug") + } + }; for arg_var in args { let arg_layout = env diff --git a/crates/linker/src/pe.rs b/crates/linker/src/pe.rs index 34a9f29514..6a3831f464 100644 --- a/crates/linker/src/pe.rs +++ b/crates/linker/src/pe.rs @@ -1107,11 +1107,15 @@ impl<'a> AppSections<'a> { for (i, section) in file.sections().enumerate() { let kind = match section.name() { - Ok(".text") => SectionKind::Text, - // Ok(".data") => SectionKind::Data, - Ok(".rdata") => SectionKind::ReadOnlyData, - - _ => continue, + Ok(name) => { + match name { + _ if name.starts_with(".text") => SectionKind::Text, + // _ if name.starts_with(".data") => SectionKind::Data, + _ if name.starts_with(".rdata") => SectionKind::ReadOnlyData, + _ => continue, + } + } + Err(_) => continue, }; let mut relocations: MutMap> = MutMap::default(); diff --git a/crates/repl_cli/src/cli_gen.rs b/crates/repl_cli/src/cli_gen.rs index accd1359d9..0b8c322ca7 100644 --- a/crates/repl_cli/src/cli_gen.rs +++ b/crates/repl_cli/src/cli_gen.rs @@ -199,6 +199,7 @@ fn mono_module_to_dylib<'a>( let MonomorphizedModule { procedures, + host_exposed_lambda_sets, entry_point, interns, subs, @@ -258,6 +259,7 @@ fn mono_module_to_dylib<'a>( &layout_interner, opt_level, procedures, + host_exposed_lambda_sets, entry_point, ); diff --git a/crates/reporting/src/error/canonicalize.rs b/crates/reporting/src/error/canonicalize.rs index 998ed22810..dae48321b9 100644 --- a/crates/reporting/src/error/canonicalize.rs +++ b/crates/reporting/src/error/canonicalize.rs @@ -42,9 +42,9 @@ const OPAQUE_NOT_APPLIED: &str = "OPAQUE TYPE NOT APPLIED"; const OPAQUE_OVER_APPLIED: &str = "OPAQUE TYPE APPLIED TO TOO MANY ARGS"; const INVALID_EXTENSION_TYPE: &str = "INVALID_EXTENSION_TYPE"; const ABILITY_HAS_TYPE_VARIABLES: &str = "ABILITY HAS TYPE VARIABLES"; -const HAS_CLAUSE_IS_NOT_AN_ABILITY: &str = "HAS CLAUSE IS NOT AN ABILITY"; -const ILLEGAL_HAS_CLAUSE: &str = "ILLEGAL HAS CLAUSE"; -const ABILITY_MEMBER_MISSING_HAS_CLAUSE: &str = "ABILITY MEMBER MISSING HAS CLAUSE"; +const IMPLEMENTS_CLAUSE_IS_NOT_AN_ABILITY: &str = "IMPLEMENTS CLAUSE IS NOT AN ABILITY"; +const ILLEGAL_IMPLEMENTS_CLAUSE: &str = "ILLEGAL IMPLEMENTS CLAUSE"; +const ABILITY_MEMBER_MISSING_IMPLEMENTS_CLAUSE: &str = "ABILITY MEMBER MISSING IMPLEMENTS CLAUSE"; const ABILITY_MEMBER_BINDS_MULTIPLE_VARIABLES: &str = "ABILITY MEMBER BINDS MULTIPLE VARIABLES"; const ABILITY_NOT_ON_TOPLEVEL: &str = "ABILITY NOT ON TOP-LEVEL"; const SPECIALIZATION_NOT_ON_TOPLEVEL: &str = "SPECIALIZATION NOT ON TOP-LEVEL"; @@ -642,35 +642,37 @@ pub fn can_problem<'b>( title = ABILITY_HAS_TYPE_VARIABLES.to_string(); } - Problem::HasClauseIsNotAbility { + Problem::ImplementsClauseIsNotAbility { region: clause_region, } => { doc = alloc.stack([ - alloc.reflow(r#"The type referenced in this "has" clause is not an ability:"#), + alloc.reflow( + r#"The type referenced in this "implements" clause is not an ability:"#, + ), alloc.region(lines.convert_region(clause_region)), ]); - title = HAS_CLAUSE_IS_NOT_AN_ABILITY.to_string(); + title = IMPLEMENTS_CLAUSE_IS_NOT_AN_ABILITY.to_string(); } - Problem::IllegalHasClause { region } => { + Problem::IllegalImplementsClause { region } => { doc = alloc.stack([ alloc.concat([ - alloc.reflow("A "), - alloc.keyword("has"), + alloc.reflow("An "), + alloc.keyword(roc_parse::keyword::IMPLEMENTS), alloc.reflow(" clause is not allowed here:"), ]), alloc.region(lines.convert_region(region)), alloc.concat([ - alloc.keyword("has"), + alloc.keyword(roc_parse::keyword::IMPLEMENTS), alloc.reflow( " clauses can only be specified on the top-level type annotations.", ), ]), ]); - title = ILLEGAL_HAS_CLAUSE.to_string(); + title = ILLEGAL_IMPLEMENTS_CLAUSE.to_string(); } - Problem::DuplicateHasAbility { ability, region } => { + Problem::DuplicateImplementsAbility { ability, region } => { doc = alloc.stack([ alloc.concat([ alloc.reflow("I already saw that this type variable is bound to the "), @@ -679,15 +681,15 @@ pub fn can_problem<'b>( ]), alloc.region(lines.convert_region(region)), alloc.concat([ - alloc.reflow("Abilities only need to bound to a type variable once in a "), - alloc.keyword("has"), + alloc.reflow("Abilities only need to bound to a type variable once in an "), + alloc.keyword(roc_parse::keyword::IMPLEMENTS), alloc.reflow(" clause!"), ]), ]); title = "DUPLICATE BOUND ABILITY".to_string(); } - Problem::AbilityMemberMissingHasClause { + Problem::AbilityMemberMissingImplementsClause { member, ability, region, @@ -696,35 +698,35 @@ pub fn can_problem<'b>( alloc.concat([ alloc.reflow("The definition of the ability member "), alloc.symbol_unqualified(member), - alloc.reflow(" does not include a "), - alloc.keyword("has"), + alloc.reflow(" does not include an "), + alloc.keyword(roc_parse::keyword::IMPLEMENTS), alloc.reflow(" clause binding a type variable to the ability "), alloc.symbol_unqualified(ability), alloc.reflow(":"), ]), alloc.region(lines.convert_region(region)), alloc.concat([ - alloc.reflow("Ability members must include a "), - alloc.keyword("has"), + alloc.reflow("Ability members must include an "), + alloc.keyword(roc_parse::keyword::IMPLEMENTS), alloc.reflow(" clause binding a type variable to an ability, like"), ]), alloc.type_block(alloc.concat([ alloc.type_variable("a".into()), alloc.space(), - alloc.keyword("has"), + alloc.keyword(roc_parse::keyword::IMPLEMENTS), alloc.space(), alloc.symbol_unqualified(ability), ])), alloc.concat([alloc .reflow("Otherwise, the function does not need to be part of the ability!")]), ]); - title = ABILITY_MEMBER_MISSING_HAS_CLAUSE.to_string(); + title = ABILITY_MEMBER_MISSING_IMPLEMENTS_CLAUSE.to_string(); } Problem::AbilityMemberMultipleBoundVars { member, ability, - span_has_clauses, + span_implements_clauses: span_has_clauses, mut bound_var_names, } => { doc = alloc.stack([ @@ -772,13 +774,13 @@ pub fn can_problem<'b>( ), alloc .hint("") - .append(alloc.reflow("Perhaps you meant to include a ")) - .append(alloc.keyword("has")) + .append(alloc.reflow("Perhaps you meant to include an ")) + .append(alloc.keyword(roc_parse::keyword::IMPLEMENTS)) .append(alloc.reflow(" annotation, like")), alloc.type_block(alloc.concat([ alloc.type_variable(suggested_var_name), alloc.space(), - alloc.keyword("has"), + alloc.keyword(roc_parse::keyword::IMPLEMENTS), alloc.space(), alloc.symbol_unqualified(ability), ])), @@ -845,7 +847,7 @@ pub fn can_problem<'b>( let hint = if ability.is_builtin() { alloc.hint("").append( alloc.reflow("if you want this implementation to be derived, don't include a record of implementations. For example,") - .append(alloc.type_block(alloc.concat([alloc.type_str("has ["), alloc.symbol_unqualified(ability), alloc.type_str("]")]))) + .append(alloc.type_block(alloc.concat([alloc.type_str(roc_parse::keyword::IMPLEMENTS), alloc.type_str(" ["), alloc.symbol_unqualified(ability), alloc.type_str("]")]))) .append(alloc.reflow(" will attempt to derive ").append(alloc.symbol_unqualified(ability)))) } else { alloc.nil() diff --git a/crates/reporting/src/error/type.rs b/crates/reporting/src/error/type.rs index 44df819731..e9ad9e9552 100644 --- a/crates/reporting/src/error/type.rs +++ b/crates/reporting/src/error/type.rs @@ -373,7 +373,7 @@ fn underivable_hint<'b>( alloc.concat([ alloc.reflow(" or "), alloc.inline_type_block(alloc.concat([ - alloc.keyword("has"), + alloc.keyword(roc_parse::keyword::IMPLEMENTS), alloc.space(), alloc.symbol_qualified(ability), ])), @@ -399,14 +399,15 @@ fn underivable_hint<'b>( Some(alloc.tip().append(alloc.concat([ alloc.reflow("This type variable is not bound to "), alloc.symbol_unqualified(ability), - alloc.reflow(". Consider adding a "), - alloc.keyword("has"), + alloc.reflow(". Consider adding an "), + alloc.keyword(roc_parse::keyword::IMPLEMENTS), alloc.reflow(" clause to bind the type variable, like "), alloc.inline_type_block(alloc.concat([ - alloc.string("| ".to_string()), + alloc.keyword(roc_parse::keyword::WHERE), + alloc.space(), alloc.type_variable(v.clone()), alloc.space(), - alloc.keyword("has"), + alloc.keyword(roc_parse::keyword::IMPLEMENTS), alloc.space(), alloc.symbol_qualified(ability), ])), @@ -2752,10 +2753,16 @@ fn type_with_able_vars<'b>( doc.push(typ); for (i, (var, abilities)) in able.into_iter().enumerate() { - doc.push(alloc.string(if i == 0 { " | " } else { ", " }.to_string())); + if i == 0 { + doc.push(alloc.space()); + doc.push(alloc.keyword(roc_parse::keyword::WHERE)); + } else { + doc.push(alloc.string(",".to_string())); + } + doc.push(alloc.space()); doc.push(alloc.type_variable(var)); doc.push(alloc.space()); - doc.push(alloc.keyword("has")); + doc.push(alloc.keyword(roc_parse::keyword::IMPLEMENTS)); for (i, ability) in abilities.into_sorted_iter().enumerate() { if i > 0 { @@ -4108,21 +4115,21 @@ mod report_text { alloc.text("()") } else { alloc - .text("( ") - .append(alloc.ellipsis().append(alloc.text(" }"))) + .text("(") + .append(alloc.ellipsis().append(alloc.text(")"))) } .append(ext_doc) } else if entries.len() == 1 { // Single-field records get printed on one line; multi-field records get multiple lines alloc - .text("( ") + .text("(") .append(entries.into_iter().next().unwrap()) .append(if fields_omitted == 0 { alloc.text("") } else { alloc.text(", ").append(alloc.ellipsis()) }) - .append(alloc.text(" )")) + .append(alloc.text(")")) .append(ext_doc) } else { let ending = if fields_omitted == 0 { @@ -4135,7 +4142,7 @@ mod report_text { } .append(ext_doc); - // Multi-elem tuple get printed on multiple lines + // Multi-elem tuples get printed on multiple lines alloc.vcat( std::iter::once(alloc.reflow("(")).chain( entries @@ -4465,7 +4472,7 @@ fn type_problem_to_pretty<'b>( .note("") .append(alloc.reflow("The type variable ")) .append(alloc.type_variable(name.clone())) - .append(alloc.reflow(" says it can take on any value that has the ")) + .append(alloc.reflow(" says it can take on any value that implements the ")) .append(list_abilities(alloc, &abilities)) .append(alloc.reflow(".")), alloc.concat([ @@ -4506,11 +4513,13 @@ fn type_problem_to_pretty<'b>( alloc .note("") .append(type_var_doc) - .append(alloc.reflow(" can take on any value that has only the ")) + .append( + alloc.reflow(" can take on any value that implements only the "), + ) .append(list_abilities(alloc, &abilities)) .append(alloc.reflow(".")), alloc.concat([ - alloc.reflow("But, I see that it's also used as if it has the "), + alloc.reflow("But, I see that it's also used as if it implements the "), list_abilities(alloc, &extra_abilities), alloc.reflow(". Can you use "), alloc.type_variable(name.clone()), @@ -4527,7 +4536,7 @@ fn type_problem_to_pretty<'b>( alloc.reflow("it") }, alloc.reflow(" to the "), - alloc.keyword("has"), + alloc.keyword(roc_parse::keyword::IMPLEMENTS), alloc.reflow(" clause of "), alloc.type_variable(name), alloc.reflow("."), diff --git a/crates/reporting/tests/test_reporting.rs b/crates/reporting/tests/test_reporting.rs index 9146b28cb2..6a65d88a9f 100644 --- a/crates/reporting/tests/test_reporting.rs +++ b/crates/reporting/tests/test_reporting.rs @@ -658,9 +658,9 @@ mod test_reporting { Did you mean one of these? - Str Frac Num + Str Err "### ); @@ -5929,7 +5929,7 @@ In roc, functions are always written as a lambda, like{} r#" app "broken" packages { - pf: "https://github.com/roc-lang/basic-cli/releases/download/0.3.2/tE4xS_zLdmmxmHwHih9kHWQ7fsXtJr7W7h3425-eZFk.tar.br", + pf: "https://github.com/roc-lang/basic-cli/releases/download/0.5.0/Cufzl36_SnJ4QbOoEmiJ5dIpUxBvdB3NEySvuH82Wio.tar.br", } imports [ pf.Stdout, @@ -6506,7 +6506,7 @@ In roc, functions are always written as a lambda, like{} inference_var_conflict_in_rigid_links, indoc!( r#" - f : a -> (_ -> b) | a has Eq + f : a -> (_ -> b) where a implements Eq f = \x -> \y -> if x == y then x else y f "# @@ -6517,17 +6517,17 @@ In roc, functions are always written as a lambda, like{} Something is off with the body of the `f` definition: - 4│ f : a -> (_ -> b) | a has Eq + 4│ f : a -> (_ -> b) where a implements Eq 5│ f = \x -> \y -> if x == y then x else y ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The body is an anonymous function of type: - a -> a | a has Eq, a has Eq + a -> a where a implements Eq, a implements Eq But the type annotation on `f` says it should be: - a -> b | a has Eq + a -> b where a implements Eq Tip: Your type annotation uses `b` and `a` as separate type variables. Your code seems to be saying they are the same though. Maybe they @@ -8201,8 +8201,8 @@ In roc, functions are always written as a lambda, like{} Type Unsigned8 - Unsigned32 Unsigned16 + Unsigned64 ── UNRECOGNIZED NAME ───────────────────────────────────── /code/proj/Main.roc ─ @@ -8215,8 +8215,8 @@ In roc, functions are always written as a lambda, like{} Type Unsigned8 - Unsigned32 Unsigned16 + Unsigned64 "### ); @@ -8224,8 +8224,8 @@ In roc, functions are always written as a lambda, like{} ability_first_demand_not_indented_enough, indoc!( r#" - MEq has - eq : a, a -> U64 | a has MEq + MEq implements + eq : a, a -> U64 where a implements MEq 1 "# @@ -8236,8 +8236,8 @@ In roc, functions are always written as a lambda, like{} I was partway through parsing an ability definition, but I got stuck here: - 4│ MEq has - 5│ eq : a, a -> U64 | a has MEq + 4│ MEq implements + 5│ eq : a, a -> U64 where a implements MEq ^ I suspect this line is not indented enough (by 1 spaces) @@ -8248,9 +8248,9 @@ In roc, functions are always written as a lambda, like{} ability_demands_not_indented_with_first, indoc!( r#" - MEq has - eq : a, a -> U64 | a has MEq - neq : a, a -> U64 | a has MEq + MEq implements + eq : a, a -> U64 where a implements MEq + neq : a, a -> U64 where a implements MEq 1 "# @@ -8261,8 +8261,8 @@ In roc, functions are always written as a lambda, like{} I was partway through parsing an ability definition, but I got stuck here: - 5│ eq : a, a -> U64 | a has MEq - 6│ neq : a, a -> U64 | a has MEq + 5│ eq : a, a -> U64 where a implements MEq + 6│ neq : a, a -> U64 where a implements MEq ^ I suspect this line is indented too much (by 4 spaces)"# @@ -8272,8 +8272,8 @@ In roc, functions are always written as a lambda, like{} ability_demand_value_has_args, indoc!( r#" - MEq has - eq b c : a, a -> U64 | a has MEq + MEq implements + eq b c : a, a -> U64 where a implements MEq 1 "# @@ -8284,8 +8284,8 @@ In roc, functions are always written as a lambda, like{} I was partway through parsing an ability definition, but I got stuck here: - 4│ MEq has - 5│ eq b c : a, a -> U64 | a has MEq + 4│ MEq implements + 5│ eq b c : a, a -> U64 where a implements MEq ^ I was expecting to see a : annotating the signature of this value @@ -8296,7 +8296,7 @@ In roc, functions are always written as a lambda, like{} ability_non_signature_expression, indoc!( r#" - MEq has + MEq implements 123 1 @@ -8308,7 +8308,7 @@ In roc, functions are always written as a lambda, like{} I was partway through parsing an ability definition, but I got stuck here: - 4│ MEq has + 4│ MEq implements 5│ 123 ^ @@ -8434,8 +8434,8 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [] to "./platform" - MHash a b c has - hash : a -> U64 | a has MHash + MHash a b c implements + hash : a -> U64 where a implements MHash "# ), @r###" @@ -8443,7 +8443,7 @@ In roc, functions are always written as a lambda, like{} The definition of the `MHash` ability includes type variables: - 3│ MHash a b c has + 3│ MHash a b c implements ^^^^^ Abilities cannot depend on type variables, but their member values @@ -8453,7 +8453,7 @@ In roc, functions are always written as a lambda, like{} `MHash` is not used anywhere in your code. - 3│ MHash a b c has + 3│ MHash a b c implements ^^^^^ If you didn't intend on using `MHash` then remove it so future readers @@ -8462,21 +8462,21 @@ In roc, functions are always written as a lambda, like{} ); test_report!( - alias_in_has_clause, + alias_in_implements_clause, indoc!( r#" app "test" provides [hash] to "./platform" - MHash has hash : a, b -> Num.U64 | a has MHash, b has Bool.Bool + MHash implements hash : a, b -> Num.U64 where a implements MHash, b implements Bool.Bool "# ), @r###" - ── HAS CLAUSE IS NOT AN ABILITY ────────────────────────── /code/proj/Main.roc ─ + ── IMPLEMENTS CLAUSE IS NOT AN ABILITY ─────────────────── /code/proj/Main.roc ─ - The type referenced in this "has" clause is not an ability: + The type referenced in this "implements" clause is not an ability: - 3│ MHash has hash : a, b -> Num.U64 | a has MHash, b has Bool.Bool - ^^^^^^^^^ + 3│ MHash implements hash : a, b -> Num.U64 where a implements MHash, b implements Bool.Bool + ^^^^^^^^^ "### ); @@ -8486,7 +8486,7 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [ab1] to "./platform" - Ab1 has ab1 : a -> {} | a has Ab1, a has Ab1 + Ab1 implements ab1 : a -> {} where a implements Ab1, a implements Ab1 "# ), @r#" @@ -8494,13 +8494,13 @@ In roc, functions are always written as a lambda, like{} The `a` name is first defined here: - 3│ Ab1 has ab1 : a -> {} | a has Ab1, a has Ab1 - ^^^^^^^^^ + 3│ Ab1 implements ab1 : a -> {} where a implements Ab1, a implements Ab1 + ^^^^^^^^^^^^^^^^ But then it's defined a second time here: - 3│ Ab1 has ab1 : a -> {} | a has Ab1, a has Ab1 - ^^^^^^^^^ + 3│ Ab1 implements ab1 : a -> {} where a implements Ab1, a implements Ab1 + ^^^^^^^^^^^^^^^^ Since these variables have the same name, it's easy to use the wrong one by accident. Give one of them a new name. @@ -8513,9 +8513,9 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [ab] to "./platform" - Ability has ab : a -> U64 | a has Ability + Ability implements ab : a -> U64 where a implements Ability - Ability has ab1 : a -> U64 | a has Ability + Ability implements ab1 : a -> U64 where a implements Ability "# ), @r#" @@ -8523,12 +8523,12 @@ In roc, functions are always written as a lambda, like{} The `Ability` name is first defined here: - 3│ Ability has ab : a -> U64 | a has Ability + 3│ Ability implements ab : a -> U64 where a implements Ability ^^^^^^^ But then it's defined a second time here: - 5│ Ability has ab1 : a -> U64 | a has Ability + 5│ Ability implements ab1 : a -> U64 where a implements Ability ^^^^^^^ Since these abilities have the same name, it's easy to use the wrong @@ -8542,22 +8542,22 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [] to "./platform" - Ability has ab : {} -> {} + Ability implements ab : {} -> {} "# ), @r#" - ── ABILITY MEMBER MISSING HAS CLAUSE ───────────────────── /code/proj/Main.roc ─ + ── ABILITY MEMBER MISSING IMPLEMENTS CLAUSE ────────────── /code/proj/Main.roc ─ - The definition of the ability member `ab` does not include a `has` clause - binding a type variable to the ability `Ability`: + The definition of the ability member `ab` does not include an `implements` + clause binding a type variable to the ability `Ability`: - 3│ Ability has ab : {} -> {} - ^^ + 3│ Ability implements ab : {} -> {} + ^^ - Ability members must include a `has` clause binding a type variable to - an ability, like + Ability members must include an `implements` clause binding a type + variable to an ability, like - a has Ability + a implements Ability Otherwise, the function does not need to be part of the ability! @@ -8565,7 +8565,7 @@ In roc, functions are always written as a lambda, like{} `Ability` is not used anywhere in your code. - 3│ Ability has ab : {} -> {} + 3│ Ability implements ab : {} -> {} ^^^^^^^ If you didn't intend on using `Ability` then remove it so future readers @@ -8579,7 +8579,7 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [] to "./platform" - MEq has eq : a, b -> Bool.Bool | a has MEq, b has MEq + MEq implements eq : a, b -> Bool.Bool where a implements MEq, b implements MEq "# ), @r#" @@ -8588,8 +8588,8 @@ In roc, functions are always written as a lambda, like{} The definition of the ability member `eq` includes multiple variables bound to the `MEq`` ability:` - 3│ MEq has eq : a, b -> Bool.Bool | a has MEq, b has MEq - ^^^^^^^^^^^^^^^^^^^^ + 3│ MEq implements eq : a, b -> Bool.Bool where a implements MEq, b implements MEq + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Ability members can only bind one type variable to their parent ability. Otherwise, I wouldn't know what type implements an ability by @@ -8605,33 +8605,34 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [f] to "./platform" - MHash has hash : (a | a has MHash) -> Num.U64 + MHash implements hash : (a where a implements MHash) -> Num.U64 - f : a -> Num.U64 | a has MHash + f : a -> Num.U64 where a implements MHash "# ), @r###" - ── ILLEGAL HAS CLAUSE ──────────────────────────────────── /code/proj/Main.roc ─ + ── ILLEGAL IMPLEMENTS CLAUSE ───────────────────────────── /code/proj/Main.roc ─ - A `has` clause is not allowed here: + An `implements` clause is not allowed here: - 3│ MHash has hash : (a | a has MHash) -> Num.U64 - ^^^^^^^^^^^ + 3│ MHash implements hash : (a where a implements MHash) -> Num.U64 + ^^^^^^^^^^^^^^^^^^ - `has` clauses can only be specified on the top-level type annotations. + `implements` clauses can only be specified on the top-level type + annotations. - ── ABILITY MEMBER MISSING HAS CLAUSE ───────────────────── /code/proj/Main.roc ─ + ── ABILITY MEMBER MISSING IMPLEMENTS CLAUSE ────────────── /code/proj/Main.roc ─ - The definition of the ability member `hash` does not include a `has` - clause binding a type variable to the ability `MHash`: + The definition of the ability member `hash` does not include an + `implements` clause binding a type variable to the ability `MHash`: - 3│ MHash has hash : (a | a has MHash) -> Num.U64 - ^^^^ + 3│ MHash implements hash : (a where a implements MHash) -> Num.U64 + ^^^^ - Ability members must include a `has` clause binding a type variable to - an ability, like + Ability members must include an `implements` clause binding a type + variable to an ability, like - a has MHash + a implements MHash Otherwise, the function does not need to be part of the ability! "### @@ -8643,9 +8644,9 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [hash] to "./platform" - MHash has hash : a -> U64 | a has MHash + MHash implements hash : a -> U64 where a implements MHash - Id := U32 has [MHash {hash}] + Id := U32 implements [MHash {hash}] hash = \@Id n -> n "# @@ -8674,11 +8675,11 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [eq, le] to "./platform" - MEq has - eq : a, a -> Bool | a has MEq - le : a, a -> Bool | a has MEq + MEq implements + eq : a, a -> Bool where a implements MEq + le : a, a -> Bool where a implements MEq - Id := U64 has [MEq {eq}] + Id := U64 implements [MEq {eq}] eq = \@Id m, @Id n -> m == n "# @@ -8688,8 +8689,8 @@ In roc, functions are always written as a lambda, like{} This type does not fully implement the `MEq` ability: - 7│ Id := U64 has [MEq {eq}] - ^^^^^^^^ + 7│ Id := U64 implements [MEq {eq}] + ^^^^^^^^ The following necessary members are missing implementations: @@ -8703,8 +8704,8 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [hash] to "./platform" - MHash has - hash : a -> U64 | a has MHash + MHash implements + hash : a -> U64 where a implements MHash hash = \_ -> 0u64 "# @@ -8728,11 +8729,11 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [hash, One, Two] to "./platform" - MHash has - hash : a -> U64 | a has MHash + MHash implements + hash : a -> U64 where a implements MHash - One := {} has [MHash {hash}] - Two := {} has [MHash {hash}] + One := {} implements [MHash {hash}] + Two := {} implements [MHash {hash}] hash = \_ -> 0u64 "# @@ -8744,8 +8745,8 @@ In roc, functions are always written as a lambda, like{} This ability member specialization is already claimed to specialize another opaque type: - 7│ Two := {} has [MHash {hash}] - ^^^^ + 7│ Two := {} implements [MHash {hash}] + ^^^^ Previously, we found it to specialize `hash` for `One`. @@ -8765,7 +8766,7 @@ In roc, functions are always written as a lambda, like{} But the type annotation on `hash` says it must match: - a -> U64 | a has MHash + a -> U64 where a implements MHash Note: The specialized type is too general, and does not provide a concrete type where a type variable is bound to an ability. @@ -8782,11 +8783,11 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [hash, One, Two] to "./platform" - MHash has - hash : a -> U64 | a has MHash + MHash implements + hash : a -> U64 where a implements MHash - One := {} has [MHash {hash}] - Two := {} has [MHash {hash}] + One := {} implements [MHash {hash}] + Two := {} implements [MHash {hash}] hash = \@One _ -> 0u64 "# @@ -8797,8 +8798,8 @@ In roc, functions are always written as a lambda, like{} This ability member specialization is already claimed to specialize another opaque type: - 7│ Two := {} has [MHash {hash}] - ^^^^ + 7│ Two := {} implements [MHash {hash}] + ^^^^ Previously, we found it to specialize `hash` for `One`. @@ -8813,10 +8814,10 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [eq] to "./platform" - MEq has - eq : a, a -> Bool | a has MEq + MEq implements + eq : a, a -> Bool where a implements MEq - You := {} has [MEq {eq}] + You := {} implements [MEq {eq}] AndI := {} eq = \@You {}, @AndI {} -> False @@ -8848,10 +8849,10 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [hash] to "./platform" - MHash has - hash : a -> U64 | a has MHash + MHash implements + hash : a -> U64 where a implements MHash - Id := U64 has [MHash {hash}] + Id := U64 implements [MHash {hash}] hash : Id -> U32 hash = \@Id n -> n @@ -8882,10 +8883,10 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [noGoodVeryBadTerrible] to "./platform" - MHash has - hash : a -> U64 | a has MHash + MHash implements + hash : a -> U64 where a implements MHash - Id := U64 has [MHash {hash}] + Id := U64 implements [MHash {hash}] hash = \@Id n -> n @@ -8930,8 +8931,8 @@ In roc, functions are always written as a lambda, like{} app "test" provides [main] to "./platform" main = - MHash has - hash : a -> U64 | a has MHash + MHash implements + hash : a -> U64 where a implements MHash 123 "# @@ -8941,8 +8942,8 @@ In roc, functions are always written as a lambda, like{} This ability definition is not on the top-level of a module: - 4│> MHash has - 5│> hash : a -> U64 | a has MHash + 4│> MHash implements + 5│> hash : a -> U64 where a implements MHash Abilities can only be defined on the top-level of a Roc module. "# @@ -8954,13 +8955,13 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [hash, hashable] to "./platform" - MHash has - hash : a -> U64 | a has MHash + MHash implements + hash : a -> U64 where a implements MHash - Id := U64 has [MHash {hash}] + Id := U64 implements [MHash {hash}] hash = \@Id n -> n - hashable : a | a has MHash + hashable : a where a implements MHash hashable = @Id 15 "# ), @@ -8969,7 +8970,7 @@ In roc, functions are always written as a lambda, like{} Something is off with the body of the `hashable` definition: - 9│ hashable : a | a has MHash + 9│ hashable : a where a implements MHash 10│ hashable = @Id 15 ^^^^^^ @@ -8979,10 +8980,10 @@ In roc, functions are always written as a lambda, like{} But the type annotation on `hashable` says it should be: - a | a has MHash + a where a implements MHash - Note: The type variable `a` says it can take on any value that has the - ability `MHash`. + Note: The type variable `a` says it can take on any value that + implements the ability `MHash`. But, I see that the type is only ever used as a a `Id` value. Can you replace `a` with a more specific type? @@ -8995,16 +8996,16 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [result] to "./platform" - MHash has - hash : a -> U64 | a has MHash + MHash implements + hash : a -> U64 where a implements MHash mulMHashes : MHash, MHash -> U64 mulMHashes = \x, y -> hash x * hash y - Id := U64 has [MHash {hash: hashId}] + Id := U64 implements [MHash {hash: hashId}] hashId = \@Id n -> n - Three := {} has [MHash {hash: hashThree}] + Three := {} implements [MHash {hash: hashThree}] hashThree = \@Three _ -> 3 result = mulMHashes (@Id 100) (@Three {}) @@ -9021,9 +9022,9 @@ In roc, functions are always written as a lambda, like{} Abilities can only be used in type annotations to constrain type variables. - Hint: Perhaps you meant to include a `has` annotation, like + Hint: Perhaps you meant to include an `implements` annotation, like - a has MHash + a implements MHash ── ABILITY USED AS TYPE ────────────────────────────────── /code/proj/Main.roc ─ @@ -9035,9 +9036,9 @@ In roc, functions are always written as a lambda, like{} Abilities can only be used in type annotations to constrain type variables. - Hint: Perhaps you meant to include a `has` annotation, like + Hint: Perhaps you meant to include an `implements` annotation, like - b has MHash + b implements MHash "### ); @@ -9171,10 +9172,10 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [main] to "./platform" - Default has default : {} -> a | a has Default + Default implements default : {} -> a where a implements Default main = - A := {} has [Default {default}] + A := {} implements [Default {default}] default = \{} -> @A {} default {} "# @@ -9379,7 +9380,7 @@ In roc, functions are always written as a lambda, like{} cannot be generated. Tip: `A` does not implement `Encoding`. Consider adding a custom - implementation or `has Encode.Encoding` to the definition of `A`. + implementation or `implements Encode.Encoding` to the definition of `A`. "### ); @@ -9422,9 +9423,9 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [A] to "./platform" - MEq has eq : a, a -> U64 | a has MEq + MEq implements eq : a, a -> U64 where a implements MEq - A := U8 has [MEq {eq}] + A := U8 implements [MEq {eq}] "# ), @r###" @@ -9432,8 +9433,8 @@ In roc, functions are always written as a lambda, like{} An implementation of `eq` could not be found in this scope: - 5│ A := U8 has [MEq {eq}] - ^^ + 5│ A := U8 implements [MEq {eq}] + ^^ Tip: consider adding a value of name `eq` in this scope, or using another variable that implements this ability member, like @@ -9443,8 +9444,8 @@ In roc, functions are always written as a lambda, like{} This type does not fully implement the `MEq` ability: - 5│ A := U8 has [MEq {eq}] - ^^^^^^^^ + 5│ A := U8 implements [MEq {eq}] + ^^^^^^^^ The following necessary members are missing implementations: @@ -9458,9 +9459,9 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [A, myMEq] to "./platform" - MEq has eq : a, a -> Bool | a has MEq + MEq implements eq : a, a -> Bool where a implements MEq - A := U8 has [ MEq {eq: aMEq} ] + A := U8 implements [ MEq {eq: aMEq} ] myMEq = \m, n -> m == n "# @@ -9470,8 +9471,8 @@ In roc, functions are always written as a lambda, like{} Nothing is named `aMEq` in this scope. - 5│ A := U8 has [ MEq {eq: aMEq} ] - ^^^^ + 5│ A := U8 implements [ MEq {eq: aMEq} ] + ^^^^ Did you mean one of these? @@ -9484,8 +9485,8 @@ In roc, functions are always written as a lambda, like{} This type does not fully implement the `MEq` ability: - 5│ A := U8 has [ MEq {eq: aMEq} ] - ^^^^^^^^^^^^^^ + 5│ A := U8 implements [ MEq {eq: aMEq} ] + ^^^^^^^^^^^^^^ The following necessary members are missing implementations: @@ -9499,9 +9500,9 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [A, myMEq] to "./platform" - MEq has eq : a, a -> Bool | a has MEq + MEq implements eq : a, a -> Bool where a implements MEq - A := U8 has [ MEq {eq ? aMEq} ] + A := U8 implements [ MEq {eq ? aMEq} ] myMEq = \m, n -> m == n "# @@ -9511,8 +9512,8 @@ In roc, functions are always written as a lambda, like{} Ability implementations cannot be optional: - 5│ A := U8 has [ MEq {eq ? aMEq} ] - ^^^^^^^^^ + 5│ A := U8 implements [ MEq {eq ? aMEq} ] + ^^^^^^^^^ Custom implementations must be supplied fully. @@ -9522,8 +9523,8 @@ In roc, functions are always written as a lambda, like{} This type does not fully implement the `MEq` ability: - 5│ A := U8 has [ MEq {eq ? aMEq} ] - ^^^^^^^^^^^^^^^ + 5│ A := U8 implements [ MEq {eq ? aMEq} ] + ^^^^^^^^^^^^^^^ The following necessary members are missing implementations: @@ -9539,7 +9540,7 @@ In roc, functions are always written as a lambda, like{} imports [] provides [A, myEncoder] to "./platform" - A := U8 has [ Encoding {toEncoder ? myEncoder} ] + A := U8 implements [ Encoding {toEncoder ? myEncoder} ] myEncoder = 1 "# @@ -9549,21 +9550,21 @@ In roc, functions are always written as a lambda, like{} Ability implementations cannot be optional: - 5│ A := U8 has [ Encoding {toEncoder ? myEncoder} ] - ^^^^^^^^^^^^^^^^^^^^^ + 5│ A := U8 implements [ Encoding {toEncoder ? myEncoder} ] + ^^^^^^^^^^^^^^^^^^^^^ Custom implementations must be supplied fully. Hint: if you want this implementation to be derived, don't include a - record of implementations. For example, has [Encoding] will attempt - to derive `Encoding` + record of implementations. For example, implements [Encoding] will + attempt to derive `Encoding` ── INCOMPLETE ABILITY IMPLEMENTATION ───────────────────── /code/proj/Main.roc ─ This type does not fully implement the `Encoding` ability: - 5│ A := U8 has [ Encoding {toEncoder ? myEncoder} ] - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 5│ A := U8 implements [ Encoding {toEncoder ? myEncoder} ] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The following necessary members are missing implementations: @@ -9577,9 +9578,9 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [A] to "./platform" - MEq has eq : a, a -> Bool | a has MEq + MEq implements eq : a, a -> Bool where a implements MEq - A := U8 has [ MEq {eq : Bool.eq} ] + A := U8 implements [ MEq {eq : Bool.eq} ] "# ), @r###" @@ -9587,8 +9588,8 @@ In roc, functions are always written as a lambda, like{} This ability implementation is qualified: - 5│ A := U8 has [ MEq {eq : Bool.eq} ] - ^^^^^^^ + 5│ A := U8 implements [ MEq {eq : Bool.eq} ] + ^^^^^^^ Custom implementations must be defined in the local scope, and unqualified. @@ -9597,8 +9598,8 @@ In roc, functions are always written as a lambda, like{} This type does not fully implement the `MEq` ability: - 5│ A := U8 has [ MEq {eq : Bool.eq} ] - ^^^^^^^^^^^^^^^^^^ + 5│ A := U8 implements [ MEq {eq : Bool.eq} ] + ^^^^^^^^^^^^^^^^^^ The following necessary members are missing implementations: @@ -9612,9 +9613,9 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [A] to "./platform" - MEq has eq : a, a -> Bool | a has MEq + MEq implements eq : a, a -> Bool where a implements MEq - A := U8 has [ MEq {eq : \m, n -> m == n} ] + A := U8 implements [ MEq {eq : \m, n -> m == n} ] "# ), @r###" @@ -9622,8 +9623,8 @@ In roc, functions are always written as a lambda, like{} This ability implementation is not an identifier: - 5│ A := U8 has [ MEq {eq : \m, n -> m == n} ] - ^^^^^^^^^^^^^^^ + 5│ A := U8 implements [ MEq {eq : \m, n -> m == n} ] + ^^^^^^^^^^^^^^^ Custom ability implementations defined in this position can only be unqualified identifiers, not arbitrary expressions. @@ -9634,8 +9635,8 @@ In roc, functions are always written as a lambda, like{} This type does not fully implement the `MEq` ability: - 5│ A := U8 has [ MEq {eq : \m, n -> m == n} ] - ^^^^^^^^^^^^^^^^^^^^^^^^^^ + 5│ A := U8 implements [ MEq {eq : \m, n -> m == n} ] + ^^^^^^^^^^^^^^^^^^^^^^^^^^ The following necessary members are missing implementations: @@ -9649,9 +9650,9 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [A] to "./platform" - MEq has eq : a, a -> Bool | a has MEq + MEq implements eq : a, a -> Bool where a implements MEq - A := U8 has [ MEq {eq: eqA, eq: eqA} ] + A := U8 implements [ MEq {eq: eqA, eq: eqA} ] eqA = \@A m, @A n -> m == n "# @@ -9661,13 +9662,13 @@ In roc, functions are always written as a lambda, like{} This ability member implementation is duplicate: - 5│ A := U8 has [ MEq {eq: eqA, eq: eqA} ] - ^^^^^^^ + 5│ A := U8 implements [ MEq {eq: eqA, eq: eqA} ] + ^^^^^^^ The first implementation was defined here: - 5│ A := U8 has [ MEq {eq: eqA, eq: eqA} ] - ^^^^^^^ + 5│ A := U8 implements [ MEq {eq: eqA, eq: eqA} ] + ^^^^^^^ Only one custom implementation can be defined for an ability member. "### @@ -9681,7 +9682,7 @@ In roc, functions are always written as a lambda, like{} Foo := {} - A := U8 has [ Foo {} ] + A := U8 implements [ Foo {} ] "# ), @r###" @@ -9689,8 +9690,8 @@ In roc, functions are always written as a lambda, like{} This identifier is not an ability in scope: - 5│ A := U8 has [ Foo {} ] - ^^^ + 5│ A := U8 implements [ Foo {} ] + ^^^ Only abilities can be implemented. "### @@ -9702,9 +9703,9 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [A] to "./platform" - Ab has ab : a -> a | a has Ab + Ab implements ab : a -> a where a implements Ab - A := {} has [Ab] + A := {} implements [Ab] "# ), @r###" @@ -9712,8 +9713,8 @@ In roc, functions are always written as a lambda, like{} This ability cannot be derived: - 5│ A := {} has [Ab] - ^^ + 5│ A := {} implements [Ab] + ^^ Only builtin abilities can be derived. @@ -9727,7 +9728,7 @@ In roc, functions are always written as a lambda, like{} r#" app "test" imports [] provides [A] to "./platform" - A a := a -> a has [Encode.Encoding] + A a := a -> a implements [Encode.Encoding] "# ), @r###" @@ -9735,8 +9736,8 @@ In roc, functions are always written as a lambda, like{} I can't derive an implementation of the `Encoding` ability for `A`: - 3│ A a := a -> a has [Encode.Encoding] - ^^^^^^^^^^^^^^^ + 3│ A a := a -> a implements [Encode.Encoding] + ^^^^^^^^^^^^^^^ Note: `Encoding` cannot be generated for functions. @@ -9750,7 +9751,7 @@ In roc, functions are always written as a lambda, like{} r#" app "test" imports [] provides [A] to "./platform" - A := B has [Encode.Encoding] + A := B implements [Encode.Encoding] B := {} "# @@ -9760,11 +9761,11 @@ In roc, functions are always written as a lambda, like{} I can't derive an implementation of the `Encoding` ability for `A`: - 3│ A := B has [Encode.Encoding] - ^^^^^^^^^^^^^^^ + 3│ A := B implements [Encode.Encoding] + ^^^^^^^^^^^^^^^ Tip: `B` does not implement `Encoding`. Consider adding a custom - implementation or `has Encode.Encoding` to the definition of `B`. + implementation or `implements Encode.Encoding` to the definition of `B`. Tip: You can define a custom implementation of `Encoding` for `A`. "### @@ -9776,9 +9777,9 @@ In roc, functions are always written as a lambda, like{} r#" app "test" imports [] provides [A] to "./platform" - A := B has [Encode.Encoding] + A := B implements [Encode.Encoding] - B := {} has [Encode.Encoding] + B := {} implements [Encode.Encoding] "# ), @"" // no error @@ -9790,7 +9791,7 @@ In roc, functions are always written as a lambda, like{} r#" app "test" imports [] provides [MyNat] to "./platform" - MyNat := [S MyNat, Z] has [Encode.Encoding] + MyNat := [S MyNat, Z] implements [Encode.Encoding] "# ), @"" // no error @@ -9963,9 +9964,9 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [x] to "./platform" - Foo has foo : a -> a | a has Foo + Foo implements foo : a -> a where a implements Foo - F a b := b | a has Foo + F a b := b where a implements Foo MHash := {} @@ -10613,7 +10614,7 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [hash, Id] to "./platform" - MHash has hash : a -> U64 | a has MHash + MHash implements hash : a -> U64 where a implements MHash Id := {} @@ -10639,9 +10640,9 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [hash, Id, Id2] to "./platform" - MHash has hash : a -> U64 | a has MHash + MHash implements hash : a -> U64 where a implements MHash - Id := {} has [MHash {hash}] + Id := {} implements [MHash {hash}] Id2 := {} hash = \@Id2 _ -> 0 @@ -10719,7 +10720,7 @@ In roc, functions are always written as a lambda, like{} r#" app "test" imports [] provides [A] to "./platform" - A a := a -> a has [Decode.Decoding] + A a := a -> a implements [Decode.Decoding] "# ), @r###" @@ -10727,8 +10728,8 @@ In roc, functions are always written as a lambda, like{} I can't derive an implementation of the `Decoding` ability for `A`: - 3│ A a := a -> a has [Decode.Decoding] - ^^^^^^^^^^^^^^^ + 3│ A a := a -> a implements [Decode.Decoding] + ^^^^^^^^^^^^^^^ Note: `Decoding` cannot be generated for functions. @@ -10742,7 +10743,7 @@ In roc, functions are always written as a lambda, like{} r#" app "test" imports [] provides [A] to "./platform" - A := B has [Decode.Decoding] + A := B implements [Decode.Decoding] B := {} "# @@ -10752,13 +10753,14 @@ In roc, functions are always written as a lambda, like{} I can't derive an implementation of the `Decoding` ability for `A`: - 3│ A := B has [Decode.Decoding] - ^^^^^^^^^^^^^^^ + 3│ A := B implements [Decode.Decoding] + ^^^^^^^^^^^^^^^ Tip: `B` does not implement `Decoding`. Consider adding a custom - implementation or `has Decode.Decoding` to the definition of `B`. + implementation or `implements Decode.Decoding` to the definition of `B`. Tip: You can define a custom implementation of `Decoding` for `A`. + "### ); @@ -10768,9 +10770,9 @@ In roc, functions are always written as a lambda, like{} r#" app "test" imports [] provides [A] to "./platform" - A := B has [Decode.Decoding] + A := B implements [Decode.Decoding] - B := {} has [Decode.Decoding] + B := {} implements [Decode.Decoding] "# ), @"" // no error @@ -10782,7 +10784,7 @@ In roc, functions are always written as a lambda, like{} r#" app "test" imports [] provides [MyNat] to "./platform" - MyNat := [S MyNat, Z] has [Decode.Decoding] + MyNat := [S MyNat, Z] implements [Decode.Decoding] "# ), @"" // no error @@ -10795,7 +10797,7 @@ In roc, functions are always written as a lambda, like{} app "test" imports [Decode.{decoder}] provides [main] to "./platform" main = - myDecoder : Decoder (a -> a) fmt | fmt has DecoderFormatting + myDecoder : Decoder (a -> a) fmt where fmt implements DecoderFormatting myDecoder = decoder myDecoder @@ -10826,7 +10828,7 @@ In roc, functions are always written as a lambda, like{} A := {} main = - myDecoder : Decoder {x : A} fmt | fmt has DecoderFormatting + myDecoder : Decoder {x : A} fmt where fmt implements DecoderFormatting myDecoder = decoder myDecoder @@ -10851,7 +10853,7 @@ In roc, functions are always written as a lambda, like{} cannot be generated. Tip: `A` does not implement `Decoding`. Consider adding a custom - implementation or `has Decode.Decoding` to the definition of `A`. + implementation or `implements Decode.Decoding` to the definition of `A`. "### ); @@ -11045,7 +11047,7 @@ In roc, functions are always written as a lambda, like{} app "test" imports [Decode.{decoder}] provides [main] to "./platform" main = - myDecoder : Decoder {x : Str, y ? Str} fmt | fmt has DecoderFormatting + myDecoder : Decoder {x : Str, y ? Str} fmt where fmt implements DecoderFormatting myDecoder = decoder myDecoder @@ -11383,7 +11385,7 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [A] to "./platform" - A a := a -> a has [Hash] + A a := a -> a implements [Hash] "# ), @r###" @@ -11391,8 +11393,8 @@ In roc, functions are always written as a lambda, like{} I can't derive an implementation of the `Hash` ability for `A`: - 3│ A a := a -> a has [Hash] - ^^^^ + 3│ A a := a -> a implements [Hash] + ^^^^ Note: `Hash` cannot be generated for functions. @@ -11406,7 +11408,7 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [A] to "./platform" - A := B has [Hash] + A := B implements [Hash] B := {} "# @@ -11416,13 +11418,14 @@ In roc, functions are always written as a lambda, like{} I can't derive an implementation of the `Hash` ability for `A`: - 3│ A := B has [Hash] - ^^^^ + 3│ A := B implements [Hash] + ^^^^ Tip: `B` does not implement `Hash`. Consider adding a custom - implementation or `has Hash.Hash` to the definition of `B`. + implementation or `implements Hash.Hash` to the definition of `B`. Tip: You can define a custom implementation of `Hash` for `A`. + "### ); @@ -11432,9 +11435,9 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [A] to "./platform" - A := B has [Hash] + A := B implements [Hash] - B := {} has [Hash] + B := {} implements [Hash] "# ), @"" // no error @@ -11446,7 +11449,7 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [MyNat] to "./platform" - MyNat := [S MyNat, Z] has [Hash] + MyNat := [S MyNat, Z] implements [Hash] "# ), @"" // no error @@ -11458,7 +11461,7 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [main] to "./platform" - foo : a -> {} | a has Hash + foo : a -> {} where a implements Hash main = foo {a: "", b: 1} "# @@ -11472,7 +11475,7 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [main] to "./platform" - foo : a -> {} | a has Hash + foo : a -> {} where a implements Hash t : [A {}, B U8 U64, C Str] @@ -11488,7 +11491,7 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [main] to "./platform" - foo : a -> {} | a has Hash + foo : a -> {} where a implements Hash main = foo (\x -> x) "# @@ -11515,7 +11518,7 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [main] to "./platform" - foo : a -> {} | a has Hash + foo : a -> {} where a implements Hash main = foo (A (\x -> x) B) "# @@ -11548,7 +11551,7 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [main] to "./platform" - foo : a -> {} | a has Hash + foo : a -> {} where a implements Hash main = foo ("", 1) "# @@ -11561,7 +11564,7 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [main] to "./platform" - foo : a -> {} | a has Hash + foo : a -> {} where a implements Hash main = foo ("", \{} -> {}) "# @@ -11684,7 +11687,7 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [A] to "./platform" - A a := a -> a has [Eq] + A a := a -> a implements [Eq] "# ), @r###" @@ -11692,8 +11695,8 @@ In roc, functions are always written as a lambda, like{} I can't derive an implementation of the `Eq` ability for `A`: - 3│ A a := a -> a has [Eq] - ^^ + 3│ A a := a -> a implements [Eq] + ^^ Note: `Eq` cannot be generated for functions. @@ -11739,7 +11742,7 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [A] to "./platform" - A := F32 has [Eq] + A := F32 implements [Eq] "# ), @r###" @@ -11747,8 +11750,8 @@ In roc, functions are always written as a lambda, like{} I can't derive an implementation of the `Eq` ability for `A`: - 3│ A := F32 has [Eq] - ^^ + 3│ A := F32 implements [Eq] + ^^ Note: I can't derive `Bool.isEq` for floating-point types. That's because Roc's floating-point numbers cannot be compared for total @@ -11765,7 +11768,7 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [A] to "./platform" - A := F64 has [Eq] + A := F64 implements [Eq] "# ), @r###" @@ -11773,8 +11776,8 @@ In roc, functions are always written as a lambda, like{} I can't derive an implementation of the `Eq` ability for `A`: - 3│ A := F64 has [Eq] - ^^ + 3│ A := F64 implements [Eq] + ^^ Note: I can't derive `Bool.isEq` for floating-point types. That's because Roc's floating-point numbers cannot be compared for total @@ -11791,7 +11794,7 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [A] to "./platform" - A := B has [Eq] + A := B implements [Eq] B := {} "# @@ -11801,13 +11804,14 @@ In roc, functions are always written as a lambda, like{} I can't derive an implementation of the `Eq` ability for `A`: - 3│ A := B has [Eq] - ^^ + 3│ A := B implements [Eq] + ^^ Tip: `B` does not implement `Eq`. Consider adding a custom implementation - or `has Bool.Eq` to the definition of `B`. + or `implements Bool.Eq` to the definition of `B`. Tip: You can define a custom implementation of `Eq` for `A`. + "### ); @@ -11817,9 +11821,9 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [A] to "./platform" - A := B has [Eq] + A := B implements [Eq] - B := {} has [Eq] + B := {} implements [Eq] "# ), @"" // no error @@ -11831,7 +11835,7 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [MyNat] to "./platform" - MyNat := [S MyNat, Z] has [Eq] + MyNat := [S MyNat, Z] implements [Eq] "# ), @"" // no error @@ -11843,7 +11847,7 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [main] to "./platform" - foo : a -> {} | a has Eq + foo : a -> {} where a implements Eq main = foo {a: "", b: 1} "# @@ -11857,7 +11861,7 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [main] to "./platform" - foo : a -> {} | a has Eq + foo : a -> {} where a implements Eq t : [A {}, B U8 U64, C Str] @@ -11873,7 +11877,7 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [main] to "./platform" - foo : a -> {} | a has Eq + foo : a -> {} where a implements Eq main = foo (\x -> x) "# @@ -11900,7 +11904,7 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [main] to "./platform" - foo : a -> {} | a has Eq + foo : a -> {} where a implements Eq main = foo (A (\x -> x) B) "# @@ -11979,7 +11983,7 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [main] to "./platform" - foo : a -> {} | a has Eq + foo : a -> {} where a implements Eq main = foo ("", 1) "# @@ -11992,7 +11996,7 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [main] to "./platform" - foo : a -> {} | a has Eq + foo : a -> {} where a implements Eq main = foo ("", 1.0f64) "# @@ -12072,7 +12076,7 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [f] to "./platform" - F a : a | a has Hash + F a : a where a implements Hash f : F ({} -> {}) "# @@ -12126,7 +12130,7 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [main] to "./platform" - F := U8 -> U8 has [Hash, Eq, Encoding] + F := U8 -> U8 implements [Hash, Eq, Encoding] main = "" "# @@ -12136,8 +12140,8 @@ In roc, functions are always written as a lambda, like{} I can't derive an implementation of the `Hash` ability for `F`: - 3│ F := U8 -> U8 has [Hash, Eq, Encoding] - ^^^^ + 3│ F := U8 -> U8 implements [Hash, Eq, Encoding] + ^^^^ Note: `Hash` cannot be generated for functions. @@ -12147,8 +12151,8 @@ In roc, functions are always written as a lambda, like{} I can't derive an implementation of the `Eq` ability for `F`: - 3│ F := U8 -> U8 has [Hash, Eq, Encoding] - ^^ + 3│ F := U8 -> U8 implements [Hash, Eq, Encoding] + ^^ Note: `Eq` cannot be generated for functions. @@ -12158,8 +12162,8 @@ In roc, functions are always written as a lambda, like{} I can't derive an implementation of the `Encoding` ability for `F`: - 3│ F := U8 -> U8 has [Hash, Eq, Encoding] - ^^^^^^^^ + 3│ F := U8 -> U8 implements [Hash, Eq, Encoding] + ^^^^^^^^ Note: `Encoding` cannot be generated for functions. @@ -12171,7 +12175,7 @@ In roc, functions are always written as a lambda, like{} duplicate_ability_in_has_clause, indoc!( r#" - f : a -> {} | a has Hash & Hash + f : a -> {} where a implements Hash & Hash f "# @@ -12182,10 +12186,11 @@ In roc, functions are always written as a lambda, like{} I already saw that this type variable is bound to the `Hash` ability once before: - 4│ f : a -> {} | a has Hash & Hash - ^^^^ + 4│ f : a -> {} where a implements Hash & Hash + ^^^^ - Abilities only need to bound to a type variable once in a `has` clause! + Abilities only need to bound to a type variable once in an `implements` + clause! "### ); @@ -12195,9 +12200,9 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [main] to "./platform" - g : x -> x | x has Decoding & Encoding + g : x -> x where x implements Decoding & Encoding - main : x -> x | x has Encoding + main : x -> x where x implements Encoding main = \x -> g x "# ), @@ -12211,18 +12216,18 @@ In roc, functions are always written as a lambda, like{} This `x` value is a: - x | x has Encoding + x where x implements Encoding But `g` needs its 1st argument to be: - x | x has Encoding & Decoding + x where x implements Encoding & Decoding - Note: The type variable `x` says it can take on any value that has only - the ability `Encoding`. + Note: The type variable `x` says it can take on any value that + implements only the ability `Encoding`. - But, I see that it's also used as if it has the ability `Decoding`. Can - you use `x` without that ability? If not, consider adding it to the `has` - clause of `x`. + But, I see that it's also used as if it implements the ability + `Decoding`. Can you use `x` without that ability? If not, consider adding + it to the `implements` clause of `x`. "### ); @@ -12232,9 +12237,9 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [main] to "./platform" - g : x -> x | x has Decoding & Encoding & Hash + g : x -> x where x implements Decoding & Encoding & Hash - main : x -> x | x has Encoding + main : x -> x where x implements Encoding main = \x -> g x "# ), @@ -12248,18 +12253,18 @@ In roc, functions are always written as a lambda, like{} This `x` value is a: - x | x has Encoding + x where x implements Encoding But `g` needs its 1st argument to be: - x | x has Hash & Encoding & Decoding + x where x implements Hash & Encoding & Decoding - Note: The type variable `x` says it can take on any value that has only - the ability `Encoding`. + Note: The type variable `x` says it can take on any value that + implements only the ability `Encoding`. - But, I see that it's also used as if it has the abilities `Hash` and - `Decoding`. Can you use `x` without those abilities? If not, consider - adding them to the `has` clause of `x`. + But, I see that it's also used as if it implements the abilities `Hash` + and `Decoding`. Can you use `x` without those abilities? If not, consider + adding them to the `implements` clause of `x`. "### ); @@ -12269,10 +12274,10 @@ In roc, functions are always written as a lambda, like{} r#" app "test" provides [main] to "./platform" - f : x -> x | x has Hash - g : x -> x | x has Decoding & Encoding + f : x -> x where x implements Hash + g : x -> x where x implements Decoding & Encoding - main : x -> x | x has Hash & Encoding + main : x -> x where x implements Hash & Encoding main = \x -> g (f x) "# ), @@ -12286,18 +12291,18 @@ In roc, functions are always written as a lambda, like{} This `f` call produces: - x | x has Hash & Encoding + x where x implements Hash & Encoding But `g` needs its 1st argument to be: - x | x has Encoding & Decoding + x where x implements Encoding & Decoding - Note: The type variable `x` says it can take on any value that has only - the abilities `Hash` and `Encoding`. + Note: The type variable `x` says it can take on any value that + implements only the abilities `Hash` and `Encoding`. - But, I see that it's also used as if it has the ability `Decoding`. Can - you use `x` without that ability? If not, consider adding it to the `has` - clause of `x`. + But, I see that it's also used as if it implements the ability + `Decoding`. Can you use `x` without that ability? If not, consider adding + it to the `implements` clause of `x`. "### ); @@ -13036,8 +13041,9 @@ In roc, functions are always written as a lambda, like{} cannot be generated. - Tip: This type variable is not bound to `Eq`. Consider adding a `has` - clause to bind the type variable, like `| e has Bool.Eq` + Tip: This type variable is not bound to `Eq`. Consider adding an + `implements` clause to bind the type variable, like + `where e implements Bool.Eq` "### ); @@ -13503,7 +13509,7 @@ In roc, functions are always written as a lambda, like{} app "test" imports [Decode.{decoder}] provides [main] to "./platform" main = - myDecoder : Decoder Nat fmt | fmt has DecoderFormatting + myDecoder : Decoder Nat fmt where fmt implements DecoderFormatting myDecoder = decoder myDecoder @@ -13567,7 +13573,7 @@ In roc, functions are always written as a lambda, like{} app "test" imports [Decode.{decoder}] provides [main] to "./platform" main = - myDecoder : Decoder (U32, Str) fmt | fmt has DecoderFormatting + myDecoder : Decoder (U32, Str) fmt where fmt implements DecoderFormatting myDecoder = decoder myDecoder @@ -13582,7 +13588,7 @@ In roc, functions are always written as a lambda, like{} app "test" imports [Decode.{decoder}] provides [main] to "./platform" main = - myDecoder : Decoder (U32, {} -> {}) fmt | fmt has DecoderFormatting + myDecoder : Decoder (U32, {} -> {}) fmt where fmt implements DecoderFormatting myDecoder = decoder myDecoder diff --git a/default.nix b/default.nix index fe59200244..4e0ba26fb5 100644 --- a/default.nix +++ b/default.nix @@ -14,7 +14,10 @@ let llvmPkgs = pkgs.llvmPackages_13; # nix does not store libs in /usr/lib or /lib - nixGlibcPath = if pkgs.stdenv.isLinux then "${pkgs.glibc.out}/lib" else ""; + glibcPath = + if pkgs.stdenv.isLinux then "${pkgs.glibc.out}/lib" else ""; + libGccSPath = + if pkgs.stdenv.isLinux then "${pkgs.stdenv.cc.cc.lib}/lib" else ""; in assert pkgs.lib.assertMsg rustVersionsMatch '' @@ -104,7 +107,7 @@ in # wrapProgram pkgs.stdenv.cc: to make ld available for compiler/build/src/link.rs postInstall = if pkgs.stdenv.isLinux then '' - wrapProgram $out/bin/roc --set NIX_GLIBC_PATH ${nixGlibcPath} --prefix PATH : ${ + wrapProgram $out/bin/roc --set NIX_GLIBC_PATH ${glibcPath} --set NIX_LIBGCC_S_PATH ${libGccSPath} --prefix PATH : ${ pkgs.lib.makeBinPath [ pkgs.stdenv.cc ] } '' else '' diff --git a/devtools/README.md b/devtools/README.md old mode 100644 new mode 100755 index 57916ade6f..5b197d9ecc --- a/devtools/README.md +++ b/devtools/README.md @@ -7,10 +7,10 @@ The flake in this folder is meant for vscode, feel free to create a PR if you'li Further steps: -1. Copy the flake.nix and flake.lock file to a new folder outside of the roc repo folder. +1. Copy the flake.nix and flake.lock file from the devtools folder to a new folder outside of the roc repo folder. 1. Run `git init` in the new folder. -1. Execute `git add flake.nix`, nix will error if you don't do this. -1. Change `roc.url = "path:/home/username/gitrepos/roc9/roc";` to the location of the roc folder on your machine. +1. Execute `git add flake.nix flake.lock`, nix will error if you don't do this. +1. Change `roc.url = "path:/home/username/gitrepos/roc";` to the location of the roc folder on your machine. 1. Follow instructions about vscode extensions [here](#extensions). 1. add other dev tools you like in the `devInputs` list. You can search for those [here](https://search.nixos.org/packages). 1. Run `nix develop`. diff --git a/devtools/flake.lock b/devtools/flake.lock old mode 100644 new mode 100755 index beb73d0808..c15d838e56 --- a/devtools/flake.lock +++ b/devtools/flake.lock @@ -5,11 +5,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1681202837, - "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", + "lastModified": 1692799911, + "narHash": "sha256-3eihraek4qL744EvQXsK1Ha6C3CR7nnT8X2qWap4RNk=", "owner": "numtide", "repo": "flake-utils", - "rev": "cfacdce06f30d2b68473a46042957675eebb3401", + "rev": "f9e7cf818399d17d347f847525c5a5a8032e4e44", "type": "github" }, "original": { @@ -93,17 +93,17 @@ }, "nixpkgs": { "locked": { - "lastModified": 1674860021, - "narHash": "sha256-ES4XUf/AlPp8RetKR6WlWgYEZ7bLWI7k6reHp2q9rqY=", + "lastModified": 1690279121, + "narHash": "sha256-XoPGhV1UJQPue6RiehAu7lQwKss3J1B/K0QtVOMD83A=", "owner": "nixos", "repo": "nixpkgs", - "rev": "9f4346eac544cc0db5eb7d889e71eac0f9c8b9eb", + "rev": "821c72743ceae44bdd09718d47cab98fd5fd90af", "type": "github" }, "original": { "owner": "nixos", "repo": "nixpkgs", - "rev": "9f4346eac544cc0db5eb7d889e71eac0f9c8b9eb", + "rev": "821c72743ceae44bdd09718d47cab98fd5fd90af", "type": "github" } }, @@ -115,13 +115,13 @@ "rust-overlay": "rust-overlay" }, "locked": { - "lastModified": 1682784625, - "narHash": "sha256-QUncKiwgpmHajo601NNHOjeUG2/vrGp1oMgxnPhq900=", - "path": "/home/username/gitrepos/roc9/roc", + "lastModified": 1694000770, + "narHash": "sha256-92bAbPmwXxD6rwaAViG5O9r91ZBh9bqaZhM3egPCjuw=", + "path": "/home/anton/gitrepos/roc", "type": "path" }, "original": { - "path": "/home/username/gitrepos/roc9/roc", + "path": "/home/anton/gitrepos/roc", "type": "path" } }, @@ -140,11 +140,11 @@ ] }, "locked": { - "lastModified": 1682389182, - "narHash": "sha256-8t2nmFnH+8V48+IJsf8AK51ebXNlVbOSVYOpiqJKvJE=", + "lastModified": 1690252178, + "narHash": "sha256-9oEz822bvbHobfCUjJLDor2BqW3I5tycIauzDlzOALY=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "74f1a64dd28faeeb85ef081f32cad2989850322c", + "rev": "8d64353ca827002fb8459e44d49116c78d868eba", "type": "github" }, "original": { diff --git a/devtools/flake.nix b/devtools/flake.nix old mode 100644 new mode 100755 index cf86267083..a37b707bed --- a/devtools/flake.nix +++ b/devtools/flake.nix @@ -3,7 +3,7 @@ inputs = { # change this path to the path of your roc folder - roc.url = "path:/home/username/gitrepos/roc9/roc"; + roc.url = "path:/home/username/gitrepos/roc"; # to easily make configs for multiple architectures flake-utils.url = "github:numtide/flake-utils"; }; @@ -35,7 +35,7 @@ publisher = "benjamin-thomas"; version = "0.0.4"; # keep this sha for the first run, nix will tell you the correct one to change it to - sha256 = "sha256-mabNegZ+XPQ6EIHFk6jz2mAPLHAU6Pm3w0SiFB7IE+s="; + sha256 = "sha256-USZiXdvYa8hxj62cy6hdiS5c2tIDIQxSyux684lyAEY="; } ] ; diff --git a/examples/.gitignore b/examples/.gitignore index 29accfafaa..e14acf75bb 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -6,3 +6,5 @@ dynhost *.rh helloWorld +inspect-gui +inspect-logging diff --git a/examples/Community.roc b/examples/Community.roc new file mode 100644 index 0000000000..7be09c317a --- /dev/null +++ b/examples/Community.roc @@ -0,0 +1,150 @@ +interface Community + exposes [ + Community, + empty, + addPerson, + addFriend, + Person, + walkFriendNames, + ] + imports [] + +## Datatype representing a community for demonstration purposes in inspect-gui.roc and inspect-logging.roc + +Community := { + people : List Person, + friends : List (Set Nat), +} + implements [ + Inspect { + toInspector: inspectCommunity, + }, + ] + +Person := { + firstName : Str, + lastName : Str, + age : U8, + hasBeard : Bool, + favoriteColor : Color, +} + implements [ + Inspect { + toInspector: inspectPerson, + }, + ] + +Color : [ + Red, + Green, + Blue, + RGB (U8, U8, U8), +] + +empty = @Community { people: [], friends: [] } + +addPerson = \@Community { people, friends }, person -> + @Community { + people: List.append people (@Person person), + friends: List.append friends (Set.empty {}), + } + +addFriend = \@Community { people, friends }, from, to -> + when (List.get friends from, List.get friends to) is + (Ok fromSet, Ok toSet) -> + @Community { + people, + friends: friends + |> List.set from (Set.insert fromSet to) + |> List.set to (Set.insert toSet from), + } + + _ -> + @Community { people, friends } + +walkFriendNames : Community, state, (state, Str, Set Str -> state) -> state +walkFriendNames = \@Community { people, friends }, s0, nextFn -> + (out, _) = + (s1, id), friendSet <- List.walk friends (s0, 0) + (@Person person) = + when List.get people id is + Ok v -> v + Err _ -> crash "Unknown Person" + personName = + person.firstName + |> Str.concat " " + |> Str.concat person.lastName + + friendNames = + friendsSet, friendId <- Set.walk friendSet (Set.empty {}) + (@Person friend) = + when List.get people friendId is + Ok v -> v + Err _ -> crash "Unknown Person" + friendName = + friend.firstName + |> Str.concat " " + |> Str.concat friend.lastName + Set.insert friendsSet friendName + + (nextFn s1 personName friendNames, id + 1) + out + +# The functions below will be auto-generated in the future +inspectCommunity : Community -> Inspector f where f implements InspectFormatter +inspectCommunity = \@Community { people, friends } -> + f0 <- Inspect.custom + [ + { key: "people", value: Inspect.list people List.walk Inspect.toInspector }, + { + key: "friends", + value: Inspect.list + friends + List.walk + (\s -> Inspect.set + s + Set.walk + (\num -> num |> Num.toU64 |> Inspect.u64) + ), + # value: Inspect.dict + # (@Community { people, friends }) + # walkFriendNames + # Inspect.str + # (\s -> Inspect.set s Set.walk Inspect.str), + }, + ] + |> Inspect.record + |> Inspect.apply f0 + +inspectPerson : Person -> Inspector f where f implements InspectFormatter +inspectPerson = \@Person { firstName, lastName, age, hasBeard, favoriteColor } -> + # In practice, this would never be done manually due to autoderive. + # Instead you would just write: + # Inspect.inspect innerRecord + # This is what the auto-derive would generate. + + f0 <- Inspect.custom + + favoriteColorTag = + when favoriteColor is + Red -> + Inspect.tag "Red" [] + + Green -> + Inspect.tag "Green" [] + + Blue -> + Inspect.tag "Blue" [] + + RGB (r, g, b) -> + Inspect.tag "RGB" [Inspect.tuple [Inspect.u8 r, Inspect.u8 g, Inspect.u8 b]] + + [ + { key: "firstName", value: Inspect.str firstName }, + { key: "lastName", value: Inspect.str lastName }, + { key: "age", value: Inspect.u8 age }, + { key: "hasBeard", value: Inspect.bool hasBeard }, + { key: "favoriteColor", value: favoriteColorTag }, + ] + |> Inspect.record + |> Inspect.apply f0 diff --git a/examples/GuiFormatter.roc b/examples/GuiFormatter.roc new file mode 100644 index 0000000000..615edb15c8 --- /dev/null +++ b/examples/GuiFormatter.roc @@ -0,0 +1,227 @@ +interface GuiFormatter + exposes [ + GuiFormatter, + toGui, + ] + imports [] + +## Creates GUI representations of Roc values, for use in inspect-gui.roc + +## This can't depend on the platform, so I just copied all of this. + +Rgba : { r : F32, g : F32, b : F32, a : F32 } +ButtonStyles : { bgColor : Rgba, borderColor : Rgba, borderWidth : F32, textColor : Rgba } +Elem : [Button Elem ButtonStyles, Col (List Elem), Row (List Elem), Text Str] + +GuiFormatter := { nodes : List Elem } + implements [ + InspectFormatter { + init: init, + list: list, + set: set, + dict: dict, + tag: tag, + tuple: tuple, + record: record, + bool: bool, + str: str, + opaque: opaque, + u8: u8, + i8: i8, + u16: u16, + i16: i16, + u32: u32, + i32: i32, + u64: u64, + i64: i64, + u128: u128, + i128: i128, + f32: f32, + f64: f64, + dec: dec, + + }, + ] + +init : {} -> GuiFormatter +init = \{} -> @GuiFormatter { nodes: [] } + +list : list, ElemWalker GuiFormatter list elem, (elem -> Inspector GuiFormatter) -> Inspector GuiFormatter +list = \content, walkFn, toInspector -> + f0 <- Inspect.custom + # Use a temporary buffer for the children nodes + (@GuiFormatter { nodes }) = + init {} + |> \f1 -> + f2, elem <- walkFn content f1 + elem + |> toInspector + |> Inspect.apply f2 + + addNode f0 (Col nodes) + +set : set, ElemWalker GuiFormatter set elem, (elem -> Inspector GuiFormatter) -> Inspector GuiFormatter +set = \content, walkFn, toInspector -> + f0 <- Inspect.custom + # Use a temporary buffer for the children nodes + (@GuiFormatter { nodes }) = + init {} + |> \f1 -> + f2, elem <- walkFn content f1 + elem + |> toInspector + |> Inspect.apply f2 + + addNode f0 (Col nodes) + +dict : dict, KeyValWalker GuiFormatter dict key value, (key -> Inspector GuiFormatter), (value -> Inspector GuiFormatter) -> Inspector GuiFormatter +dict = \d, walkFn, keyToInspector, valueToInspector -> + f0 <- Inspect.custom + # Use a temporary buffer for the children nodes + (@GuiFormatter { nodes }) = + init {} + |> \f1 -> + f2, key, value <- walkFn d f1 + (@GuiFormatter { nodes: innerNodes }) = + init {} + |> \x -> Inspect.apply (keyToInspector key) x + |> addNode (Text ":") + |> \x -> Inspect.apply (valueToInspector value) x + + addNode f2 (Row innerNodes) + + addNode f0 (Col nodes) + +tag : Str, List (Inspector GuiFormatter) -> Inspector GuiFormatter +tag = \name, fields -> + f0 <- Inspect.custom + # Use a temporary buffer for the children nodes + (@GuiFormatter { nodes }) = + init {} + |> addNode (Text name) + |> \f1 -> + f2, fieldInspector <- List.walk fields f1 + Inspect.apply fieldInspector f2 + + addNode f0 (Row nodes) + +tuple : List (Inspector GuiFormatter) -> Inspector GuiFormatter +tuple = \fields -> + f0 <- Inspect.custom + # Use a temporary buffer for the children nodes + (@GuiFormatter { nodes }) = + init {} + |> \f1 -> + f2, fieldInspector <- List.walk fields f1 + Inspect.apply fieldInspector f2 + + addNode f0 (Row nodes) + +record : List { key : Str, value : Inspector GuiFormatter } -> Inspector GuiFormatter +record = \fields -> + f0 <- Inspect.custom + # Use a temporary buffer for the children nodes + (@GuiFormatter { nodes }) = + init {} + |> \f1 -> + f2, { key, value } <- List.walk fields f1 + (@GuiFormatter { nodes: innerNodes }) = + init {} + |> addNode (Text key) + |> addNode (Text ":") + |> \x -> Inspect.apply value x + + addNode f2 (Row innerNodes) + + addNode f0 (Col nodes) + +bool : Bool -> Inspector GuiFormatter +bool = \b -> + if b then + f0 <- Inspect.custom + addNode f0 (Text "true") + else + f0 <- Inspect.custom + addNode f0 (Text "false") + +str : Str -> Inspector GuiFormatter +str = \s -> + f0 <- Inspect.custom + addNode f0 (Text "\"\(s)\"") + +opaque : Str -> Inspector GuiFormatter +opaque = \s -> + f0 <- Inspect.custom + addNode f0 (Text "<\(s)>") + +u8 : U8 -> Inspector GuiFormatter +u8 = \num -> + f0 <- Inspect.custom + addNode f0 (num |> Num.toStr |> Text) + +i8 : I8 -> Inspector GuiFormatter +i8 = \num -> + f0 <- Inspect.custom + addNode f0 (num |> Num.toStr |> Text) + +u16 : U16 -> Inspector GuiFormatter +u16 = \num -> + f0 <- Inspect.custom + addNode f0 (num |> Num.toStr |> Text) + +i16 : I16 -> Inspector GuiFormatter +i16 = \num -> + f0 <- Inspect.custom + addNode f0 (num |> Num.toStr |> Text) + +u32 : U32 -> Inspector GuiFormatter +u32 = \num -> + f0 <- Inspect.custom + addNode f0 (num |> Num.toStr |> Text) + +i32 : I32 -> Inspector GuiFormatter +i32 = \num -> + f0 <- Inspect.custom + addNode f0 (num |> Num.toStr |> Text) + +u64 : U64 -> Inspector GuiFormatter +u64 = \num -> + f0 <- Inspect.custom + addNode f0 (num |> Num.toStr |> Text) + +i64 : I64 -> Inspector GuiFormatter +i64 = \num -> + f0 <- Inspect.custom + addNode f0 (num |> Num.toStr |> Text) + +u128 : U128 -> Inspector GuiFormatter +u128 = \num -> + f0 <- Inspect.custom + addNode f0 (num |> Num.toStr |> Text) + +i128 : I128 -> Inspector GuiFormatter +i128 = \num -> + f0 <- Inspect.custom + addNode f0 (num |> Num.toStr |> Text) + +f32 : F32 -> Inspector GuiFormatter +f32 = \num -> + f0 <- Inspect.custom + addNode f0 (num |> Num.toStr |> Text) + +f64 : F64 -> Inspector GuiFormatter +f64 = \num -> + f0 <- Inspect.custom + addNode f0 (num |> Num.toStr |> Text) + +dec : Dec -> Inspector GuiFormatter +dec = \num -> + f0 <- Inspect.custom + addNode f0 (num |> Num.toStr |> Text) + +addNode : GuiFormatter, Elem -> GuiFormatter +addNode = \@GuiFormatter { nodes }, node -> + @GuiFormatter { nodes: List.append nodes node } + +toGui : GuiFormatter -> Elem +toGui = \@GuiFormatter { nodes } -> Col nodes diff --git a/examples/LogFormatter.roc b/examples/LogFormatter.roc new file mode 100644 index 0000000000..a9a015e58c --- /dev/null +++ b/examples/LogFormatter.roc @@ -0,0 +1,246 @@ +interface LogFormatter + exposes [ + LogFormatter, + toStr, + ] + imports [] + +## Creates String representations of Roc values, for use in inspect-logging.roc + +LogFormatter := { data : Str } + implements [ + InspectFormatter { + init: init, + list: list, + set: set, + dict: dict, + tag: tag, + tuple: tuple, + record: record, + bool: bool, + str: str, + opaque: opaque, + u8: u8, + i8: i8, + u16: u16, + i16: i16, + u32: u32, + i32: i32, + u64: u64, + i64: i64, + u128: u128, + i128: i128, + f32: f32, + f64: f64, + dec: dec, + + }, + ] + +init : {} -> LogFormatter +init = \{} -> @LogFormatter { data: "" } + +list : list, ElemWalker (LogFormatter, Bool) list elem, (elem -> Inspector LogFormatter) -> Inspector LogFormatter +list = \content, walkFn, toInspector -> + f0 <- Inspect.custom + write f0 "[" + |> \f1 -> + (f2, prependSep), elem <- walkFn content (f1, Bool.false) + f3 = + if prependSep then + write f2 ", " + else + f2 + + elem + |> toInspector + |> Inspect.apply f3 + |> \f4 -> (f4, Bool.true) + |> .0 + |> write "]" + +set : set, ElemWalker (LogFormatter, Bool) set elem, (elem -> Inspector LogFormatter) -> Inspector LogFormatter +set = \content, walkFn, toInspector -> + f0 <- Inspect.custom + write f0 "{" + |> \f1 -> + (f2, prependSep), elem <- walkFn content (f1, Bool.false) + f3 = + if prependSep then + write f2 ", " + else + f2 + + elem + |> toInspector + |> Inspect.apply f3 + |> \f4 -> (f4, Bool.true) + |> .0 + |> write "}" + +dict : dict, KeyValWalker (LogFormatter, Bool) dict key value, (key -> Inspector LogFormatter), (value -> Inspector LogFormatter) -> Inspector LogFormatter +dict = \d, walkFn, keyToInspector, valueToInspector -> + f0 <- Inspect.custom + write f0 "{" + |> \f1 -> + (f2, prependSep), key, value <- walkFn d (f1, Bool.false) + f3 = + if prependSep then + write f2 ", " + else + f2 + + Inspect.apply (keyToInspector key) f3 + |> write ": " + |> \x -> Inspect.apply (valueToInspector value) x + |> \f4 -> (f4, Bool.true) + |> .0 + |> write "}" + +tag : Str, List (Inspector LogFormatter) -> Inspector LogFormatter +tag = \name, fields -> + if List.isEmpty fields then + f0 <- Inspect.custom + write f0 name + else + f0 <- Inspect.custom + write f0 "(" + |> write name + |> \f1 -> + f2, inspector <- List.walk fields f1 + write f2 " " + |> \x -> Inspect.apply inspector x + |> write ")" + +tuple : List (Inspector LogFormatter) -> Inspector LogFormatter +tuple = \fields -> + f0 <- Inspect.custom + write f0 "(" + |> \f1 -> + (f2, prependSep), inspector <- List.walk fields (f1, Bool.false) + f3 = + if prependSep then + write f2 ", " + else + f2 + + Inspect.apply inspector f3 + |> \f4 -> (f4, Bool.true) + |> .0 + |> write ")" + +record : List { key : Str, value : Inspector LogFormatter } -> Inspector LogFormatter +record = \fields -> + f0 <- Inspect.custom + write f0 "{" + |> \f1 -> + (f2, prependSep), { key, value } <- List.walk fields (f1, Bool.false) + f3 = + if prependSep then + write f2 ", " + else + f2 + + write f3 key + |> write ": " + |> \x -> Inspect.apply value x + |> \f4 -> (f4, Bool.true) + |> .0 + |> write "}" + +bool : Bool -> Inspector LogFormatter +bool = \b -> + if b then + f0 <- Inspect.custom + write f0 "true" + else + f0 <- Inspect.custom + write f0 "false" + +str : Str -> Inspector LogFormatter +str = \s -> + f0 <- Inspect.custom + f0 + |> write "\"" + |> write s + |> write "\"" + +opaque : Str -> Inspector LogFormatter +opaque = \s -> + f0 <- Inspect.custom + f0 + |> write "<" + |> write s + |> write ">" + +u8 : U8 -> Inspector LogFormatter +u8 = \num -> + f0 <- Inspect.custom + write f0 (num |> Num.toStr) + +i8 : I8 -> Inspector LogFormatter +i8 = \num -> + f0 <- Inspect.custom + write f0 (num |> Num.toStr) + +u16 : U16 -> Inspector LogFormatter +u16 = \num -> + f0 <- Inspect.custom + write f0 (num |> Num.toStr) + +i16 : I16 -> Inspector LogFormatter +i16 = \num -> + f0 <- Inspect.custom + write f0 (num |> Num.toStr) + +u32 : U32 -> Inspector LogFormatter +u32 = \num -> + f0 <- Inspect.custom + write f0 (num |> Num.toStr) + +i32 : I32 -> Inspector LogFormatter +i32 = \num -> + f0 <- Inspect.custom + write f0 (num |> Num.toStr) + +u64 : U64 -> Inspector LogFormatter +u64 = \num -> + f0 <- Inspect.custom + write f0 (num |> Num.toStr) + +i64 : I64 -> Inspector LogFormatter +i64 = \num -> + f0 <- Inspect.custom + write f0 (num |> Num.toStr) + +u128 : U128 -> Inspector LogFormatter +u128 = \num -> + f0 <- Inspect.custom + write f0 (num |> Num.toStr) + +i128 : I128 -> Inspector LogFormatter +i128 = \num -> + f0 <- Inspect.custom + write f0 (num |> Num.toStr) + +f32 : F32 -> Inspector LogFormatter +f32 = \num -> + f0 <- Inspect.custom + write f0 (num |> Num.toStr) + +f64 : F64 -> Inspector LogFormatter +f64 = \num -> + f0 <- Inspect.custom + write f0 (num |> Num.toStr) + +dec : Dec -> Inspector LogFormatter +dec = \num -> + f0 <- Inspect.custom + write f0 (num |> Num.toStr) + +write : LogFormatter, Str -> LogFormatter +write = \@LogFormatter { data }, added -> + @LogFormatter { data: Str.concat data added } + +toStr : LogFormatter -> Str +toStr = \@LogFormatter { data } -> data diff --git a/examples/cli/cli-platform/Env.roc b/examples/cli/cli-platform/Env.roc index 2826d34941..50af317d8c 100644 --- a/examples/cli/cli-platform/Env.roc +++ b/examples/cli/cli-platform/Env.roc @@ -65,7 +65,7 @@ var = \name -> ## - comma-separated lists (of either strings or numbers), as long as there are no spaces after the commas ## ## Trying to decode into any other types will always fail with a `DecodeErr`. -decode : Str -> Task val [VarNotFound, DecodeErr DecodeError] | val has Decoding +decode : Str -> Task val [VarNotFound, DecodeErr DecodeError] where val implements Decoding decode = \name -> Effect.envVar name |> Effect.map @@ -120,4 +120,4 @@ dict = # decode all the required vars only, and then decode the optional ones separately some other way. # Alternatively, it could make sense to have some sort of tag union convention here, e.g. # if decoding into a tag union of [Present val, Missing], then it knows what to do. -# decodeAll : Task val [] [EnvDecodingFailed Str] [Env] | val has Decoding +# decodeAll : Task val [] [EnvDecodingFailed Str] [Env] where val implements Decoding diff --git a/examples/cli/cli-platform/EnvDecoding.roc b/examples/cli/cli-platform/EnvDecoding.roc index d6be7f2b2c..b817143975 100644 --- a/examples/cli/cli-platform/EnvDecoding.roc +++ b/examples/cli/cli-platform/EnvDecoding.roc @@ -1,6 +1,6 @@ interface EnvDecoding exposes [EnvFormat, format] imports [] -EnvFormat := {} has [ +EnvFormat := {} implements [ DecoderFormatting { u8: envU8, u16: envU16, diff --git a/examples/cli/cli-platform/File.roc b/examples/cli/cli-platform/File.roc index 708fe1b7a6..b5e367f889 100644 --- a/examples/cli/cli-platform/File.roc +++ b/examples/cli/cli-platform/File.roc @@ -26,7 +26,7 @@ WriteErr : InternalFile.WriteErr ## This opens the file first and closes it after writing to it. ## ## To write unformatted bytes to a file, you can use [File.writeBytes] instead. -write : Path, val, fmt -> Task {} [FileWriteErr Path WriteErr] | val has Encode.Encoding, fmt has Encode.EncoderFormatting +write : Path, val, fmt -> Task {} [FileWriteErr Path WriteErr] where val implements Encode.Encoding, fmt implements Encode.EncoderFormatting write = \path, val, fmt -> bytes = Encode.toBytes val fmt @@ -119,7 +119,7 @@ readUtf8 = \path -> # Str # [FileReadErr Path ReadErr, FileReadDecodeErr Path [Leftover (List U8)]Decode.DecodeError ] # [Read [File]] -# | val has Decode.Decoding, fmt has Decode.DecoderFormatting +# where val implements Decode.Decoding, fmt implements Decode.DecoderFormatting # read = \path, fmt -> # effect = Effect.map (Effect.fileReadBytes (InternalPath.toBytes path)) \result -> # when result is diff --git a/examples/cli/cli-platform/Http.roc b/examples/cli/cli-platform/Http.roc index 2353e2cef3..8304277c44 100644 --- a/examples/cli/cli-platform/Http.roc +++ b/examples/cli/cli-platform/Http.roc @@ -56,7 +56,7 @@ stringBody : [MimeType Str], Str -> Body stringBody = \mimeType, str -> Body mimeType (Str.toUtf8 str) -# jsonBody : a -> Body | a has Encoding +# jsonBody : a -> Body where a implements Encoding # jsonBody = \val -> # Body (MimeType "application/json") (Encode.toBytes val TotallyNotJson.format) # diff --git a/examples/cli/cli-platform/main.roc b/examples/cli/cli-platform/main.roc index 8e185a6db1..c8f90a9191 100644 --- a/examples/cli/cli-platform/main.roc +++ b/examples/cli/cli-platform/main.roc @@ -5,5 +5,5 @@ platform "cli" imports [Task.{ Task }] provides [mainForHost] -mainForHost : Task {} [] as Fx +mainForHost : Task {} [] mainForHost = main diff --git a/examples/cli/effects-platform/main.roc b/examples/cli/effects-platform/main.roc index 5e718ffc47..e2092147f7 100644 --- a/examples/cli/effects-platform/main.roc +++ b/examples/cli/effects-platform/main.roc @@ -5,5 +5,5 @@ platform "effects" imports [pf.Effect] provides [mainForHost] -mainForHost : Effect.Effect {} as Fx +mainForHost : Effect.Effect {} mainForHost = main diff --git a/examples/cli/false-interpreter/platform/main.roc b/examples/cli/false-interpreter/platform/main.roc index 2d737816a5..cf97352ce4 100644 --- a/examples/cli/false-interpreter/platform/main.roc +++ b/examples/cli/false-interpreter/platform/main.roc @@ -5,5 +5,5 @@ platform "false-interpreter" imports [Task.{ Task }] provides [mainForHost] -mainForHost : Str -> Task {} [] as Fx +mainForHost : Str -> Task {} [] mainForHost = \file -> main file diff --git a/examples/glue/rust-platform/Cargo.toml b/examples/glue/rust-platform/Cargo.toml index 8d10ce6eea..3cfadfba58 100644 --- a/examples/glue/rust-platform/Cargo.toml +++ b/examples/glue/rust-platform/Cargo.toml @@ -16,7 +16,8 @@ name = "host" path = "src/main.rs" [dependencies] -roc_std = { path = "../../../crates/roc_std" } +roc_app = { path = "roc_app" } +roc_std = { path = "roc_std" } libc = "0.2" [workspace] diff --git a/examples/glue/rust-platform/src/lib.rs b/examples/glue/rust-platform/src/lib.rs index fe5398b647..e821634b41 100644 --- a/examples/glue/rust-platform/src/lib.rs +++ b/examples/glue/rust-platform/src/lib.rs @@ -1,15 +1,13 @@ #![allow(non_snake_case)] -mod test_glue; - use core::ffi::c_void; +use roc_app::Op; use roc_std::RocStr; use std::ffi::CStr; use std::io::Write; use std::os::raw::c_char; -use test_glue::Op; -use test_glue::mainForHost as roc_main; +use roc_app::mainForHost as roc_main; #[no_mangle] pub unsafe extern "C" fn roc_alloc(size: usize, _alignment: u32) -> *mut c_void { @@ -80,7 +78,7 @@ pub unsafe extern "C" fn roc_shm_open( #[no_mangle] pub extern "C" fn rust_main() -> i32 { - use test_glue::discriminant_Op::*; + use roc_app::discriminant_Op::*; println!("Let's do things!"); @@ -91,7 +89,7 @@ pub extern "C" fn rust_main() -> i32 { StdoutWrite => { let stdout_write = op.get_StdoutWrite(); let output: RocStr = stdout_write.f0; - op = unsafe { stdout_write.f1.force_thunk(()) }; + op = unsafe { stdout_write.f1.force_thunk() }; if let Err(e) = std::io::stdout().write_all(output.as_bytes()) { panic!("Writing to stdout failed! {:?}", e); @@ -100,7 +98,7 @@ pub extern "C" fn rust_main() -> i32 { StderrWrite => { let stderr_write = op.get_StderrWrite(); let output: RocStr = stderr_write.f0; - op = unsafe { stderr_write.f1.force_thunk(()) }; + op = unsafe { stderr_write.f1.force_thunk() }; if let Err(e) = std::io::stderr().write_all(output.as_bytes()) { panic!("Writing to stdout failed! {:?}", e); diff --git a/examples/helloWorld.roc b/examples/helloWorld.roc index 6501e3f0d4..fe6bddd76e 100644 --- a/examples/helloWorld.roc +++ b/examples/helloWorld.roc @@ -1,5 +1,5 @@ app "helloWorld" - packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.4.0/DI4lqn7LIZs8ZrCDUgLK-tHHpQmxGF1ZrlevRKq5LXk.tar.br" } + packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.5.0/Cufzl36_SnJ4QbOoEmiJ5dIpUxBvdB3NEySvuH82Wio.tar.br" } imports [pf.Stdout] provides [main] to pf diff --git a/examples/inspect-gui.roc b/examples/inspect-gui.roc new file mode 100644 index 0000000000..a3e0aa120c --- /dev/null +++ b/examples/inspect-gui.roc @@ -0,0 +1,38 @@ +# +# Visualizes Roc values in a basic GUI +# +app "inspect-gui" + packages { pf: "gui/platform/main.roc" } + imports [ + Community, + GuiFormatter, + ] + provides [render] to pf + +render = + Community.empty + |> Community.addPerson { + firstName: "John", + lastName: "Smith", + age: 27, + hasBeard: Bool.true, + favoriteColor: Blue, + } + |> Community.addPerson { + firstName: "Debby", + lastName: "Johnson", + age: 47, + hasBeard: Bool.false, + favoriteColor: Green, + } + |> Community.addPerson { + firstName: "Jane", + lastName: "Doe", + age: 33, + hasBeard: Bool.false, + favoriteColor: RGB (255, 255, 0), + } + |> Community.addFriend 0 2 + |> Community.addFriend 1 2 + |> Inspect.inspect + |> GuiFormatter.toGui diff --git a/examples/inspect-logging.roc b/examples/inspect-logging.roc new file mode 100644 index 0000000000..fd284def02 --- /dev/null +++ b/examples/inspect-logging.roc @@ -0,0 +1,40 @@ +# +# Shows how Roc values can be logged +# +app "inspect-logging" + packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.5.0/Cufzl36_SnJ4QbOoEmiJ5dIpUxBvdB3NEySvuH82Wio.tar.br" } + imports [ + pf.Stdout, + LogFormatter, + Community, + ] + provides [main] to pf + +main = + Community.empty + |> Community.addPerson { + firstName: "John", + lastName: "Smith", + age: 27, + hasBeard: Bool.true, + favoriteColor: Blue, + } + |> Community.addPerson { + firstName: "Debby", + lastName: "Johnson", + age: 47, + hasBeard: Bool.false, + favoriteColor: Green, + } + |> Community.addPerson { + firstName: "Jane", + lastName: "Doe", + age: 33, + hasBeard: Bool.false, + favoriteColor: RGB (255, 255, 0), + } + |> Community.addFriend 0 2 + |> Community.addFriend 1 2 + |> Inspect.inspect + |> LogFormatter.toStr + |> Stdout.line diff --git a/examples/parser/examples/letter-counts.roc b/examples/parser/examples/letter-counts.roc index 0978188a11..05ee2f37ad 100644 --- a/examples/parser/examples/letter-counts.roc +++ b/examples/parser/examples/letter-counts.roc @@ -1,6 +1,6 @@ app "example" packages { - cli: "https://github.com/roc-lang/basic-cli/releases/download/0.4.0/DI4lqn7LIZs8ZrCDUgLK-tHHpQmxGF1ZrlevRKq5LXk.tar.br", + cli: "https://github.com/roc-lang/basic-cli/releases/download/0.5.0/Cufzl36_SnJ4QbOoEmiJ5dIpUxBvdB3NEySvuH82Wio.tar.br", parser: "../package/main.roc", } imports [ diff --git a/examples/python-interop/platform/main.roc b/examples/python-interop/platform/main.roc index 31eaa8c9d1..ffcf7cbfff 100644 --- a/examples/python-interop/platform/main.roc +++ b/examples/python-interop/platform/main.roc @@ -1,5 +1,5 @@ platform "python-interop" - requires {} { main : arg -> ret | arg has Decoding, ret has Encoding } + requires {} { main : arg -> ret where arg implements Decoding, ret implements Encoding } exposes [] packages {} imports [TotallyNotJson] diff --git a/examples/ruby-interop/platform/main.roc b/examples/ruby-interop/platform/main.roc index ddbd512547..901c1a1298 100644 --- a/examples/ruby-interop/platform/main.roc +++ b/examples/ruby-interop/platform/main.roc @@ -1,5 +1,5 @@ platform "ruby-interop" - requires {} { main : arg -> ret | arg has Decoding, ret has Encoding } + requires {} { main : arg -> ret where arg implements Decoding, ret implements Encoding } exposes [] packages {} imports [TotallyNotJson] diff --git a/examples/virtual-dom-wip/platform/Html/Attributes.roc b/examples/virtual-dom-wip/platform/Html/Attributes.roc index f068391da9..6d6f63d121 100644 --- a/examples/virtual-dom-wip/platform/Html/Attributes.roc +++ b/examples/virtual-dom-wip/platform/Html/Attributes.roc @@ -134,7 +134,7 @@ interface Html.Attributes width, wrap, ] - imports [Html.Internal.{ Attribute }] + imports [Html.Internal.Shared.{ Attribute }] attribute : Str -> (Str -> Attribute state) attribute = \attrType -> diff --git a/examples/virtual-dom-wip/platform/Html/Event.roc b/examples/virtual-dom-wip/platform/Html/Event.roc index 9643a9c747..95a7a8056c 100644 --- a/examples/virtual-dom-wip/platform/Html/Event.roc +++ b/examples/virtual-dom-wip/platform/Html/Event.roc @@ -20,25 +20,25 @@ interface Html.Event ] imports [ Action.{ Action }, - Html.Internal.{ Attribute }, + Html.Internal.Shared.{ Attribute }, ] -Handler state : Html.Internal.Handler state -CyclicStructureAccessor : Html.Internal.CyclicStructureAccessor +Handler state : Html.Internal.Shared.Handler state +CyclicStructureAccessor : Html.Internal.Shared.CyclicStructureAccessor custom : Str, List CyclicStructureAccessor, (state, List (List U8) -> { action : Action state, stopPropagation : Bool, preventDefault : Bool }) -> Attribute state custom = \eventName, accessors, callback -> - EventListener eventName accessors (Ok (Custom callback)) + EventListener eventName accessors (Custom callback) on : Str, List CyclicStructureAccessor, (state, List (List U8) -> Action state) -> Attribute state on = \eventName, accessors, callback -> - EventListener eventName accessors (Ok (Normal callback)) + EventListener eventName accessors (Normal callback) # Internal helper curriedOn : Str -> (List CyclicStructureAccessor, (state, List (List U8) -> Action state) -> Attribute state) curriedOn = \eventName -> \accessors, callback -> - EventListener eventName accessors (Ok (Normal callback)) + EventListener eventName accessors (Normal callback) onClick = curriedOn "click" onDoubleClick = curriedOn "dblclick" @@ -61,7 +61,7 @@ onInput = \accessors, callback -> preventDefault: Bool.false, } - EventListener "input" accessors (Ok (Custom customCallback)) + EventListener "input" accessors (Custom customCallback) onSubmit : List CyclicStructureAccessor, (state, List (List U8) -> Action state) -> Attribute state onSubmit = \accessors, callback -> @@ -71,7 +71,7 @@ onSubmit = \accessors, callback -> preventDefault: Bool.true, } - EventListener "submit" accessors (Ok (Custom customCallback)) + EventListener "submit" accessors (Custom customCallback) # Notes from Elm: # - stopPropagation causes immediate view update, without waiting for animationFrame, diff --git a/examples/virtual-dom-wip/platform/Html/Internal/Client.roc b/examples/virtual-dom-wip/platform/Html/Internal/Client.roc index 90cf0021c5..fe719e195c 100644 --- a/examples/virtual-dom-wip/platform/Html/Internal/Client.roc +++ b/examples/virtual-dom-wip/platform/Html/Internal/Client.roc @@ -84,7 +84,7 @@ DiffState state : { rendered : RenderedTree state, patches : List Patch } # ------------------------------- # INITIALISATION # ------------------------------- -initClientApp : List U8, App state initData -> Effect (PlatformState state initData) | initData has Decoding +initClientApp : List U8, App state initData -> Effect (PlatformState state initData) where initData implements Decoding initClientApp = \json, app -> # Initialise the Roc representation of the rendered DOM, and calculate patches (for event listeners) { state, rendered, patches } = @@ -100,7 +100,7 @@ initClientApp = \json, app -> } # Testable helper function to initialise the app -initClientAppHelp : List U8, App state initData -> { state, rendered : RenderedTree state, patches : List Patch } | initData has Decoding +initClientAppHelp : List U8, App state initData -> { state, rendered : RenderedTree state, patches : List Patch } where initData implements Decoding initClientAppHelp = \json, app -> state = json @@ -200,7 +200,7 @@ JsEventResult state initData : { } ## Dispatch a JavaScript event to a Roc handler, given the handler ID and some JSON event data. -dispatchEvent : PlatformState state initData, List (List U8), HandlerId -> Effect (JsEventResult state initData) | initData has Decoding +dispatchEvent : PlatformState state initData, List (List U8), HandlerId -> Effect (JsEventResult state initData) where initData implements Decoding dispatchEvent = \platformState, eventData, handlerId -> { app, state, rendered } = platformState diff --git a/examples/virtual-dom-wip/platform/Html/Internal/Server.roc b/examples/virtual-dom-wip/platform/Html/Internal/Server.roc index 5e5cd90f62..aedd397af7 100644 --- a/examples/virtual-dom-wip/platform/Html/Internal/Server.roc +++ b/examples/virtual-dom-wip/platform/Html/Internal/Server.roc @@ -57,7 +57,7 @@ appendRenderedStaticAttr = \{ buffer, styles }, attr -> # ------------------------------- # INITIALISATION # ------------------------------- -initServerApp : App state initData, initData, Str -> Result (Html []) [InvalidDocument] | initData has Encoding +initServerApp : App state initData, initData, Str -> Result (Html []) [InvalidDocument] where initData implements Encoding initServerApp = \app, initData, hostJavaScript -> initData |> Ok @@ -66,7 +66,7 @@ initServerApp = \app, initData, hostJavaScript -> |> translateStatic |> insertRocScript initData app.wasmUrl hostJavaScript -insertRocScript : Html [], initData, Str, Str -> Result (Html []) [InvalidDocument] | initData has Encoding +insertRocScript : Html [], initData, Str, Str -> Result (Html []) [InvalidDocument] where initData implements Encoding insertRocScript = \document, initData, wasmUrl, hostJavaScript -> encode = \value -> diff --git a/examples/virtual-dom-wip/platform/client-side.roc b/examples/virtual-dom-wip/platform/client-side.roc index 02bf4f7559..bfa0c19fb8 100644 --- a/examples/virtual-dom-wip/platform/client-side.roc +++ b/examples/virtual-dom-wip/platform/client-side.roc @@ -26,7 +26,7 @@ ToHost state initData : { } # TODO: naming the type variables causes a type 'mismatch' -# main : FromHost state initData -> Effect (ToHost state initData) | initData has Decoding & Encoding +# main : FromHost state initData -> Effect (ToHost state initData) where initData implements Decoding & Encoding main : FromHost _ _ -> Effect (ToHost _ _) main = \fromHost -> if fromHost.isInitEvent then diff --git a/flake.nix b/flake.nix index a8be3b40e1..091c11bb1c 100644 --- a/flake.nix +++ b/flake.nix @@ -56,6 +56,7 @@ Foundation Metal Security + curl # for wasm-bindgen-cli libcurl (see ./ci/www-repl.sh) ]); # For debugging LLVM IR @@ -125,9 +126,15 @@ [ ]); LLVM_SYS_130_PREFIX = "${llvmPkgs.llvm.dev}"; + # nix does not store libs in /usr/lib or /lib + # for libgcc_s.so.1 + NIX_LIBGCC_S_PATH = + if pkgs.stdenv.isLinux then "${pkgs.stdenv.cc.cc.lib}/lib" else ""; + # for crti.o, crtn.o, and Scrt1.o NIX_GLIBC_PATH = if pkgs.stdenv.isLinux then "${pkgs.glibc.out}/lib" else ""; + LD_LIBRARY_PATH = with pkgs; lib.makeLibraryPath ([ pkg-config stdenv.cc.cc.lib libffi ncurses zlib ] @@ -136,7 +143,7 @@ 1; # to run the editor with NVIDIA's closed source drivers shellHook = '' - source <(echo "${aliases}") + ${aliases} ''; }; diff --git a/www/build.sh b/www/build.sh index a5581ce069..ff1b92f33d 100755 --- a/www/build.sh +++ b/www/build.sh @@ -23,7 +23,7 @@ DESIGN_ASSETS_COMMIT="4d949642ebc56ca455cf270b288382788bce5873" DESIGN_ASSETS_TARFILE="roc-lang-design-assets-4d94964.tar.gz" DESIGN_ASSETS_DIR="roc-lang-design-assets-4d94964" -curl -fLJO https://github.com/roc-lang/design-assets/tarball/$DESIGN_ASSETS_COMMIT +curl -fLJO https://github.com/roc-lang/design-assets/tarball/$DESIGN_ASSETS_COMMIT tar -xzf $DESIGN_ASSETS_TARFILE mv $DESIGN_ASSETS_DIR/fonts build/ rm -rf $DESIGN_ASSETS_TARFILE $DESIGN_ASSETS_DIR @@ -71,7 +71,7 @@ if ! [ -v GITHUB_TOKEN_READ_ONLY ]; then roc=target/release/roc else echo 'Fetching latest roc nightly...' - + # get roc release archive curl -fOL https://github.com/roc-lang/roc/releases/download/nightly/roc_nightly-linux_x86_64-latest.tar.gz # extract archive @@ -124,7 +124,7 @@ if [ -v GITHUB_TOKEN_READ_ONLY ]; then curl -v -H "Authorization: $GITHUB_TOKEN_READ_ONLY" -fL -o basic_cli_releases.json "https://api.github.com/repos/roc-lang/basic-cli/releases" DOCS_LINKS=$(cat basic_cli_releases.json | jq -r '.[] | .assets[] | select(.name=="docs.tar.gz") | .browser_download_url') - + rm basic_cli_releases.json VERSION_NUMBERS=$(echo "$DOCS_LINKS" | grep -oP '(?<=/download/)[^/]+(?=/docs.tar.gz)') diff --git a/www/generate_tutorial/src/input/tutorial.md b/www/generate_tutorial/src/input/tutorial.md index 6ed341202c..da7cbeac2f 100644 --- a/www/generate_tutorial/src/input/tutorial.md +++ b/www/generate_tutorial/src/input/tutorial.md @@ -131,7 +131,7 @@ Make a file named `main.roc` and put this in it: ```roc app "hello" - packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.4.0/DI4lqn7LIZs8ZrCDUgLK-tHHpQmxGF1ZrlevRKq5LXk.tar.br" } + packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.5.0/Cufzl36_SnJ4QbOoEmiJ5dIpUxBvdB3NEySvuH82Wio.tar.br" } imports [pf.Stdout] provides [main] to pf @@ -1376,7 +1376,7 @@ Let's take a closer look at the part of `main.roc` above the `main` def: ```roc app "hello" - packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.4.0/DI4lqn7LIZs8ZrCDUgLK-tHHpQmxGF1ZrlevRKq5LXk.tar.br" } + packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.5.0/Cufzl36_SnJ4QbOoEmiJ5dIpUxBvdB3NEySvuH82Wio.tar.br" } imports [pf.Stdout] provides [main] to pf ``` @@ -1388,7 +1388,7 @@ The line `app "hello"` states that this module defines a Roc application, and th The remaining lines all involve the [platform](https://github.com/roc-lang/roc/wiki/Roc-concepts-explained#platform) this application is built on: ```roc -packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.4.0/DI4lqn7LIZs8ZrCDUgLK-tHHpQmxGF1ZrlevRKq5LXk.tar.br" } +packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.5.0/Cufzl36_SnJ4QbOoEmiJ5dIpUxBvdB3NEySvuH82Wio.tar.br" } imports [pf.Stdout] provides [main] to pf ``` @@ -1474,7 +1474,7 @@ Let's start with a basic "Hello World" program. ```roc app "cli-tutorial" - packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.4.0/DI4lqn7LIZs8ZrCDUgLK-tHHpQmxGF1ZrlevRKq5LXk.tar.br" } + packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.5.0/Cufzl36_SnJ4QbOoEmiJ5dIpUxBvdB3NEySvuH82Wio.tar.br" } imports [pf.Stdout] provides [main] to pf @@ -1504,7 +1504,7 @@ Let's change `main` to read a line from `stdin`, and then print it back out agai ```roc app "cli-tutorial" - packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.4.0/DI4lqn7LIZs8ZrCDUgLK-tHHpQmxGF1ZrlevRKq5LXk.tar.br" } + packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.5.0/Cufzl36_SnJ4QbOoEmiJ5dIpUxBvdB3NEySvuH82Wio.tar.br" } imports [pf.Stdout, pf.Stdin, pf.Task] provides [main] to pf @@ -1545,7 +1545,7 @@ This works, but we can make it a little nicer to read. Let's change it to the fo ```roc app "cli-tutorial" - packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.4.0/DI4lqn7LIZs8ZrCDUgLK-tHHpQmxGF1ZrlevRKq5LXk.tar.br" } + packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.5.0/Cufzl36_SnJ4QbOoEmiJ5dIpUxBvdB3NEySvuH82Wio.tar.br" } imports [pf.Stdout, pf.Stdin, pf.Task.{ await }] provides [main] to pf diff --git a/www/generate_tutorial/src/tutorial.roc b/www/generate_tutorial/src/tutorial.roc index 6502d96b11..5d13eb337d 100644 --- a/www/generate_tutorial/src/tutorial.roc +++ b/www/generate_tutorial/src/tutorial.roc @@ -1,5 +1,5 @@ app "roc-tutorial" - packages { pf: "../../../examples/static-site-gen/platform/main.roc" } + packages { pf: "../../../examples/static-site-gen/platform/main.roc" } imports [ pf.Html.{ html, head, body, footer, script, div, main, p, section, h1, h2, label, ol, input, text, nav, a, li, link, meta }, pf.Html.Attributes.{ content, name, for, id, type, href, rel, lang, class, title, charset, src }, @@ -28,7 +28,7 @@ view = \htmlContent -> text htmlContent, ], footer [] [ - text "Made by people who like to make nice things. © 2023" + text "Made by people who like to make nice things." ] ], script [src "/site.js"] [], @@ -62,26 +62,26 @@ viewTutorialStart = tocLinks = { tag, value } <- List.map [ - { tag: "#installation", value: "Installation" }, - { tag: "#strings-and-numbers", value: "Strings and Numbers" }, - { tag: "#building-an-application", value: "Building an Application" }, - { tag: "#defining-functions", value: "Defining Functions" }, - { tag: "#if-then-else", value: "if-then-else" }, - { tag: "#debugging", value: "Debugging" }, - { tag: "#records", value: "Records" }, - { tag: "#tags", value: "Tags & Pattern Matching" }, - { tag: "#booleans", value: "Booleans" }, - { tag: "#lists", value: "Lists" }, - { tag: "#types", value: "Types" }, - { tag: "#numeric-types", value: "Numeric Types" }, - { tag: "#crashing", value: "Crashing" }, - { tag: "#tests-and-expectations", value: "Tests and Expectations" }, - { tag: "#modules", value: "Modules" }, - { tag: "#tasks", value: "Tasks" }, - { tag: "#abilities", value: "Abilities" }, - { tag: "#appendix-advanced-concepts", value: "Advanced Concepts" }, - { tag: "#operator-desugaring-table", value: "Operator Desugaring Table" }, - ] + { tag: "#installation", value: "Installation" }, + { tag: "#strings-and-numbers", value: "Strings and Numbers" }, + { tag: "#building-an-application", value: "Building an Application" }, + { tag: "#defining-functions", value: "Defining Functions" }, + { tag: "#if-then-else", value: "if-then-else" }, + { tag: "#debugging", value: "Debugging" }, + { tag: "#records", value: "Records" }, + { tag: "#tags", value: "Tags & Pattern Matching" }, + { tag: "#booleans", value: "Booleans" }, + { tag: "#lists", value: "Lists" }, + { tag: "#types", value: "Types" }, + { tag: "#numeric-types", value: "Numeric Types" }, + { tag: "#crashing", value: "Crashing" }, + { tag: "#tests-and-expectations", value: "Tests and Expectations" }, + { tag: "#modules", value: "Modules" }, + { tag: "#tasks", value: "Tasks" }, + { tag: "#abilities", value: "Abilities" }, + { tag: "#appendix-advanced-concepts", value: "Advanced Concepts" }, + { tag: "#operator-desugaring-table", value: "Operator Desugaring Table" }, + ] li [] [ a [href tag] [text value], @@ -98,8 +98,8 @@ tutorialIntro = p [] [text "This tutorial will teach you how to build Roc applications. Along the way, you'll learn how to write tests, use the REPL, and more!"], ], section [] [ - h2 [ id "installation" ] [ - a [href "#installation"] [text "Installation"] + h2 [id "installation"] [ + a [href "#installation"] [text "Installation"], ], p [] [ text "Roc doesn’t have a numbered release or an installer yet, but you can follow the install instructions for your OS", @@ -108,7 +108,7 @@ tutorialIntro = a [href "https://roc.zulipchat.com/#narrow/stream/231634-beginners"] [text " #beginners "], text "on", a [href "https://roc.zulipchat.com/"] [text " Roc Zulip Chat "], - text "and ask for assistance!" - ] + text "and ask for assistance!", + ], ], ] diff --git a/www/wip_new_website/README.md b/www/wip_new_website/README.md new file mode 100644 index 0000000000..bef0305d16 --- /dev/null +++ b/www/wip_new_website/README.md @@ -0,0 +1,30 @@ + +# Getting Started + +## Prerequisites + +- Linux or MacOS operating system, Windows users can use linux through WSL. +- Install [git](https://chat.openai.com/share/71fb3ae6-80d7-478c-8a27-a36aaa5ba921) +- Install [nix](https://nixos.org/download.html) + +## Building the website from scratch + +```bash +git clone https://github.com/roc-lang/roc.git +cd roc +nix develop +./www/build.sh +# make the roc command available +export PATH="$(pwd)/target/release/:$PATH" +cd www/wip_new_website +roc build.roc +``` + +Open http://0.0.0.0:8080/wip in your browser. + +## After you've made a change + +In the terminal where `roc build.roc` is running: +1. kill the server with Ctrl+C +2. run `roc build.roc` +3. refresh the page in your browser \ No newline at end of file diff --git a/www/wip_new_website/build.roc b/www/wip_new_website/build.roc index ab4bd61551..b5b5566154 100755 --- a/www/wip_new_website/build.roc +++ b/www/wip_new_website/build.roc @@ -1,6 +1,6 @@ #!/usr/bin/env roc app "website-builder" - packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.4.0/DI4lqn7LIZs8ZrCDUgLK-tHHpQmxGF1ZrlevRKq5LXk.tar.br" } + packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.5.0/Cufzl36_SnJ4QbOoEmiJ5dIpUxBvdB3NEySvuH82Wio.tar.br" } imports [ pf.Task.{ Task }, pf.Command, diff --git a/www/wip_new_website/content/index.md b/www/wip_new_website/content/index.md index 7df0ac858a..daf3d7d9dc 100644 --- a/www/wip_new_website/content/index.md +++ b/www/wip_new_website/content/index.md @@ -1,7 +1,7 @@ # Roc -Work in progress! +A work-in-progress programming language that aims to be fast, friendly, and functional. - [tutorial](/wip/tutorial.html) @@ -10,35 +10,35 @@ Work in progress! - [help / group chat](https://roc.zulipchat.com), we're friendly! -## Goals - +## Goals
-

Fast

-

Runs fast, compiles fast.
Learn more

+

Fast

+

Delightful software runs fast. The Roc compiler should run fast, and it should be able to produce programs that run fast too. What does fast mean here?

Friendly

-

User-friendly language, friendly community.
Learn more

+

Friendly

+

Roc aims to be a user-friendly language with a friendly community of users. This involves the set of tools Roc includes, and also the spirit of the community of Roc programmers. What does friendly mean here?

Functional

-

Pure functional programming, keep it simple.
Learn more

+

Roc is a purely functional programming language. The language is built on a small set of simple primitives, which together give you a toolset that's more than the sum of its parts. What does functional mean here?

## Try Roc -The code below shows a Roc application which prints `Hello World!` to the terminal. It does this using the [roc-lang/basic-cli](https://github.com/roc-lang/basic-cli) platform. +The code below shows a Roc application which prints `Hello World!` to the terminal. It does this using the [roc-lang/basic-cli](https://github.com/roc-lang/basic-cli) platform. ```roc app "hello-world" - packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.3.2/tE4xS_zLdmmxmHwHih9kHWQ7fsXtJr7W7h3425-eZFk.tar.br" } + packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.5.0/Cufzl36_SnJ4QbOoEmiJ5dIpUxBvdB3NEySvuH82Wio.tar.br" } imports [pf.Stdout] provides [main] to pf -main = +main = Stdout.line "Hello, World!" ``` diff --git a/www/wip_new_website/content/install.md b/www/wip_new_website/content/install.md index ae76396cae..7ce61eec31 100644 --- a/www/wip_new_website/content/install.md +++ b/www/wip_new_website/content/install.md @@ -31,9 +31,10 @@ You can include packages using an URL: app "hello" packages { # basic-cli platform - pf: "https://github.com/roc-lang/basic-cli/releases/download/0.4.0/DI4lqn7LIZs8ZrCDUgLK-tHHpQmxGF1ZrlevRKq5LXk.tar.br", + pf: "https://github.com/roc-lang/basic-cli/releases/download/0.5.0/Cufzl36_SnJ4QbOoEmiJ5dIpUxBvdB3NEySvuH82Wio.tar.br", # json package - json: "https://github.com/lukewilliamboswell/roc-json/releases/download/0.1.0/xbO9bXdHi7E9ja6upN5EJXpDoYm7lwmJ8VzL7a5zhYE.tar.br", + # TODO update to json 0.3.0 + json: "https://github.com/lukewilliamboswell/roc-json/releases/download/0.2.0/gh4zvR8xyEsef0R961Fcv5vxFEZJ-GJF-7bQwgL2Xz8.tar.br", } imports [ pf.Stdout, diff --git a/www/wip_new_website/main.roc b/www/wip_new_website/main.roc index 7ffaf0dded..494b5fd494 100644 --- a/www/wip_new_website/main.roc +++ b/www/wip_new_website/main.roc @@ -1,13 +1,13 @@ app "roc-website" - packages { pf: "../../examples/static-site-gen/platform/main.roc" } + packages { pf: "../../examples/static-site-gen/platform/main.roc" } imports [ - pf.Html.{ html, head, body, footer, br, div, main, text, nav, a, link, meta }, + pf.Html.{ html, head, body, footer, div, main, text, nav, a, link, meta }, pf.Html.Attributes.{ content, name, id, href, rel, lang, class, title, charset }, ] provides [transformFileContent] to pf -pageData = - Dict.empty {} +pageData = + Dict.empty {} |> Dict.insert "community.html" { title: "Community", description: "The Roc community" } |> Dict.insert "design_goals.html" { title: "Design Goals", description: "Roc's design goals" } |> Dict.insert "docs.html" { title: "Documentation", description: "Learn the Roc programming language" } @@ -22,11 +22,11 @@ getPage = \current -> |> Result.withDefault { title: "", description: ""} getTitle : Str -> Str -getTitle = \current -> +getTitle = \current -> getPage current |> .title getDescription : Str -> Str -getDescription = \current -> +getDescription = \current -> getPage current |> .description transformFileContent : Str, Str -> Str @@ -78,7 +78,7 @@ viewNavbar = ], ] -rocLogo = +rocLogo = (Html.element "svg") [ (Html.attribute "viewBox") "0 -6 51 58", (Html.attribute "xmlns") "http://www.w3.org/2000/svg",