Update to use new square brace formatting

This commit is contained in:
Richard Feldman 2022-05-22 22:43:50 -04:00
parent 0fae5b0bac
commit 4eec34becf
No known key found for this signature in database
GPG key ID: 7E4127D1E4241798
120 changed files with 1149 additions and 1155 deletions

View file

@ -3,7 +3,7 @@ platform "test-platform"
exposes [] exposes []
packages {} packages {}
imports [] imports []
provides [ mainForHost ] provides [mainForHost]
MyRcd : { a : U64, b : U128 } MyRcd : { a : U64, b : U128 }

View file

@ -1,6 +1,6 @@
app "app" app "app"
packages { pf: "." } packages { pf: "." }
imports [] imports []
provides [ main ] to pf provides [main] to pf
main = { a: 1995, b: 42 } main = { a: 1995, b: 42 }

View file

@ -3,9 +3,9 @@ platform "test-platform"
exposes [] exposes []
packages {} packages {}
imports [] imports []
provides [ mainForHost ] provides [mainForHost]
MyEnum : [ Foo, Bar, Baz ] MyEnum : [Foo, Bar, Baz]
mainForHost : MyEnum mainForHost : MyEnum
mainForHost = main mainForHost = main

View file

@ -1,6 +1,6 @@
app "app" app "app"
packages { pf: "." } packages { pf: "." }
imports [] imports []
provides [ main ] to pf provides [main] to pf
main = Foo main = Foo

View file

@ -3,7 +3,7 @@ platform "test-platform"
exposes [] exposes []
packages {} packages {}
imports [] imports []
provides [ mainForHost ] provides [mainForHost]
Outer : { x : Inner, y : Str, z : List U8 } Outer : { x : Inner, y : Str, z : List U8 }

View file

@ -1,6 +1,6 @@
app "app" app "app"
packages { pf: "." } packages { pf: "." }
imports [] imports []
provides [ main ] to pf provides [main] to pf
main = { x: { a: 5, b: 24 }, y: "foo", z: [ 1, 2 ] } main = { x: { a: 5, b: 24 }, y: "foo", z: [1, 2] }

View file

@ -3,7 +3,7 @@ platform "test-platform"
exposes [] exposes []
packages {} packages {}
imports [] imports []
provides [ mainForHost ] provides [mainForHost]
# This case is important to test because the U128 # This case is important to test because the U128
# gives the whole struct an alignment of 16, but the # gives the whole struct an alignment of 16, but the
@ -11,7 +11,7 @@ platform "test-platform"
# a size of 32 (due to alignment, rounded up from Str's 24), # a size of 32 (due to alignment, rounded up from Str's 24),
# and the discriminant is stored in the 8+ bytes of padding # and the discriminant is stored in the 8+ bytes of padding
# that all variants have. # that all variants have.
NonRecursive : [ Foo Str, Bar U128, Blah I32, Baz ] NonRecursive : [Foo Str, Bar U128, Blah I32, Baz]
mainForHost : NonRecursive mainForHost : NonRecursive
mainForHost = main mainForHost = main

View file

@ -1,6 +1,6 @@
app "app" app "app"
packages { pf: "." } packages { pf: "." }
imports [] imports []
provides [ main ] to pf provides [main] to pf
main = Foo "This is a test" main = Foo "This is a test"

View file

@ -3,13 +3,13 @@ platform "test-platform"
exposes [] exposes []
packages {} packages {}
imports [] imports []
provides [ mainForHost ] provides [mainForHost]
# This case is important to test because there's no padding # This case is important to test because there's no padding
# after the largest variant, so the compiler adds an extra u8 # after the largest variant, so the compiler adds an extra u8
# (rounded up to alignment, so an an extra 8 bytes) in which # (rounded up to alignment, so an an extra 8 bytes) in which
# to store the discriminant. We have to bindgen accordingly! # to store the discriminant. We have to bindgen accordingly!
NonRecursive : [ Foo Str, Bar I64, Blah I32, Baz ] NonRecursive : [Foo Str, Bar I64, Blah I32, Baz]
mainForHost : NonRecursive mainForHost : NonRecursive
mainForHost = main mainForHost = main

View file

@ -1,6 +1,6 @@
app "app" app "app"
packages { pf: "." } packages { pf: "." }
imports [] imports []
provides [ main ] to pf provides [main] to pf
main = Foo "This is a test" main = Foo "This is a test"

View file

@ -17,7 +17,7 @@ pub fn generate_bindings(decl_src: &str) -> String {
exposes [] exposes []
packages {} packages {}
imports [] imports []
provides [ main ] provides [main]
"# "#
) )

View file

@ -958,7 +958,7 @@ mod cli_run {
Nothing from Symbol is used in this module. Nothing from Symbol is used in this module.
3 imports [ Symbol.{ Ident } ] 3 imports [Symbol.{ Ident }]
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
Since Symbol isn't used, you don't need to import it. Since Symbol isn't used, you don't need to import it.
@ -981,7 +981,7 @@ mod cli_run {
I don't know how to generate the foobar function. I don't know how to generate the foobar function.
4 generates Effect with [ after, map, always, foobar ] 4 generates Effect with [after, map, always, foobar]
^^^^^^ ^^^^^^
Only specific functions like `after` and `map` can be generated.Learn Only specific functions like `after` and `map` can be generated.Learn

View file

@ -1,6 +1,6 @@
app "formatted" app "formatted"
packages { pf: "platform" } packages { pf: "platform" }
provides [ main ] to pf provides [main] to pf
main : Str main : Str
main = Dep1.value1 {} main = Dep1.value1 {}

View file

@ -1,4 +1,4 @@
interface Dep1 exposes [ str1 ] imports [ Dep2 ] interface Dep1 exposes [str1] imports [Dep2]
str1 : Str str1 : Str
str1 = Dep2.str2 str1 = Dep2.str2

View file

@ -1,4 +1,4 @@
interface Dep2 exposes [ str2 ] imports [] interface Dep2 exposes [str2] imports []
str2 : Str str2 : Str
str2 = "I am Dep2.str2" str2 = "I am Dep2.str2"

View file

@ -1,7 +1,7 @@
app "multi-dep-str" app "multi-dep-str"
packages { pf: "platform" } packages { pf: "platform" }
imports [ Dep1 ] imports [Dep1]
provides [ main ] to pf provides [main] to pf
main : Str main : Str
main = Dep1.str1 main = Dep1.str1

View file

@ -3,7 +3,7 @@ platform "multi-module"
exposes [] exposes []
packages {} packages {}
imports [] imports []
provides [ mainForHost ] provides [mainForHost]
mainForHost : Str mainForHost : Str
mainForHost = main mainForHost = main

View file

@ -1,4 +1,4 @@
interface Dep1 exposes [ value1 ] imports [ Dep2 ] interface Dep1 exposes [value1] imports [Dep2]
value1 : {} -> Str value1 : {} -> Str
value1 = \_ -> Dep2.value2 {} value1 = \_ -> Dep2.value2 {}

View file

@ -1,4 +1,4 @@
interface Dep2 exposes [ value2 ] imports [] interface Dep2 exposes [value2] imports []
value2 : {} -> Str value2 : {} -> Str
value2 = \_ -> "I am Dep2.value2" value2 = \_ -> "I am Dep2.value2"

View file

@ -1,7 +1,7 @@
app "multi-dep-thunk" app "multi-dep-thunk"
packages { pf: "platform" } packages { pf: "platform" }
imports [ Dep1 ] imports [Dep1]
provides [ main ] to pf provides [main] to pf
main : Str main : Str
main = Dep1.value1 {} main = Dep1.value1 {}

View file

@ -3,7 +3,7 @@ platform "multi-dep-thunk"
exposes [] exposes []
packages {} packages {}
imports [] imports []
provides [ mainForHost ] provides [mainForHost]
mainForHost : Str mainForHost : Str
mainForHost = main mainForHost = main

View file

@ -1,3 +1,3 @@
interface Foo interface Foo
exposes [ bar ] exposes [bar]
imports [] imports []

View file

@ -1,5 +1,5 @@
interface Symbol interface Symbol
exposes [ Ident ] exposes [Ident]
imports [] imports []
# NOTE: this module is fine, but used by UnusedImport.roc to uselessly import # NOTE: this module is fine, but used by UnusedImport.roc to uselessly import

View file

@ -1,7 +1,7 @@
app "type-error" app "type-error"
packages { pf: "platform" } packages { pf: "platform" }
imports [ pf.Stdout.{ line }, pf.Task.{ await } ] imports [pf.Stdout.{ line }, pf.Task.{ await }]
provides [ main ] to pf provides [main] to pf
main = main =
_ <- await (line "a") _ <- await (line "a")

View file

@ -1,4 +1,4 @@
hosted UnknownGeneratesWith hosted UnknownGeneratesWith
exposes [ Effect, after, map, always ] exposes [Effect, after, map, always]
imports [] imports []
generates Effect with [ after, map, always, foobar ] generates Effect with [after, map, always, foobar]

View file

@ -1,6 +1,6 @@
interface UnusedImport interface UnusedImport
exposes [ plainText, emText ] exposes [plainText, emText]
imports [ Symbol.{ Ident } ] imports [Symbol.{ Ident }]
plainText = \str -> PlainText str plainText = \str -> PlainText str

File diff suppressed because one or more lines are too long

View file

@ -10,7 +10,7 @@ Some of these have `#` inside their name (`first#list`, `#lt` ..). This is a tri
But we can use these values and some of these are necessary for implementing builtins. For example, `List.get` returns tags, and it is not easy for us to create tags when composing LLVM. What is easier however, is: But we can use these values and some of these are necessary for implementing builtins. For example, `List.get` returns tags, and it is not easy for us to create tags when composing LLVM. What is easier however, is:
- ..writing `List.#getUnsafe` that has the dangerous signature of `List elem, Nat -> elem` in LLVM - ..writing `List.#getUnsafe` that has the dangerous signature of `List elem, Nat -> elem` in LLVM
- ..writing `List elem, Nat -> Result elem [ OutOfBounds ]*` in a type safe way that uses `getUnsafe` internally, only after it checks if the `elem` at `Nat` index exists. - ..writing `List elem, Nat -> Result elem [OutOfBounds]*` in a type safe way that uses `getUnsafe` internally, only after it checks if the `elem` at `Nat` index exists.
### can/src/builtins.rs ### can/src/builtins.rs

View file

@ -705,7 +705,7 @@ pub fn listWalkUntil(
dec: Dec, dec: Dec,
output: Opaque, output: Opaque,
) callconv(.C) void { ) callconv(.C) void {
// [ Continue a, Stop a ] // [Continue a, Stop a]
if (accum_width == 0) { if (accum_width == 0) {
return; return;
@ -734,7 +734,7 @@ pub fn listWalkUntil(
caller(data, bytes_ptr, element, bytes_ptr); caller(data, bytes_ptr, element, bytes_ptr);
// [ Continue ..., Stop ] // [Continue ..., Stop]
const tag_id = has_tag_id(0, bytes_ptr); const tag_id = has_tag_id(0, bytes_ptr);
if (!tag_id.matched) { if (!tag_id.matched) {

View file

@ -547,7 +547,7 @@ fn strSplitInPlace(array: [*]RocStr, string: RocStr, delimiter: RocStr) void {
} }
test "strSplitInPlace: empty delimiter" { test "strSplitInPlace: empty delimiter" {
// Str.split "abc" "" == [ "abc" ] // Str.split "abc" "" == ["abc"]
const str_arr = "abc"; const str_arr = "abc";
const str = RocStr.init(str_arr, str_arr.len); const str = RocStr.init(str_arr, str_arr.len);
@ -581,7 +581,7 @@ test "strSplitInPlace: empty delimiter" {
} }
test "strSplitInPlace: no delimiter" { test "strSplitInPlace: no delimiter" {
// Str.split "abc" "!" == [ "abc" ] // Str.split "abc" "!" == ["abc"]
const str_arr = "abc"; const str_arr = "abc";
const str = RocStr.init(str_arr, str_arr.len); const str = RocStr.init(str_arr, str_arr.len);
@ -700,7 +700,7 @@ test "strSplitInPlace: delimiter on sides" {
} }
test "strSplitInPlace: three pieces" { test "strSplitInPlace: three pieces" {
// Str.split "a!b!c" "!" == [ "a", "b", "c" ] // Str.split "a!b!c" "!" == ["a", "b", "c"]
const str_arr = "a!b!c"; const str_arr = "a!b!c";
const str = RocStr.init(str_arr, str_arr.len); const str = RocStr.init(str_arr, str_arr.len);
@ -786,7 +786,7 @@ pub fn countSegments(string: RocStr, delimiter: RocStr) callconv(.C) usize {
} }
test "countSegments: long delimiter" { test "countSegments: long delimiter" {
// Str.split "str" "delimiter" == [ "str" ] // Str.split "str" "delimiter" == ["str"]
// 1 segment // 1 segment
const str_arr = "str"; const str_arr = "str";
const str = RocStr.init(str_arr, str_arr.len); const str = RocStr.init(str_arr, str_arr.len);
@ -804,7 +804,7 @@ test "countSegments: long delimiter" {
} }
test "countSegments: delimiter at start" { test "countSegments: delimiter at start" {
// Str.split "hello there" "hello" == [ "", " there" ] // Str.split "hello there" "hello" == ["", " there"]
// 2 segments // 2 segments
const str_arr = "hello there"; const str_arr = "hello there";
const str = RocStr.init(str_arr, str_arr.len); const str = RocStr.init(str_arr, str_arr.len);
@ -823,7 +823,7 @@ test "countSegments: delimiter at start" {
} }
test "countSegments: delimiter interspered" { test "countSegments: delimiter interspered" {
// Str.split "a!b!c" "!" == [ "a", "b", "c" ] // Str.split "a!b!c" "!" == ["a", "b", "c"]
// 3 segments // 3 segments
const str_arr = "a!b!c"; const str_arr = "a!b!c";
const str = RocStr.init(str_arr, str_arr.len); const str = RocStr.init(str_arr, str_arr.len);

View file

@ -54,7 +54,7 @@ interface Dict
## |> Dict.remove "Philadelphia" ## |> Dict.remove "Philadelphia"
## |> Dict.keys ## |> Dict.keys
## == ## ==
## [ "London", "Amsterdam", "Shanghai", "Delhi" ] ## ["London", "Amsterdam", "Shanghai", "Delhi"]
## ##
## Notice that the order changed! Philadelphia has been not only removed from the list, but Amsterdam - the last ## Notice that the order changed! Philadelphia has been not only removed from the list, but Amsterdam - the last
## entry we inserted - has been moved into the spot where Philadelphia was previously. This is exactly what ## entry we inserted - has been moved into the spot where Philadelphia was previously. This is exactly what

View file

@ -59,9 +59,9 @@ interface List
## Types ## Types
## A sequential list of values. ## A sequential list of values.
## ##
## >>> [ 1, 2, 3 ] # a list of numbers ## >>> [1, 2, 3] # a list of numbers
## >>> [ "a", "b", "c" ] # a list of strings ## >>> ["a", "b", "c"] # a list of strings
## >>> [ [ 1.1 ], [], [ 2.2, 3.3 ] ] # a list of lists of numbers ## >>> [[1.1], [], [2.2, 3.3]] # a list of lists of numbers
## ##
## The maximum size of a [List] is limited by the amount of heap memory available ## The maximum size of a [List] is limited by the amount of heap memory available
## to the current process. If there is not enough memory available, attempting to ## to the current process. If there is not enough memory available, attempting to
@ -92,11 +92,11 @@ interface List
## ##
## Let's look at an example. ## Let's look at an example.
## ##
## ratings = [ 5, 4, 3 ] ## ratings = [5, 4, 3]
## ##
## { foo: ratings, bar: ratings } ## { foo: ratings, bar: ratings }
## ##
## The first line binds the name `ratings` to the list `[ 5, 4, 3 ]`. The list ## The first line binds the name `ratings` to the list `[5, 4, 3]`. The list
## begins with a refcount of 1, because so far only `ratings` is referencing it. ## begins with a refcount of 1, because so far only `ratings` is referencing it.
## ##
## The second line alters this refcount. `{ foo: ratings` references ## The second line alters this refcount. `{ foo: ratings` references
@ -107,7 +107,7 @@ interface List
## Let's turn this example into a function. ## Let's turn this example into a function.
## ##
## getRatings = \first -> ## getRatings = \first ->
## ratings = [ first, 4, 3 ] ## ratings = [first, 4, 3]
## ##
## { foo: ratings, bar: ratings } ## { foo: ratings, bar: ratings }
## ##
@ -129,7 +129,7 @@ interface List
## Let's change the last line to be `(getRatings 5).bar` instead of `getRatings 5`: ## Let's change the last line to be `(getRatings 5).bar` instead of `getRatings 5`:
## ##
## getRatings = \first -> ## getRatings = \first ->
## ratings = [ first, 4, 3 ] ## ratings = [first, 4, 3]
## ##
## { foo: ratings, bar: ratings } ## { foo: ratings, bar: ratings }
## ##
@ -155,7 +155,7 @@ interface List
## ##
## Here's the example using a list of numbers. ## Here's the example using a list of numbers.
## ##
## nums = [ 1, 2, 3, 4, 5, 6, 7 ] ## nums = [1, 2, 3, 4, 5, 6, 7]
## ##
## first = List.first nums ## first = List.first nums
## last = List.last nums ## last = List.last nums
@ -166,7 +166,7 @@ interface List
## ##
## Here's the equivalent code with a list of lists: ## Here's the equivalent code with a list of lists:
## ##
## lists = [ [ 1 ], [ 2, 3 ], [], [ 4, 5, 6, 7 ] ] ## lists = [[1], [2, 3], [], [4, 5, 6, 7]]
## ##
## first = List.first lists ## first = List.first lists
## last = List.last lists ## last = List.last lists
@ -181,7 +181,7 @@ interface List
## because the function returned `first`, that element will actually end up ## because the function returned `first`, that element will actually end up
## *not* getting freed at the end - but all the others will be. ## *not* getting freed at the end - but all the others will be.
## ##
## In the `lists` example, `lists = [ ... ]` also creates a list with an initial ## In the `lists` example, `lists = [...]` also creates a list with an initial
## refcount of 1. Separately, it also creates several other lists - each with ## refcount of 1. Separately, it also creates several other lists - each with
## their own refcounts - to go inside that list. (The empty list at the end ## their own refcounts - to go inside that list. (The empty list at the end
## does not use heap memory, and thus has no refcount.) ## does not use heap memory, and thus has no refcount.)
@ -194,7 +194,7 @@ interface List
## * If possible, it is usually best for performance to use large lists in a way where the optimizer can turn them into in-place mutations. If this is not possible, a persistent data structure might be faster - but this is a rare enough scenario that it would not be good for the average Roc program's performance if this were the way [List] worked by default. Instead, you can look outside Roc's standard modules for an implementation of a persistent data structure - likely built using [List] under the hood! ## * If possible, it is usually best for performance to use large lists in a way where the optimizer can turn them into in-place mutations. If this is not possible, a persistent data structure might be faster - but this is a rare enough scenario that it would not be good for the average Roc program's performance if this were the way [List] worked by default. Instead, you can look outside Roc's standard modules for an implementation of a persistent data structure - likely built using [List] under the hood!
## Check if the list is empty. ## Check if the list is empty.
## ##
## >>> List.isEmpty [ 1, 2, 3 ] ## >>> List.isEmpty [1, 2, 3]
## ##
## >>> List.isEmpty [] ## >>> List.isEmpty []
isEmpty : List a -> Bool isEmpty : List a -> Bool
@ -206,7 +206,7 @@ replace : List a, Nat, a -> { list : List a, value : a }
## Replaces the element at the given index with a replacement. ## Replaces the element at the given index with a replacement.
## ##
## >>> List.set [ "a", "b", "c" ] 1 "B" ## >>> List.set ["a", "b", "c"] 1 "B"
## ##
## If the given index is outside the bounds of the list, returns the original ## If the given index is outside the bounds of the list, returns the original
## list unmodified. ## list unmodified.
@ -218,17 +218,17 @@ set = \list, index, value ->
## Add a single element to the end of a list. ## Add a single element to the end of a list.
## ##
## >>> List.append [ 1, 2, 3 ] 4 ## >>> List.append [1, 2, 3] 4
## ##
## >>> [ 0, 1, 2 ] ## >>> [0, 1, 2]
## >>> |> List.append 3 ## >>> |> List.append 3
append : List a, a -> List a append : List a, a -> List a
## Add a single element to the beginning of a list. ## Add a single element to the beginning of a list.
## ##
## >>> List.prepend [ 1, 2, 3 ] 0 ## >>> List.prepend [1, 2, 3] 0
## ##
## >>> [ 2, 3, 4 ] ## >>> [2, 3, 4]
## >>> |> List.prepend 1 ## >>> |> List.prepend 1
prepend : List a, a -> List a prepend : List a, a -> List a
@ -241,10 +241,10 @@ len : List a -> Nat
## Put two lists together. ## Put two lists together.
## ##
## >>> List.concat [ 1, 2, 3 ] [ 4, 5 ] ## >>> List.concat [1, 2, 3] [4, 5]
## ##
## >>> [ 0, 1, 2 ] ## >>> [0, 1, 2]
## >>> |> List.concat [ 3, 4 ] ## >>> |> List.concat [3, 4]
concat : List a, List a -> List a concat : List a, List a -> List a
## Returns the last element in the list, or `ListWasEmpty` if it was empty. ## Returns the last element in the list, or `ListWasEmpty` if it was empty.
@ -266,14 +266,14 @@ repeat : a, Nat -> List a
## Returns the list with its elements reversed. ## Returns the list with its elements reversed.
## ##
## >>> List.reverse [ 1, 2, 3 ] ## >>> List.reverse [1, 2, 3]
reverse : List a -> List a reverse : List a -> List a
## Join the given lists together into one list. ## Join the given lists together into one list.
## ##
## >>> List.join [ [ 1, 2, 3 ], [ 4, 5 ], [], [ 6, 7 ] ] ## >>> List.join [[1, 2, 3], [4, 5], [], [6, 7]]
## ##
## >>> List.join [ [], [] ] ## >>> List.join [[], []]
## ##
## >>> List.join [] ## >>> List.join []
join : List (List a) -> List a join : List (List a) -> List a
@ -287,7 +287,7 @@ contains : List a, a -> Bool
## ##
## You can use it in a pipeline: ## You can use it in a pipeline:
## ##
## [ 2, 4, 8 ] ## [2, 4, 8]
## |> List.walk { start: 0, step: Num.add } ## |> List.walk { start: 0, step: Num.add }
## ##
## This returns 14 because: ## This returns 14 because:
@ -295,7 +295,7 @@ contains : List a, a -> Bool
## * Each `step` runs `Num.add state elem`, and the return value becomes the new `state`. ## * Each `step` runs `Num.add state elem`, and the return value becomes the new `state`.
## ##
## Here is a table of how `state` changes as [List.walk] walks over the elements ## Here is a table of how `state` changes as [List.walk] walks over the elements
## `[ 2, 4, 8 ]` using #Num.add as its `step` function to determine the next `state`. ## `[2, 4, 8]` using #Num.add as its `step` function to determine the next `state`.
## ##
## `state` | `elem` | `step state elem` (`Num.add state elem`) ## `state` | `elem` | `step state elem` (`Num.add state elem`)
## --------+--------+----------------------------------------- ## --------+--------+-----------------------------------------
@ -308,7 +308,7 @@ contains : List a, a -> Bool
## 1. `0` (because of `start: 0`) ## 1. `0` (because of `start: 0`)
## 2. `1` (because of `Num.add state elem` with `state` = 0 and `elem` = 1 ## 2. `1` (because of `Num.add state elem` with `state` = 0 and `elem` = 1
## ##
## [ 1, 2, 3 ] ## [1, 2, 3]
## |> List.walk { start: 0, step: Num.sub } ## |> List.walk { start: 0, step: Num.sub }
## ##
## This returns -6 because ## This returns -6 because
@ -353,7 +353,7 @@ all : List a, (a -> Bool) -> Bool
## Run the given function on each element of a list, and return all the ## Run the given function on each element of a list, and return all the
## elements for which the function returned `True`. ## elements for which the function returned `True`.
## ##
## >>> List.keepIf [ 1, 2, 3, 4 ] (\num -> num > 2) ## >>> List.keepIf [1, 2, 3, 4] (\num -> num > 2)
## ##
## ## Performance Details ## ## Performance Details
## ##
@ -376,7 +376,7 @@ keepIf : List a, (a -> Bool) -> List a
## Run the given function on each element of a list, and return all the ## Run the given function on each element of a list, and return all the
## elements for which the function returned `False`. ## elements for which the function returned `False`.
## ##
## >>> List.dropIf [ 1, 2, 3, 4 ] (\num -> num > 2) ## >>> List.dropIf [1, 2, 3, 4] (\num -> num > 2)
## ##
## ## Performance Details ## ## Performance Details
## ##
@ -389,29 +389,29 @@ dropIf = \list, predicate ->
## This works like [List.map], except only the transformed values that are ## This works like [List.map], except only the transformed values that are
## wrapped in `Ok` are kept. Any that are wrapped in `Err` are dropped. ## wrapped in `Ok` are kept. Any that are wrapped in `Err` are dropped.
## ##
## >>> List.keepOks [ [ "a", "b" ], [], [], [ "c", "d", "e" ] ] List.last ## >>> List.keepOks [["a", "b"], [], [], ["c", "d", "e"]] List.last
## ##
## >>> fn = \str -> if Str.isEmpty str then Err StrWasEmpty else Ok (Str.len str) ## >>> fn = \str -> if Str.isEmpty str then Err StrWasEmpty else Ok (Str.len str)
## >>> ## >>>
## >>> List.keepOks [ "", "a", "bc", "", "d", "ef", "" ] ## >>> List.keepOks ["", "a", "bc", "", "d", "ef", ""]
keepOks : List before, (before -> Result after *) -> List after keepOks : List before, (before -> Result after *) -> List after
## This works like [List.map], except only the transformed values that are ## This works like [List.map], except only the transformed values that are
## wrapped in `Err` are kept. Any that are wrapped in `Ok` are dropped. ## wrapped in `Err` are kept. Any that are wrapped in `Ok` are dropped.
## ##
## >>> List.keepErrs [ [ "a", "b" ], [], [], [ "c", "d", "e" ] ] List.last ## >>> List.keepErrs [["a", "b"], [], [], ["c", "d", "e"]] List.last
## ##
## >>> fn = \str -> if Str.isEmpty str then Err StrWasEmpty else Ok (Str.len str) ## >>> fn = \str -> if Str.isEmpty str then Err StrWasEmpty else Ok (Str.len str)
## >>> ## >>>
## >>> List.keepErrs [ "", "a", "bc", "", "d", "ef", "" ] ## >>> List.keepErrs ["", "a", "bc", "", "d", "ef", ""]
keepErrs : List before, (before -> Result * after) -> List after keepErrs : List before, (before -> Result * after) -> List after
## Convert each element in the list to something new, by calling a conversion ## Convert each element in the list to something new, by calling a conversion
## function on each of them. Then return a new list of the converted values. ## function on each of them. Then return a new list of the converted values.
## ##
## > List.map [ 1, 2, 3 ] (\num -> num + 1) ## > List.map [1, 2, 3] (\num -> num + 1)
## ##
## > List.map [ "", "a", "bc" ] Str.isEmpty ## > List.map ["", "a", "bc"] Str.isEmpty
map : List a, (a -> b) -> List b map : List a, (a -> b) -> List b
## Run a transformation function on the first element of each list, ## Run a transformation function on the first element of each list,
@ -421,7 +421,7 @@ map : List a, (a -> b) -> List b
## Some languages have a function named `zip`, which does something similar to ## Some languages have a function named `zip`, which does something similar to
## calling [List.map2] passing two lists and `Pair`: ## calling [List.map2] passing two lists and `Pair`:
## ##
## >>> zipped = List.map2 [ "a", "b", "c" ] [ 1, 2, 3 ] Pair ## >>> zipped = List.map2 ["a", "b", "c"] [1, 2, 3] Pair
map2 : List a, List b, (a, b -> c) -> List c map2 : List a, List b, (a, b -> c) -> List c
## Run a transformation function on the first element of each list, ## Run a transformation function on the first element of each list,
@ -476,12 +476,12 @@ dropLast : List elem -> List elem
## Returns the given number of elements from the beginning of the list. ## Returns the given number of elements from the beginning of the list.
## ##
## >>> List.takeFirst 4 [ 1, 2, 3, 4, 5, 6, 7, 8 ] ## >>> List.takeFirst 4 [1, 2, 3, 4, 5, 6, 7, 8]
## ##
## If there are fewer elements in the list than the requested number, ## If there are fewer elements in the list than the requested number,
## returns the entire list. ## returns the entire list.
## ##
## >>> List.takeFirst 5 [ 1, 2 ] ## >>> List.takeFirst 5 [1, 2]
## ##
## To *remove* elements from the beginning of the list, use `List.takeLast`. ## To *remove* elements from the beginning of the list, use `List.takeLast`.
## ##
@ -503,12 +503,12 @@ takeFirst : List elem, Nat -> List elem
## Returns the given number of elements from the end of the list. ## Returns the given number of elements from the end of the list.
## ##
## >>> List.takeLast 4 [ 1, 2, 3, 4, 5, 6, 7, 8 ] ## >>> List.takeLast 4 [1, 2, 3, 4, 5, 6, 7, 8]
## ##
## If there are fewer elements in the list than the requested number, ## If there are fewer elements in the list than the requested number,
## returns the entire list. ## returns the entire list.
## ##
## >>> List.takeLast 5 [ 1, 2 ] ## >>> List.takeLast 5 [1, 2]
## ##
## To *remove* elements from the end of the list, use `List.takeFirst`. ## To *remove* elements from the end of the list, use `List.takeFirst`.
## ##
@ -588,11 +588,11 @@ find : List elem, (elem -> Bool) -> Result elem [NotFound]*
## ##
## If `start` is outside the bounds of the given list, returns the empty list. ## If `start` is outside the bounds of the given list, returns the empty list.
## ##
## >>> List.sublist { start: 4, len: 0 } [ 1, 2, 3 ] ## >>> List.sublist { start: 4, len: 0 } [1, 2, 3]
## ##
## If more elements are requested than exist in the list, returns as many as it can. ## If more elements are requested than exist in the list, returns as many as it can.
## ##
## >>> List.sublist { start: 2, len: 10 } [ 1, 2, 3, 4, 5 ] ## >>> List.sublist { start: 2, len: 10 } [1, 2, 3, 4, 5]
## ##
## > If you want a sublist which goes all the way to the end of the list, no ## > If you want a sublist which goes all the way to the end of the list, no
## > matter how long the list is, `List.takeLast` can do that more efficiently. ## > matter how long the list is, `List.takeLast` can do that more efficiently.

View file

@ -1192,20 +1192,20 @@ toF64Checked : Num * -> Result F64 [OutOfBounds]*
## ##
## Although this can be passed to `List.sort`, you'll get better performance ## Although this can be passed to `List.sort`, you'll get better performance
## by using `List.sortAsc` or `List.sortDesc` instead. ## by using `List.sortAsc` or `List.sortDesc` instead.
# compare : Num a, Num a -> [ Lt, Eq, Gt ] # compare : Num a, Num a -> [Lt, Eq, Gt]
## [Endianness](https://en.wikipedia.org/wiki/Endianness) ## [Endianness](https://en.wikipedia.org/wiki/Endianness)
# Endi : [ Big, Little, Native ] # Endi : [Big, Little, Native]
## The `Endi` argument does not matter for [U8] and [I8], since they have ## The `Endi` argument does not matter for [U8] and [I8], since they have
## only one byte. ## only one byte.
# toBytes : Num *, Endi -> List U8 # toBytes : Num *, Endi -> List U8
## when Num.parseBytes bytes Big is ## when Num.parseBytes bytes Big is
## Ok { val: f64, rest } -> ... ## Ok { val: f64, rest } -> ...
## Err (ExpectedNum (Frac Binary64)) -> ... ## Err (ExpectedNum (Frac Binary64)) -> ...
# parseBytes : List U8, Endi -> Result { val : Num a, rest : List U8 } [ ExpectedNum a ]* # parseBytes : List U8, Endi -> Result { val : Num a, rest : List U8 } [ExpectedNum a]*
## when Num.fromBytes bytes Big is ## when Num.fromBytes bytes Big is
## Ok f64 -> ... ## Ok f64 -> ...
## Err (ExpectedNum (Frac Binary64)) -> ... ## Err (ExpectedNum (Frac Binary64)) -> ...
# fromBytes : List U8, Endi -> Result (Num a) [ ExpectedNum a ]* # fromBytes : List U8, Endi -> Result (Num a) [ExpectedNum a]*
# Bit shifts # Bit shifts
## [Logical bit shift](https://en.wikipedia.org/wiki/Bitwise_operation#Logical_shift) left. ## [Logical bit shift](https://en.wikipedia.org/wiki/Bitwise_operation#Logical_shift) left.
## ##
@ -1280,10 +1280,10 @@ toF64Checked : Num * -> Result F64 [OutOfBounds]*
# format : # format :
# Num *, # Num *,
# { # {
# base ? [ Decimal, Hexadecimal, Octal, Binary ], # base ? [Decimal, Hexadecimal, Octal, Binary],
# notation ? [ Standard, Scientific ], # notation ? [Standard, Scientific],
# decimalMark ? [ AlwaysShow Str, HideForIntegers ], # decimalMark ? [AlwaysShow Str, HideForIntegers],
# decimalDigits ? { min : U16, max : [ All, Trunc U16, Round U16, Floor U16, Ceil U16 ] }, # decimalDigits ? { min : U16, max : [All, Trunc U16, Round U16, Floor U16, Ceil U16] },
# minWholeDigits ? U16, # minWholeDigits ? U16,
# wholeSep ? { mark : Str, places : U64 } # wholeSep ? { mark : Str, places : U64 }
# } # }

View file

@ -132,7 +132,7 @@ concat : Str, Str -> Str
## Combine a list of strings into a single string, with a separator ## Combine a list of strings into a single string, with a separator
## string in between each. ## string in between each.
## ##
## >>> Str.joinWith [ "one", "two", "three" ] ", " ## >>> Str.joinWith ["one", "two", "three"] ", "
joinWith : List Str, Str -> Str joinWith : List Str, Str -> Str
## Split a string around a separator. ## Split a string around a separator.
@ -185,8 +185,8 @@ startsWithCodePt : Str, U32 -> Bool
## >>> Str.toUtf8 "🐦" ## >>> Str.toUtf8 "🐦"
toUtf8 : Str -> List U8 toUtf8 : Str -> List U8
# fromUtf8 : List U8 -> Result Str [ BadUtf8 Utf8Problem ]* # fromUtf8 : List U8 -> Result Str [BadUtf8 Utf8Problem]*
# fromUtf8Range : List U8 -> Result Str [ BadUtf8 Utf8Problem Nat, OutOfBounds ]* # fromUtf8Range : List U8 -> Result Str [BadUtf8 Utf8Problem Nat, OutOfBounds]*
fromUtf8 : List U8 -> Result Str [BadUtf8 Utf8ByteProblem Nat]* fromUtf8 : List U8 -> Result Str [BadUtf8 Utf8ByteProblem Nat]*
fromUtf8Range : List U8, { start : Nat, count : Nat } -> Result Str [BadUtf8 Utf8ByteProblem Nat, OutOfBounds]* fromUtf8Range : List U8, { start : Nat, count : Nat } -> Result Str [BadUtf8 Utf8ByteProblem Nat, OutOfBounds]*

View file

@ -136,7 +136,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
) )
} }
// addChecked : Num a, Num a -> Result (Num a) [ Overflow ]* // addChecked : Num a, Num a -> Result (Num a) [Overflow]*
add_top_level_function_type!( add_top_level_function_type!(
Symbol::NUM_ADD_CHECKED, Symbol::NUM_ADD_CHECKED,
vec![num_type(flex(TVAR1)), num_type(flex(TVAR1))], vec![num_type(flex(TVAR1)), num_type(flex(TVAR1))],
@ -171,7 +171,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(int_type(flex(TVAR1))), Box::new(int_type(flex(TVAR1))),
); );
// subChecked : Num a, Num a -> Result (Num a) [ Overflow ]* // subChecked : Num a, Num a -> Result (Num a) [Overflow]*
add_top_level_function_type!( add_top_level_function_type!(
Symbol::NUM_SUB_CHECKED, Symbol::NUM_SUB_CHECKED,
vec![num_type(flex(TVAR1)), num_type(flex(TVAR1))], vec![num_type(flex(TVAR1)), num_type(flex(TVAR1))],
@ -199,7 +199,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(int_type(flex(TVAR1))), Box::new(int_type(flex(TVAR1))),
); );
// mulChecked : Num a, Num a -> Result (Num a) [ Overflow ]* // mulChecked : Num a, Num a -> Result (Num a) [Overflow]*
add_top_level_function_type!( add_top_level_function_type!(
Symbol::NUM_MUL_CHECKED, Symbol::NUM_MUL_CHECKED,
vec![num_type(flex(TVAR1)), num_type(flex(TVAR1))], vec![num_type(flex(TVAR1)), num_type(flex(TVAR1))],
@ -262,7 +262,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(bool_type()), Box::new(bool_type()),
); );
// compare : Num a, Num a -> [ LT, EQ, GT ] // compare : Num a, Num a -> [LT, EQ, GT]
add_top_level_function_type!( add_top_level_function_type!(
Symbol::NUM_COMPARE, Symbol::NUM_COMPARE,
vec![num_type(flex(TVAR1)), num_type(flex(TVAR1))], vec![num_type(flex(TVAR1)), num_type(flex(TVAR1))],
@ -323,7 +323,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(int_type(flex(TVAR1))) Box::new(int_type(flex(TVAR1)))
); );
// divTruncChecked : Int a, Int a -> Result (Int a) [ DivByZero ]* // divTruncChecked : Int a, Int a -> Result (Int a) [DivByZero]*
add_top_level_function_type!( add_top_level_function_type!(
Symbol::NUM_DIV_TRUNC_CHECKED, Symbol::NUM_DIV_TRUNC_CHECKED,
vec![int_type(flex(TVAR1)), int_type(flex(TVAR1))], vec![int_type(flex(TVAR1)), int_type(flex(TVAR1))],
@ -337,7 +337,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(int_type(flex(TVAR1))) Box::new(int_type(flex(TVAR1)))
); );
// divCeilChecked : Int a, Int a -> Result (Int a) [ DivByZero ]* // divCeilChecked : Int a, Int a -> Result (Int a) [DivByZero]*
add_top_level_function_type!( add_top_level_function_type!(
Symbol::NUM_DIV_CEIL_CHECKED, Symbol::NUM_DIV_CEIL_CHECKED,
vec![int_type(flex(TVAR1)), int_type(flex(TVAR1))], vec![int_type(flex(TVAR1)), int_type(flex(TVAR1))],
@ -400,7 +400,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(int_type(flex(TVAR1))), Box::new(int_type(flex(TVAR1))),
); );
// remChecked : Int a, Int a -> Result (Int a) [ DivByZero ]* // remChecked : Int a, Int a -> Result (Int a) [DivByZero]*
add_top_level_function_type!( add_top_level_function_type!(
Symbol::NUM_REM_CHECKED, Symbol::NUM_REM_CHECKED,
vec![int_type(flex(TVAR1)), int_type(flex(TVAR1))], vec![int_type(flex(TVAR1)), int_type(flex(TVAR1))],
@ -480,7 +480,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(SolvedType::Wildcard), Box::new(SolvedType::Wildcard),
); );
// toI8Checked : Int * -> Result I8 [ OutOfBounds ]* // toI8Checked : Int * -> Result I8 [OutOfBounds]*
add_top_level_function_type!( add_top_level_function_type!(
Symbol::NUM_TO_I8_CHECKED, Symbol::NUM_TO_I8_CHECKED,
vec![int_type(flex(TVAR1))], vec![int_type(flex(TVAR1))],
@ -494,7 +494,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(i16_type()), Box::new(i16_type()),
); );
// toI16Checked : Int * -> Result I16 [ OutOfBounds ]* // toI16Checked : Int * -> Result I16 [OutOfBounds]*
add_top_level_function_type!( add_top_level_function_type!(
Symbol::NUM_TO_I16_CHECKED, Symbol::NUM_TO_I16_CHECKED,
vec![int_type(flex(TVAR1))], vec![int_type(flex(TVAR1))],
@ -508,7 +508,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(i32_type()), Box::new(i32_type()),
); );
// toI32Checked : Int * -> Result I32 [ OutOfBounds ]* // toI32Checked : Int * -> Result I32 [OutOfBounds]*
add_top_level_function_type!( add_top_level_function_type!(
Symbol::NUM_TO_I32_CHECKED, Symbol::NUM_TO_I32_CHECKED,
vec![int_type(flex(TVAR1))], vec![int_type(flex(TVAR1))],
@ -522,7 +522,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(i64_type()), Box::new(i64_type()),
); );
// toI64Checked : Int * -> Result I64 [ OutOfBounds ]* // toI64Checked : Int * -> Result I64 [OutOfBounds]*
add_top_level_function_type!( add_top_level_function_type!(
Symbol::NUM_TO_I64_CHECKED, Symbol::NUM_TO_I64_CHECKED,
vec![int_type(flex(TVAR1))], vec![int_type(flex(TVAR1))],
@ -536,7 +536,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(i128_type()), Box::new(i128_type()),
); );
// toI128Checked : Int * -> Result I128 [ OutOfBounds ]* // toI128Checked : Int * -> Result I128 [OutOfBounds]*
add_top_level_function_type!( add_top_level_function_type!(
Symbol::NUM_TO_I128_CHECKED, Symbol::NUM_TO_I128_CHECKED,
vec![int_type(flex(TVAR1))], vec![int_type(flex(TVAR1))],
@ -555,7 +555,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(SolvedType::Wildcard), Box::new(SolvedType::Wildcard),
); );
// toU8Checked : Int * -> Result U8 [ OutOfBounds ]* // toU8Checked : Int * -> Result U8 [OutOfBounds]*
add_top_level_function_type!( add_top_level_function_type!(
Symbol::NUM_TO_U8_CHECKED, Symbol::NUM_TO_U8_CHECKED,
vec![int_type(flex(TVAR1))], vec![int_type(flex(TVAR1))],
@ -569,7 +569,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(u16_type()), Box::new(u16_type()),
); );
// toU16Checked : Int * -> Result U16 [ OutOfBounds ]* // toU16Checked : Int * -> Result U16 [OutOfBounds]*
add_top_level_function_type!( add_top_level_function_type!(
Symbol::NUM_TO_U16_CHECKED, Symbol::NUM_TO_U16_CHECKED,
vec![int_type(flex(TVAR1))], vec![int_type(flex(TVAR1))],
@ -583,7 +583,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(u32_type()), Box::new(u32_type()),
); );
// toU32Checked : Int * -> Result U32 [ OutOfBounds ]* // toU32Checked : Int * -> Result U32 [OutOfBounds]*
add_top_level_function_type!( add_top_level_function_type!(
Symbol::NUM_TO_U32_CHECKED, Symbol::NUM_TO_U32_CHECKED,
vec![int_type(flex(TVAR1))], vec![int_type(flex(TVAR1))],
@ -597,7 +597,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(u64_type()), Box::new(u64_type()),
); );
// toU64Checked : Int * -> Result U64 [ OutOfBounds ]* // toU64Checked : Int * -> Result U64 [OutOfBounds]*
add_top_level_function_type!( add_top_level_function_type!(
Symbol::NUM_TO_U64_CHECKED, Symbol::NUM_TO_U64_CHECKED,
vec![int_type(flex(TVAR1))], vec![int_type(flex(TVAR1))],
@ -611,7 +611,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(u128_type()), Box::new(u128_type()),
); );
// toU128Checked : Int * -> Result U128 [ OutOfBounds ]* // toU128Checked : Int * -> Result U128 [OutOfBounds]*
add_top_level_function_type!( add_top_level_function_type!(
Symbol::NUM_TO_U128_CHECKED, Symbol::NUM_TO_U128_CHECKED,
vec![int_type(flex(TVAR1))], vec![int_type(flex(TVAR1))],
@ -625,7 +625,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(nat_type()), Box::new(nat_type()),
); );
// toNatChecked : Int * -> Result Nat [ OutOfBounds ]* // toNatChecked : Int * -> Result Nat [OutOfBounds]*
add_top_level_function_type!( add_top_level_function_type!(
Symbol::NUM_TO_NAT_CHECKED, Symbol::NUM_TO_NAT_CHECKED,
vec![int_type(flex(TVAR1))], vec![int_type(flex(TVAR1))],
@ -639,7 +639,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(f32_type()), Box::new(f32_type()),
); );
// toF32Checked : Num * -> Result F32 [ OutOfBounds ]* // toF32Checked : Num * -> Result F32 [OutOfBounds]*
add_top_level_function_type!( add_top_level_function_type!(
Symbol::NUM_TO_F32_CHECKED, Symbol::NUM_TO_F32_CHECKED,
vec![num_type(flex(TVAR1))], vec![num_type(flex(TVAR1))],
@ -653,7 +653,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(f64_type()), Box::new(f64_type()),
); );
// toF64Checked : Num * -> Result F64 [ OutOfBounds ]* // toF64Checked : Num * -> Result F64 [OutOfBounds]*
add_top_level_function_type!( add_top_level_function_type!(
Symbol::NUM_TO_F64_CHECKED, Symbol::NUM_TO_F64_CHECKED,
vec![num_type(flex(TVAR1))], vec![num_type(flex(TVAR1))],
@ -676,7 +676,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(frac_type(flex(TVAR1))) Box::new(frac_type(flex(TVAR1)))
); );
// divChecked : Frac a, Frac a -> Result (Frac a) [ DivByZero ]* // divChecked : Frac a, Frac a -> Result (Frac a) [DivByZero]*
add_top_level_function_type!( add_top_level_function_type!(
Symbol::NUM_DIV_FRAC_CHECKED, Symbol::NUM_DIV_FRAC_CHECKED,
vec![frac_type(flex(TVAR1)), frac_type(flex(TVAR1))], vec![frac_type(flex(TVAR1)), frac_type(flex(TVAR1))],
@ -690,7 +690,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(frac_type(flex(TVAR1))), Box::new(frac_type(flex(TVAR1))),
); );
// sqrtChecked : Frac a -> Result (Frac a) [ SqrtOfNegative ]* // sqrtChecked : Frac a -> Result (Frac a) [SqrtOfNegative]*
let sqrt_of_negative = SolvedType::TagUnion( let sqrt_of_negative = SolvedType::TagUnion(
vec![(TagName::Tag("SqrtOfNegative".into()), vec![])], vec![(TagName::Tag("SqrtOfNegative".into()), vec![])],
Box::new(SolvedType::Wildcard), Box::new(SolvedType::Wildcard),
@ -709,7 +709,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(frac_type(flex(TVAR1))), Box::new(frac_type(flex(TVAR1))),
); );
// logChecked : Frac a -> Result (Frac a) [ LogNeedsPositive ]* // logChecked : Frac a -> Result (Frac a) [LogNeedsPositive]*
let log_needs_positive = SolvedType::TagUnion( let log_needs_positive = SolvedType::TagUnion(
vec![(TagName::Tag("LogNeedsPositive".into()), vec![])], vec![(TagName::Tag("LogNeedsPositive".into()), vec![])],
Box::new(SolvedType::Wildcard), Box::new(SolvedType::Wildcard),
@ -798,7 +798,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(frac_type(flex(TVAR1))), Box::new(frac_type(flex(TVAR1))),
); );
// bytesToU16 : List U8, Nat -> Result U16 [ OutOfBounds ] // bytesToU16 : List U8, Nat -> Result U16 [OutOfBounds]
{ {
let position_out_of_bounds = SolvedType::TagUnion( let position_out_of_bounds = SolvedType::TagUnion(
vec![(TagName::Tag("OutOfBounds".into()), vec![])], vec![(TagName::Tag("OutOfBounds".into()), vec![])],
@ -811,7 +811,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
); );
} }
// bytesToU32 : List U8, Nat -> Result U32 [ OutOfBounds ] // bytesToU32 : List U8, Nat -> Result U32 [OutOfBounds]
{ {
let position_out_of_bounds = SolvedType::TagUnion( let position_out_of_bounds = SolvedType::TagUnion(
vec![(TagName::Tag("OutOfBounds".into()), vec![])], vec![(TagName::Tag("OutOfBounds".into()), vec![])],
@ -932,7 +932,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
// trim : Str -> Str // trim : Str -> Str
add_top_level_function_type!(Symbol::STR_TRIM, vec![str_type()], Box::new(str_type())); add_top_level_function_type!(Symbol::STR_TRIM, vec![str_type()], Box::new(str_type()));
// fromUtf8 : List U8 -> Result Str [ BadUtf8 Utf8Problem ]* // fromUtf8 : List U8 -> Result Str [BadUtf8 Utf8Problem]*
{ {
let bad_utf8 = SolvedType::TagUnion( let bad_utf8 = SolvedType::TagUnion(
vec![( vec![(
@ -949,7 +949,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
); );
} }
// fromUtf8Range : List U8, { start : Nat, count : Nat } -> Result Str [ BadUtf8 Utf8Problem, OutOfBounds ]* // fromUtf8Range : List U8, { start : Nat, count : Nat } -> Result Str [BadUtf8 Utf8Problem, OutOfBounds]*
{ {
let bad_utf8 = SolvedType::TagUnion( let bad_utf8 = SolvedType::TagUnion(
vec![ vec![
@ -985,7 +985,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(list_type(u8_type())) Box::new(list_type(u8_type()))
); );
// toNum : Str -> Result (Num a) [ InvalidNumStr ] // toNum : Str -> Result (Num a) [InvalidNumStr]
// Because toNum doesn't work with floats & decimals by default without // Because toNum doesn't work with floats & decimals by default without
// a point of usage to be able to infer the proper layout // a point of usage to be able to infer the proper layout
// we decided that separate functions for each sub num type // we decided that separate functions for each sub num type
@ -998,98 +998,98 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
) )
}; };
// toDec : Str -> Result Dec [ InvalidNumStr ] // toDec : Str -> Result Dec [InvalidNumStr]
add_top_level_function_type!( add_top_level_function_type!(
Symbol::STR_TO_DEC, Symbol::STR_TO_DEC,
vec![str_type()], vec![str_type()],
Box::new(result_type(dec_type(), invalid_str())) Box::new(result_type(dec_type(), invalid_str()))
); );
// toF64 : Str -> Result F64 [ InvalidNumStr ] // toF64 : Str -> Result F64 [InvalidNumStr]
add_top_level_function_type!( add_top_level_function_type!(
Symbol::STR_TO_F64, Symbol::STR_TO_F64,
vec![str_type()], vec![str_type()],
Box::new(result_type(f64_type(), invalid_str())) Box::new(result_type(f64_type(), invalid_str()))
); );
// toF32 : Str -> Result F32 [ InvalidNumStr ] // toF32 : Str -> Result F32 [InvalidNumStr]
add_top_level_function_type!( add_top_level_function_type!(
Symbol::STR_TO_F32, Symbol::STR_TO_F32,
vec![str_type()], vec![str_type()],
Box::new(result_type(f32_type(), invalid_str())) Box::new(result_type(f32_type(), invalid_str()))
); );
// toNat : Str -> Result Nat [ InvalidNumStr ] // toNat : Str -> Result Nat [InvalidNumStr]
add_top_level_function_type!( add_top_level_function_type!(
Symbol::STR_TO_NAT, Symbol::STR_TO_NAT,
vec![str_type()], vec![str_type()],
Box::new(result_type(nat_type(), invalid_str())) Box::new(result_type(nat_type(), invalid_str()))
); );
// toU128 : Str -> Result U128 [ InvalidNumStr ] // toU128 : Str -> Result U128 [InvalidNumStr]
add_top_level_function_type!( add_top_level_function_type!(
Symbol::STR_TO_U128, Symbol::STR_TO_U128,
vec![str_type()], vec![str_type()],
Box::new(result_type(u128_type(), invalid_str())) Box::new(result_type(u128_type(), invalid_str()))
); );
// toI128 : Str -> Result I128 [ InvalidNumStr ] // toI128 : Str -> Result I128 [InvalidNumStr]
add_top_level_function_type!( add_top_level_function_type!(
Symbol::STR_TO_I128, Symbol::STR_TO_I128,
vec![str_type()], vec![str_type()],
Box::new(result_type(i128_type(), invalid_str())) Box::new(result_type(i128_type(), invalid_str()))
); );
// toU64 : Str -> Result U64 [ InvalidNumStr ] // toU64 : Str -> Result U64 [InvalidNumStr]
add_top_level_function_type!( add_top_level_function_type!(
Symbol::STR_TO_U64, Symbol::STR_TO_U64,
vec![str_type()], vec![str_type()],
Box::new(result_type(u64_type(), invalid_str())) Box::new(result_type(u64_type(), invalid_str()))
); );
// toI64 : Str -> Result I64 [ InvalidNumStr ] // toI64 : Str -> Result I64 [InvalidNumStr]
add_top_level_function_type!( add_top_level_function_type!(
Symbol::STR_TO_I64, Symbol::STR_TO_I64,
vec![str_type()], vec![str_type()],
Box::new(result_type(i64_type(), invalid_str())) Box::new(result_type(i64_type(), invalid_str()))
); );
// toU32 : Str -> Result U32 [ InvalidNumStr ] // toU32 : Str -> Result U32 [InvalidNumStr]
add_top_level_function_type!( add_top_level_function_type!(
Symbol::STR_TO_U32, Symbol::STR_TO_U32,
vec![str_type()], vec![str_type()],
Box::new(result_type(u32_type(), invalid_str())) Box::new(result_type(u32_type(), invalid_str()))
); );
// toI32 : Str -> Result I32 [ InvalidNumStr ] // toI32 : Str -> Result I32 [InvalidNumStr]
add_top_level_function_type!( add_top_level_function_type!(
Symbol::STR_TO_I32, Symbol::STR_TO_I32,
vec![str_type()], vec![str_type()],
Box::new(result_type(i32_type(), invalid_str())) Box::new(result_type(i32_type(), invalid_str()))
); );
// toU16 : Str -> Result U16 [ InvalidNumStr ] // toU16 : Str -> Result U16 [InvalidNumStr]
add_top_level_function_type!( add_top_level_function_type!(
Symbol::STR_TO_U16, Symbol::STR_TO_U16,
vec![str_type()], vec![str_type()],
Box::new(result_type(u16_type(), invalid_str())) Box::new(result_type(u16_type(), invalid_str()))
); );
// toI16 : Str -> Result I16 [ InvalidNumStr ] // toI16 : Str -> Result I16 [InvalidNumStr]
add_top_level_function_type!( add_top_level_function_type!(
Symbol::STR_TO_I16, Symbol::STR_TO_I16,
vec![str_type()], vec![str_type()],
Box::new(result_type(i16_type(), invalid_str())) Box::new(result_type(i16_type(), invalid_str()))
); );
// toU8 : Str -> Result U8 [ InvalidNumStr ] // toU8 : Str -> Result U8 [InvalidNumStr]
add_top_level_function_type!( add_top_level_function_type!(
Symbol::STR_TO_U8, Symbol::STR_TO_U8,
vec![str_type()], vec![str_type()],
Box::new(result_type(u8_type(), invalid_str())) Box::new(result_type(u8_type(), invalid_str()))
); );
// toI8 : Str -> Result I8 [ InvalidNumStr ] // toI8 : Str -> Result I8 [InvalidNumStr]
add_top_level_function_type!( add_top_level_function_type!(
Symbol::STR_TO_I8, Symbol::STR_TO_I8,
vec![str_type()], vec![str_type()],
@ -1098,7 +1098,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
// List module // List module
// get : List elem, Nat -> Result elem [ OutOfBounds ]* // get : List elem, Nat -> Result elem [OutOfBounds]*
let index_out_of_bounds = SolvedType::TagUnion( let index_out_of_bounds = SolvedType::TagUnion(
vec![(TagName::Tag("OutOfBounds".into()), vec![])], vec![(TagName::Tag("OutOfBounds".into()), vec![])],
Box::new(SolvedType::Wildcard), Box::new(SolvedType::Wildcard),
@ -1110,7 +1110,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(result_type(flex(TVAR1), index_out_of_bounds)), Box::new(result_type(flex(TVAR1), index_out_of_bounds)),
); );
// first : List elem -> Result elem [ ListWasEmpty ]* // first : List elem -> Result elem [ListWasEmpty]*
let list_was_empty = SolvedType::TagUnion( let list_was_empty = SolvedType::TagUnion(
vec![(TagName::Tag("ListWasEmpty".into()), vec![])], vec![(TagName::Tag("ListWasEmpty".into()), vec![])],
Box::new(SolvedType::Wildcard), Box::new(SolvedType::Wildcard),
@ -1122,7 +1122,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(result_type(flex(TVAR1), list_was_empty.clone())), Box::new(result_type(flex(TVAR1), list_was_empty.clone())),
); );
// last : List elem -> Result elem [ ListWasEmpty ]* // last : List elem -> Result elem [ListWasEmpty]*
add_top_level_function_type!( add_top_level_function_type!(
Symbol::LIST_LAST, Symbol::LIST_LAST,
vec![list_type(flex(TVAR1))], vec![list_type(flex(TVAR1))],
@ -1163,14 +1163,14 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(bool_type()), Box::new(bool_type()),
); );
// min : List (Num a) -> Result (Num a) [ ListWasEmpty ]* // min : List (Num a) -> Result (Num a) [ListWasEmpty]*
add_top_level_function_type!( add_top_level_function_type!(
Symbol::LIST_MIN, Symbol::LIST_MIN,
vec![list_type(num_type(flex(TVAR1)))], vec![list_type(num_type(flex(TVAR1)))],
Box::new(result_type(num_type(flex(TVAR1)), list_was_empty.clone())), Box::new(result_type(num_type(flex(TVAR1)), list_was_empty.clone())),
); );
// max : List (Num a) -> Result (Num a) [ ListWasEmpty ]* // max : List (Num a) -> Result (Num a) [ListWasEmpty]*
add_top_level_function_type!( add_top_level_function_type!(
Symbol::LIST_MAX, Symbol::LIST_MAX,
vec![list_type(num_type(flex(TVAR1)))], vec![list_type(num_type(flex(TVAR1)))],
@ -1214,7 +1214,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
); );
fn until_type(content: SolvedType) -> SolvedType { fn until_type(content: SolvedType) -> SolvedType {
// [ LT, EQ, GT ] // [LT, EQ, GT]
SolvedType::TagUnion( SolvedType::TagUnion(
vec![ vec![
(TagName::Tag("Continue".into()), vec![content.clone()]), (TagName::Tag("Continue".into()), vec![content.clone()]),
@ -1224,7 +1224,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
) )
} }
// walkUntil : List elem, state, (state, elem -> [ Continue state, Stop state ]) -> state // walkUntil : List elem, state, (state, elem -> [Continue state, Stop state]) -> state
add_top_level_function_type!( add_top_level_function_type!(
Symbol::LIST_WALK_UNTIL, Symbol::LIST_WALK_UNTIL,
vec![ vec![
@ -1576,7 +1576,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(list_type(num_type(flex(TVAR1)))) Box::new(list_type(num_type(flex(TVAR1))))
); );
// find : List elem, (elem -> Bool) -> Result elem [ NotFound ]* // find : List elem, (elem -> Bool) -> Result elem [NotFound]*
{ {
let not_found = SolvedType::TagUnion( let not_found = SolvedType::TagUnion(
vec![(TagName::Tag("NotFound".into()), vec![])], vec![(TagName::Tag("NotFound".into()), vec![])],
@ -1619,7 +1619,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(dict_type(flex(TVAR1), flex(TVAR2))), Box::new(dict_type(flex(TVAR1), flex(TVAR2))),
); );
// get : Dict k v, k -> Result v [ KeyNotFound ]* // get : Dict k v, k -> Result v [KeyNotFound]*
let key_not_found = SolvedType::TagUnion( let key_not_found = SolvedType::TagUnion(
vec![(TagName::Tag("KeyNotFound".into()), vec![])], vec![(TagName::Tag("KeyNotFound".into()), vec![])],
Box::new(SolvedType::Wildcard), Box::new(SolvedType::Wildcard),

View file

@ -359,7 +359,7 @@ pub(crate) fn make_apply_symbol(
/// Retrieves all symbols in an annotations that reference a type definition, that is either an /// Retrieves all symbols in an annotations that reference a type definition, that is either an
/// alias or an opaque type. /// alias or an opaque type.
/// ///
/// For example, in `[ A Age U8, B Str {} ]`, there are three type definition references - `Age`, /// For example, in `[A Age U8, B Str {}]`, there are three type definition references - `Age`,
/// `U8`, and `Str`. /// `U8`, and `Str`.
pub fn find_type_def_symbols( pub fn find_type_def_symbols(
scope: &mut Scope, scope: &mut Scope,

View file

@ -31,13 +31,13 @@ macro_rules! macro_magic {
/// Some builtins cannot be constructed in code gen alone, and need to be defined /// Some builtins cannot be constructed in code gen alone, and need to be defined
/// as separate Roc defs. For example, List.get has this type: /// as separate Roc defs. For example, List.get has this type:
/// ///
/// List.get : List elem, Nat -> Result elem [ OutOfBounds ]* /// List.get : List elem, Nat -> Result elem [OutOfBounds]*
/// ///
/// Because this returns an open tag union for its Err type, it's not possible /// Because this returns an open tag union for its Err type, it's not possible
/// for code gen to return a hardcoded value for OutOfBounds. For example, /// for code gen to return a hardcoded value for OutOfBounds. For example,
/// if this Result unifies to [ Foo, OutOfBounds ] then OutOfBOunds will /// if this Result unifies to [Foo, OutOfBounds] then OutOfBOunds will
/// get assigned the number 1 (because Foo got 0 alphabetically), whereas /// get assigned the number 1 (because Foo got 0 alphabetically), whereas
/// if it unifies to [ OutOfBounds, Qux ] then OutOfBounds will get the number 0. /// if it unifies to [OutOfBounds, Qux] then OutOfBounds will get the number 0.
/// ///
/// Getting these numbers right requires having List.get participate in the /// Getting these numbers right requires having List.get participate in the
/// normal type-checking and monomorphization processes. As such, this function /// normal type-checking and monomorphization processes. As such, this function
@ -574,7 +574,7 @@ fn to_num_checked(symbol: Symbol, var_store: &mut VarStore, lowlevel: LowLevel)
macro_rules! num_to_checked { macro_rules! num_to_checked {
($($fn:ident)*) => {$( ($($fn:ident)*) => {$(
// Num.toXXXChecked : Int * -> Result XXX [ OutOfBounds ]* // Num.toXXXChecked : Int * -> Result XXX [OutOfBounds]*
fn $fn(symbol: Symbol, var_store: &mut VarStore) -> Def { fn $fn(symbol: Symbol, var_store: &mut VarStore) -> Def {
// Use the generic `NumToIntChecked`; we'll figure out exactly what layout(s) we need // Use the generic `NumToIntChecked`; we'll figure out exactly what layout(s) we need
// during code generation after types are resolved. // during code generation after types are resolved.
@ -869,7 +869,7 @@ fn num_overflow_checked(symbol: Symbol, var_store: &mut VarStore, lowlevel: LowL
) )
} }
/// Num.addChecked : Num a, Num a -> Result (Num a) [ Overflow ]* /// Num.addChecked : Num a, Num a -> Result (Num a) [Overflow]*
fn num_add_checked(symbol: Symbol, var_store: &mut VarStore) -> Def { fn num_add_checked(symbol: Symbol, var_store: &mut VarStore) -> Def {
num_overflow_checked(symbol, var_store, LowLevel::NumAddChecked) num_overflow_checked(symbol, var_store, LowLevel::NumAddChecked)
} }
@ -889,7 +889,7 @@ fn num_sub_wrap(symbol: Symbol, var_store: &mut VarStore) -> Def {
num_binop(symbol, var_store, LowLevel::NumSubWrap) num_binop(symbol, var_store, LowLevel::NumSubWrap)
} }
/// Num.subChecked : Num a, Num a -> Result (Num a) [ Overflow ]* /// Num.subChecked : Num a, Num a -> Result (Num a) [Overflow]*
fn num_sub_checked(symbol: Symbol, var_store: &mut VarStore) -> Def { fn num_sub_checked(symbol: Symbol, var_store: &mut VarStore) -> Def {
num_overflow_checked(symbol, var_store, LowLevel::NumSubChecked) num_overflow_checked(symbol, var_store, LowLevel::NumSubChecked)
} }
@ -909,7 +909,7 @@ fn num_mul_wrap(symbol: Symbol, var_store: &mut VarStore) -> Def {
num_binop(symbol, var_store, LowLevel::NumMulWrap) num_binop(symbol, var_store, LowLevel::NumMulWrap)
} }
/// Num.mulChecked : Num a, Num a -> Result (Num a) [ Overflow ]* /// Num.mulChecked : Num a, Num a -> Result (Num a) [Overflow]*
fn num_mul_checked(symbol: Symbol, var_store: &mut VarStore) -> Def { fn num_mul_checked(symbol: Symbol, var_store: &mut VarStore) -> Def {
num_overflow_checked(symbol, var_store, LowLevel::NumMulChecked) num_overflow_checked(symbol, var_store, LowLevel::NumMulChecked)
} }
@ -934,7 +934,7 @@ fn num_lte(symbol: Symbol, var_store: &mut VarStore) -> Def {
num_num_other_binop(symbol, var_store, LowLevel::NumLte) num_num_other_binop(symbol, var_store, LowLevel::NumLte)
} }
/// Num.compare : Num a, Num a -> [ LT, EQ, GT ] /// Num.compare : Num a, Num a -> [LT, EQ, GT]
fn num_compare(symbol: Symbol, var_store: &mut VarStore) -> Def { fn num_compare(symbol: Symbol, var_store: &mut VarStore) -> Def {
num_num_other_binop(symbol, var_store, LowLevel::NumCompare) num_num_other_binop(symbol, var_store, LowLevel::NumCompare)
} }
@ -1178,7 +1178,7 @@ fn num_sqrt(symbol: Symbol, var_store: &mut VarStore) -> Def {
num_unaryop(symbol, var_store, LowLevel::NumSqrtUnchecked) num_unaryop(symbol, var_store, LowLevel::NumSqrtUnchecked)
} }
/// Num.sqrtChecked : Frac a -> Result (Frac a) [ SqrtOfNegative ]* /// Num.sqrtChecked : Frac a -> Result (Frac a) [SqrtOfNegative]*
fn num_sqrt_checked(symbol: Symbol, var_store: &mut VarStore) -> Def { fn num_sqrt_checked(symbol: Symbol, var_store: &mut VarStore) -> Def {
let bool_var = var_store.fresh(); let bool_var = var_store.fresh();
let frac_var = var_store.fresh(); let frac_var = var_store.fresh();
@ -1232,7 +1232,7 @@ fn num_log(symbol: Symbol, var_store: &mut VarStore) -> Def {
num_unaryop(symbol, var_store, LowLevel::NumLogUnchecked) num_unaryop(symbol, var_store, LowLevel::NumLogUnchecked)
} }
/// Num.logChecked : Frac a -> Result (Frac a) [ LogNeedsPositive ]* /// Num.logChecked : Frac a -> Result (Frac a) [LogNeedsPositive]*
fn num_log_checked(symbol: Symbol, var_store: &mut VarStore) -> Def { fn num_log_checked(symbol: Symbol, var_store: &mut VarStore) -> Def {
let bool_var = var_store.fresh(); let bool_var = var_store.fresh();
let frac_var = var_store.fresh(); let frac_var = var_store.fresh();
@ -1442,12 +1442,12 @@ fn num_asin(symbol: Symbol, var_store: &mut VarStore) -> Def {
) )
} }
/// Num.bytesToU16 : List U8, Nat -> Result U16 [ OutOfBounds ] /// Num.bytesToU16 : List U8, Nat -> Result U16 [OutOfBounds]
fn num_bytes_to_u16(symbol: Symbol, var_store: &mut VarStore) -> Def { fn num_bytes_to_u16(symbol: Symbol, var_store: &mut VarStore) -> Def {
num_bytes_to(symbol, var_store, 1, LowLevel::NumBytesToU16) num_bytes_to(symbol, var_store, 1, LowLevel::NumBytesToU16)
} }
/// Num.bytesToU32 : List U8, Nat -> Result U32 [ OutOfBounds ] /// Num.bytesToU32 : List U8, Nat -> Result U32 [OutOfBounds]
fn num_bytes_to_u32(symbol: Symbol, var_store: &mut VarStore) -> Def { fn num_bytes_to_u32(symbol: Symbol, var_store: &mut VarStore) -> Def {
num_bytes_to(symbol, var_store, 3, LowLevel::NumBytesToU32) num_bytes_to(symbol, var_store, 3, LowLevel::NumBytesToU32)
} }
@ -1573,7 +1573,7 @@ fn str_trim_right(symbol: Symbol, var_store: &mut VarStore) -> Def {
lowlevel_1(symbol, LowLevel::StrTrimRight, var_store) lowlevel_1(symbol, LowLevel::StrTrimRight, var_store)
} }
/// Str.toNum : Str -> Result (Num *) [ InvalidNumStr ]* /// Str.toNum : Str -> Result (Num *) [InvalidNumStr]*
fn str_to_num(symbol: Symbol, var_store: &mut VarStore) -> Def { fn str_to_num(symbol: Symbol, var_store: &mut VarStore) -> Def {
let bool_var = var_store.fresh(); let bool_var = var_store.fresh();
let str_var = var_store.fresh(); let str_var = var_store.fresh();
@ -1805,7 +1805,7 @@ fn str_count_graphemes(symbol: Symbol, var_store: &mut VarStore) -> Def {
) )
} }
/// Str.fromUtf8 : List U8 -> Result Str [ BadUtf8 { byteIndex : Nat, problem : Utf8Problem } } ]* /// Str.fromUtf8 : List U8 -> Result Str [BadUtf8 { byteIndex : Nat, problem : Utf8Problem } }]*
fn str_from_utf8(symbol: Symbol, var_store: &mut VarStore) -> Def { fn str_from_utf8(symbol: Symbol, var_store: &mut VarStore) -> Def {
let bytes_var = var_store.fresh(); let bytes_var = var_store.fresh();
let bool_var = var_store.fresh(); let bool_var = var_store.fresh();
@ -1908,7 +1908,7 @@ fn str_from_utf8(symbol: Symbol, var_store: &mut VarStore) -> Def {
ret_var, ret_var,
) )
} }
/// Str.fromUtf8Range : List U8, { start : Nat, count : Nat } -> Result Str [ BadUtf8 { byteIndex : Nat, problem : Utf8Problem } } ]* /// Str.fromUtf8Range : List U8, { start : Nat, count : Nat } -> Result Str [BadUtf8 { byteIndex : Nat, problem : Utf8Problem } }]*
fn str_from_utf8_range(symbol: Symbol, var_store: &mut VarStore) -> Def { fn str_from_utf8_range(symbol: Symbol, var_store: &mut VarStore) -> Def {
let bytes_var = var_store.fresh(); let bytes_var = var_store.fresh();
let bool_var = var_store.fresh(); let bool_var = var_store.fresh();
@ -2173,12 +2173,12 @@ fn list_len(symbol: Symbol, var_store: &mut VarStore) -> Def {
) )
} }
/// List.get : List elem, Int -> Result elem [ OutOfBounds ]* /// List.get : List elem, Int -> Result elem [OutOfBounds]*
/// ///
/// List.get : /// List.get :
/// Attr (* | u) (List (Attr u a)), /// Attr (* | u) (List (Attr u a)),
/// Attr * Int /// Attr * Int
/// -> Attr * (Result (Attr u a) (Attr * [ OutOfBounds ]*)) /// -> Attr * (Result (Attr u a) (Attr * [OutOfBounds]*))
fn list_get(symbol: Symbol, var_store: &mut VarStore) -> Def { fn list_get(symbol: Symbol, var_store: &mut VarStore) -> Def {
let arg_list = Symbol::ARG_1; let arg_list = Symbol::ARG_1;
let arg_index = Symbol::ARG_2; let arg_index = Symbol::ARG_2;
@ -2863,7 +2863,7 @@ fn list_drop_at(symbol: Symbol, var_store: &mut VarStore) -> Def {
) )
} }
/// List.dropFirst : List elem -> Result { first: elem, others : List elem } [ ListWasEmpty ]* /// List.dropFirst : List elem -> Result { first: elem, others : List elem } [ListWasEmpty]*
fn list_drop_first(symbol: Symbol, var_store: &mut VarStore) -> Def { fn list_drop_first(symbol: Symbol, var_store: &mut VarStore) -> Def {
let list_var = var_store.fresh(); let list_var = var_store.fresh();
let index_var = var_store.fresh(); let index_var = var_store.fresh();
@ -3074,7 +3074,7 @@ fn list_walk_backwards(symbol: Symbol, var_store: &mut VarStore) -> Def {
lowlevel_3(symbol, LowLevel::ListWalkBackwards, var_store) lowlevel_3(symbol, LowLevel::ListWalkBackwards, var_store)
} }
/// List.walkUntil : List elem, state, (state, elem -> [ Continue state, Stop state ]) -> state /// List.walkUntil : List elem, state, (state, elem -> [Continue state, Stop state]) -> state
fn list_walk_until(symbol: Symbol, var_store: &mut VarStore) -> Def { fn list_walk_until(symbol: Symbol, var_store: &mut VarStore) -> Def {
lowlevel_3(symbol, LowLevel::ListWalkUntil, var_store) lowlevel_3(symbol, LowLevel::ListWalkUntil, var_store)
} }
@ -3164,7 +3164,7 @@ fn list_join_map(symbol: Symbol, var_store: &mut VarStore) -> Def {
) )
} }
// min : List (Num a) -> Result (Num a) [ ListWasEmpty ]* // min : List (Num a) -> Result (Num a) [ListWasEmpty]*
fn list_min(symbol: Symbol, var_store: &mut VarStore) -> Def { fn list_min(symbol: Symbol, var_store: &mut VarStore) -> Def {
let arg_var = var_store.fresh(); let arg_var = var_store.fresh();
let bool_var = var_store.fresh(); let bool_var = var_store.fresh();
@ -3305,7 +3305,7 @@ fn list_min_lt(list_elem_var: Variable, var_store: &mut VarStore) -> Expr {
) )
} }
// max : List (Num a) -> Result (Num a) [ ListWasEmpty ]* // max : List (Num a) -> Result (Num a) [ListWasEmpty]*
fn list_max(symbol: Symbol, var_store: &mut VarStore) -> Def { fn list_max(symbol: Symbol, var_store: &mut VarStore) -> Def {
let arg_var = var_store.fresh(); let arg_var = var_store.fresh();
let bool_var = var_store.fresh(); let bool_var = var_store.fresh();
@ -3693,7 +3693,7 @@ fn list_all(symbol: Symbol, var_store: &mut VarStore) -> Def {
lowlevel_2(symbol, LowLevel::ListAll, var_store) lowlevel_2(symbol, LowLevel::ListAll, var_store)
} }
/// List.find : List elem, (elem -> Bool) -> Result elem [ NotFound ]* /// List.find : List elem, (elem -> Bool) -> Result elem [NotFound]*
fn list_find(symbol: Symbol, var_store: &mut VarStore) -> Def { fn list_find(symbol: Symbol, var_store: &mut VarStore) -> Def {
let list = Symbol::ARG_1; let list = Symbol::ARG_1;
let find_predicate = Symbol::ARG_2; let find_predicate = Symbol::ARG_2;
@ -3859,7 +3859,7 @@ fn dict_contains(symbol: Symbol, var_store: &mut VarStore) -> Def {
lowlevel_2(symbol, LowLevel::DictContains, var_store) lowlevel_2(symbol, LowLevel::DictContains, var_store)
} }
/// Dict.get : Dict k v, k -> Result v [ KeyNotFound ]* /// Dict.get : Dict k v, k -> Result v [KeyNotFound]*
fn dict_get(symbol: Symbol, var_store: &mut VarStore) -> Def { fn dict_get(symbol: Symbol, var_store: &mut VarStore) -> Def {
let arg_dict = Symbol::ARG_1; let arg_dict = Symbol::ARG_1;
let arg_key = Symbol::ARG_2; let arg_key = Symbol::ARG_2;
@ -4169,7 +4169,7 @@ fn num_rem(symbol: Symbol, var_store: &mut VarStore) -> Def {
num_binop(symbol, var_store, LowLevel::NumRemUnchecked) num_binop(symbol, var_store, LowLevel::NumRemUnchecked)
} }
/// Num.remChecked : Int a, Int a -> Result (Int a) [ DivByZero ]* /// Num.remChecked : Int a, Int a -> Result (Int a) [DivByZero]*
fn num_rem_checked(symbol: Symbol, var_store: &mut VarStore) -> Def { fn num_rem_checked(symbol: Symbol, var_store: &mut VarStore) -> Def {
let num_var = var_store.fresh(); let num_var = var_store.fresh();
let unbound_zero_var = var_store.fresh(); let unbound_zero_var = var_store.fresh();
@ -4276,7 +4276,7 @@ fn num_div_frac(symbol: Symbol, var_store: &mut VarStore) -> Def {
num_binop(symbol, var_store, LowLevel::NumDivUnchecked) num_binop(symbol, var_store, LowLevel::NumDivUnchecked)
} }
/// Num.divChecked : Frac, Frac -> Result Frac [ DivByZero ]* /// Num.divChecked : Frac, Frac -> Result Frac [DivByZero]*
fn num_div_frac_checked(symbol: Symbol, var_store: &mut VarStore) -> Def { fn num_div_frac_checked(symbol: Symbol, var_store: &mut VarStore) -> Def {
let bool_var = var_store.fresh(); let bool_var = var_store.fresh();
let num_var = var_store.fresh(); let num_var = var_store.fresh();
@ -4347,7 +4347,7 @@ fn num_div_trunc(symbol: Symbol, var_store: &mut VarStore) -> Def {
num_binop(symbol, var_store, LowLevel::NumDivUnchecked) num_binop(symbol, var_store, LowLevel::NumDivUnchecked)
} }
/// Num.divTruncChecked : Int a , Int a -> Result (Int a) [ DivByZero ]* /// Num.divTruncChecked : Int a , Int a -> Result (Int a) [DivByZero]*
fn num_div_trunc_checked(symbol: Symbol, var_store: &mut VarStore) -> Def { fn num_div_trunc_checked(symbol: Symbol, var_store: &mut VarStore) -> Def {
let bool_var = var_store.fresh(); let bool_var = var_store.fresh();
let num_var = var_store.fresh(); let num_var = var_store.fresh();
@ -4423,7 +4423,7 @@ fn num_div_ceil(symbol: Symbol, var_store: &mut VarStore) -> Def {
num_binop(symbol, var_store, LowLevel::NumDivCeilUnchecked) num_binop(symbol, var_store, LowLevel::NumDivCeilUnchecked)
} }
/// Num.divCeilChecked : Int a , Int a -> Result (Int a) [ DivByZero ]* /// Num.divCeilChecked : Int a , Int a -> Result (Int a) [DivByZero]*
fn num_div_ceil_checked(symbol: Symbol, var_store: &mut VarStore) -> Def { fn num_div_ceil_checked(symbol: Symbol, var_store: &mut VarStore) -> Def {
let bool_var = var_store.fresh(); let bool_var = var_store.fresh();
let num_var = var_store.fresh(); let num_var = var_store.fresh();
@ -4494,11 +4494,11 @@ fn num_div_ceil_checked(symbol: Symbol, var_store: &mut VarStore) -> Def {
) )
} }
/// List.first : List elem -> Result elem [ ListWasEmpty ]* /// List.first : List elem -> Result elem [ListWasEmpty]*
/// ///
/// List.first : /// List.first :
/// Attr (* | u) (List (Attr u a)), /// Attr (* | u) (List (Attr u a)),
/// -> Attr * (Result (Attr u a) (Attr * [ OutOfBounds ]*)) /// -> Attr * (Result (Attr u a) (Attr * [OutOfBounds]*))
fn list_first(symbol: Symbol, var_store: &mut VarStore) -> Def { fn list_first(symbol: Symbol, var_store: &mut VarStore) -> Def {
let bool_var = var_store.fresh(); let bool_var = var_store.fresh();
let list_var = var_store.fresh(); let list_var = var_store.fresh();
@ -4580,11 +4580,11 @@ fn list_first(symbol: Symbol, var_store: &mut VarStore) -> Def {
) )
} }
/// List.last : List elem -> Result elem [ ListWasEmpty ]* /// List.last : List elem -> Result elem [ListWasEmpty]*
/// ///
/// List.last : /// List.last :
/// Attr (* | u) (List (Attr u a)), /// Attr (* | u) (List (Attr u a)),
/// -> Attr * (Result (Attr u a) (Attr * [ OutOfBounds ]*)) /// -> Attr * (Result (Attr u a) (Attr * [OutOfBounds]*))
fn list_last(symbol: Symbol, var_store: &mut VarStore) -> Def { fn list_last(symbol: Symbol, var_store: &mut VarStore) -> Def {
let arg_var = var_store.fresh(); let arg_var = var_store.fresh();
let bool_var = var_store.fresh(); let bool_var = var_store.fresh();

View file

@ -1810,19 +1810,19 @@ fn correct_mutual_recursive_type_alias<'a>(
// Within a recursive group, we must instantiate all aliases like how they came to the // Within a recursive group, we must instantiate all aliases like how they came to the
// loop. e.g. given // loop. e.g. given
// //
// A : [ ConsA B, NilA ] // A : [ConsA B, NilA]
// B : [ ConsB A, NilB ] // B : [ConsB A, NilB]
// //
// Our goal is // Our goal is
// //
// A : [ ConsA [ ConsB A, NilB ], NilA ] // A : [ConsA [ConsB A, NilB], NilA]
// B : [ ConsB [ ConsA B, NilA ], NilB ] // B : [ConsB [ConsA B, NilA], NilB]
// //
// But if we would first instantiate B into A, then use the updated A to instantiate B, // But if we would first instantiate B into A, then use the updated A to instantiate B,
// we get // we get
// //
// A : [ ConsA [ ConsB A, NilB ], NilA ] // A : [ConsA [ConsB A, NilB], NilA]
// B : [ ConsB [ ConsA [ ConsB A, NilB ], NilA ], NilB ] // B : [ConsB [ConsA [ConsB A, NilB], NilA], NilB]
// //
// Which is incorrect. We do need the instantiated version however. // Which is incorrect. We do need the instantiated version however.
// e.g. if in a next group we have: // e.g. if in a next group we have:
@ -1831,7 +1831,7 @@ fn correct_mutual_recursive_type_alias<'a>(
// //
// Then we must use the instantiated version // Then we must use the instantiated version
// //
// C : [ ConsA [ ConsB A, NilB ], NilA ] // C : [ConsA [ConsB A, NilB], NilA]
// //
// So, we cannot replace the original version of A with its instantiated version // So, we cannot replace the original version of A with its instantiated version
// while we process A's group. We have to store the instantiated version until the // while we process A's group. We have to store the instantiated version until the
@ -1997,21 +1997,21 @@ enum MakeTagUnionRecursive {
/// Attempt to make a tag union recursive at the position of `recursive_alias`; for example, /// Attempt to make a tag union recursive at the position of `recursive_alias`; for example,
/// ///
/// ```roc /// ```roc
/// [ Cons a (ConsList a), Nil ] as ConsList a /// [Cons a (ConsList a), Nil] as ConsList a
/// ``` /// ```
/// ///
/// can be made recursive at the position "ConsList a" with a fresh recursive variable, say r1: /// can be made recursive at the position "ConsList a" with a fresh recursive variable, say r1:
/// ///
/// ```roc /// ```roc
/// [ Cons a r1, Nil ] as r1 /// [Cons a r1, Nil] as r1
/// ``` /// ```
/// ///
/// Returns `Err` if the tag union is recursive, but there is no structure-preserving recursion /// Returns `Err` if the tag union is recursive, but there is no structure-preserving recursion
/// variable for it. This can happen when the type is a nested datatype, for example in either of /// variable for it. This can happen when the type is a nested datatype, for example in either of
/// ///
/// ```roc /// ```roc
/// Nested a : [ Chain a (Nested (List a)), Term ] /// Nested a : [Chain a (Nested (List a)), Term]
/// DuoList a b : [ Cons a (DuoList b a), Nil ] /// DuoList a b : [Cons a (DuoList b a), Nil]
/// ``` /// ```
/// ///
/// When `Err` is returned, a problem will be added to `env`. /// When `Err` is returned, a problem will be added to `env`.

View file

@ -78,7 +78,7 @@ pub(crate) fn build_effect_builtins(
)); ));
} }
// Effect.loop : a, (a -> Effect [ Step a, Done b ]) -> Effect b // Effect.loop : a, (a -> Effect [Step a, Done b]) -> Effect b
if generated_functions.loop_ { if generated_functions.loop_ {
let def = helper!(build_effect_loop); let def = helper!(build_effect_loop);
declarations.push(Declaration::DeclareRec( declarations.push(Declaration::DeclareRec(
@ -708,7 +708,7 @@ fn build_effect_forever(
// thunk2 = Effect.forever effect // thunk2 = Effect.forever effect
// thunk2 {} // thunk2 {}
// //
// Effect.forever : [ C foreverInner { effect : T } ] // Effect.forever : [C foreverInner { effect : T }]
// Effect.forever = \effect -> // Effect.forever = \effect ->
// C { effect } // C { effect }
// //

View file

@ -202,7 +202,7 @@ pub enum Expr {
// definition, which we then use during constraint generation. For example // definition, which we then use during constraint generation. For example
// suppose we have // suppose we have
// //
// Id n := [ Id U64 n ] // Id n := [Id U64 n]
// @Id "sasha" // @Id "sasha"
// //
// Then `opaque` is "Id", `argument` is "sasha", but this is not enough for us to // Then `opaque` is "Id", `argument` is "sasha", but this is not enough for us to
@ -210,7 +210,7 @@ pub enum Expr {
// the variable "n". // the variable "n".
// That's what `specialized_def_type` and `type_arguments` are for; they are specialized // That's what `specialized_def_type` and `type_arguments` are for; they are specialized
// for the expression from the opaque definition. `type_arguments` is something like // for the expression from the opaque definition. `type_arguments` is something like
// [(n, fresh1)], and `specialized_def_type` becomes "[ Id U64 fresh1 ]". // [(n, fresh1)], and `specialized_def_type` becomes "[Id U64 fresh1]".
specialized_def_type: Box<Type>, specialized_def_type: Box<Type>,
type_arguments: Vec<OptAbleVar>, type_arguments: Vec<OptAbleVar>,
lambda_set_variables: Vec<LambdaSet>, lambda_set_variables: Vec<LambdaSet>,

View file

@ -213,7 +213,7 @@ pub fn canonicalize_module_defs<'a>(
// Exposed values are treated like defs that appear before any others, e.g. // Exposed values are treated like defs that appear before any others, e.g.
// //
// imports [ Foo.{ bar, baz } ] // imports [Foo.{ bar, baz }]
// //
// ...is basically the same as if we'd added these extra defs at the start of the module: // ...is basically the same as if we'd added these extra defs at the start of the module:
// //
@ -233,7 +233,7 @@ pub fn canonicalize_module_defs<'a>(
Ok(()) => { Ok(()) => {
// Add an entry to exposed_imports using the current module's name // Add an entry to exposed_imports using the current module's name
// as the key; e.g. if this is the Foo module and we have // as the key; e.g. if this is the Foo module and we have
// exposes [ Bar.{ baz } ] then insert Foo.baz as the key, so when // exposes [Bar.{ baz }] then insert Foo.baz as the key, so when
// anything references `baz` in this Foo module, it will resolve to Bar.baz. // anything references `baz` in this Foo module, it will resolve to Bar.baz.
can_exposed_imports.insert(symbol, expr_var); can_exposed_imports.insert(symbol, expr_var);

View file

@ -35,7 +35,7 @@ pub enum Pattern {
// definition, which we then use during constraint generation. For example // definition, which we then use during constraint generation. For example
// suppose we have // suppose we have
// //
// Id n := [ Id U64 n ] // Id n := [Id U64 n]
// strToBool : Str -> Bool // strToBool : Str -> Bool
// //
// f = \@Id who -> strToBool who // f = \@Id who -> strToBool who
@ -45,7 +45,7 @@ pub enum Pattern {
// the variable "n". // the variable "n".
// That's what `specialized_def_type` and `type_arguments` are for; they are specialized // That's what `specialized_def_type` and `type_arguments` are for; they are specialized
// for the expression from the opaque definition. `type_arguments` is something like // for the expression from the opaque definition. `type_arguments` is something like
// [(n, fresh1)], and `specialized_def_type` becomes "[ Id U64 fresh1 ]". // [(n, fresh1)], and `specialized_def_type` becomes "[Id U64 fresh1]".
specialized_def_type: Box<Type>, specialized_def_type: Box<Type>,
type_arguments: Vec<OptAbleVar>, type_arguments: Vec<OptAbleVar>,
lambda_set_variables: Vec<LambdaSet>, lambda_set_variables: Vec<LambdaSet>,

View file

@ -1015,7 +1015,7 @@ mod test_can {
fn unused_def_regression() { fn unused_def_regression() {
let src = indoc!( let src = indoc!(
r#" r#"
Booly : [ Yes, No, Maybe ] Booly : [Yes, No, Maybe]
y : Booly y : Booly
y = No y = No
@ -1025,7 +1025,7 @@ mod test_can {
# #
# https://github.com/rtfeldman/roc/issues/298 # https://github.com/rtfeldman/roc/issues/298
x : List Booly x : List Booly
x = [ y ] x = [y]
x x
"# "#

View file

@ -2138,10 +2138,10 @@ pub fn rec_defs_help(
// the let-generalization. // the let-generalization.
// 2. Introduce all symbols of the untyped defs, but don't generalize them yet. Now, solve // 2. Introduce all symbols of the untyped defs, but don't generalize them yet. Now, solve
// the untyped defs' bodies. This way, when checking something like // the untyped defs' bodies. This way, when checking something like
// f = \x -> f [ x ] // f = \x -> f [x]
// we introduce `f: b -> c`, then constrain the call `f [ x ]`, // we introduce `f: b -> c`, then constrain the call `f [x]`,
// forcing `b -> c ~ List b -> c` and correctly picking up a recursion error. // forcing `b -> c ~ List b -> c` and correctly picking up a recursion error.
// Had we generalized `b -> c`, the call `f [ x ]` would have been generalized, and this // Had we generalized `b -> c`, the call `f [x]` would have been generalized, and this
// error would not be found. // error would not be found.
// 3. Now properly let-generalize the untyped body defs, since we now know their types and // 3. Now properly let-generalize the untyped body defs, since we now know their types and
// that they don't have circular type errors. // that they don't have circular type errors.

View file

@ -509,7 +509,7 @@ pub fn constrain_pattern(
type_arguments, type_arguments,
lambda_set_variables, lambda_set_variables,
} => { } => {
// Suppose we are constraining the pattern \@Id who, where Id n := [ Id U64 n ] // Suppose we are constraining the pattern \@Id who, where Id n := [Id U64 n]
let (arg_pattern_var, loc_arg_pattern) = &**argument; let (arg_pattern_var, loc_arg_pattern) = &**argument;
let arg_pattern_type = Type::Variable(*arg_pattern_var); let arg_pattern_type = Type::Variable(*arg_pattern_var);
@ -549,15 +549,15 @@ pub fn constrain_pattern(
// Link the entire wrapped opaque type (with the now-constrained argument) to the type // Link the entire wrapped opaque type (with the now-constrained argument) to the type
// variables of the opaque type. // variables of the opaque type.
// //
// For example, suppose we have `O k := [ A k, B k ]`, and the pattern `@O (A s) -> s == ""`. // For example, suppose we have `O k := [A k, B k]`, and the pattern `@O (A s) -> s == ""`.
// Previous constraints will have solved `typeof s ~ Str`, and we have the // Previous constraints will have solved `typeof s ~ Str`, and we have the
// `specialized_def_type` being `[ A k1, B k1 ]`, specializing `k` as `k1` for this opaque // `specialized_def_type` being `[A k1, B k1]`, specializing `k` as `k1` for this opaque
// usage. // usage.
// We now want to link `typeof s ~ k1`, so to capture this relationship, we link // We now want to link `typeof s ~ k1`, so to capture this relationship, we link
// the type of `A s` (the arg type) to `[ A k1, B k1 ]` (the specialized opaque type). // the type of `A s` (the arg type) to `[A k1, B k1]` (the specialized opaque type).
// //
// This must **always** be a presence constraint, that is enforcing // This must **always** be a presence constraint, that is enforcing
// `[ A k1, B k1 ] += typeof (A s)`, because we are in a destructure position and not // `[A k1, B k1] += typeof (A s)`, because we are in a destructure position and not
// all constructors are covered in this branch! // all constructors are covered in this branch!
let link_type_variables_con = constraints.pattern_presence( let link_type_variables_con = constraints.pattern_presence(
arg_pattern_type, arg_pattern_type,

View file

@ -380,7 +380,7 @@ fn build_transform_caller_help<'a, 'ctx, 'env>(
env, env,
fn_name, fn_name,
env.context.void_type().into(), env.context.void_type().into(),
&(bumpalo::vec![ in env.arena; BasicTypeEnum::PointerType(arg_type); argument_layouts.len() + 2 ]), &(bumpalo::vec![in env.arena; BasicTypeEnum::PointerType(arg_type); argument_layouts.len() + 2]),
); );
// called from zig, must use C calling convention // called from zig, must use C calling convention

View file

@ -5652,7 +5652,7 @@ fn run_low_level<'a, 'ctx, 'env>(
list_join(env, list, element_layout) list_join(env, list, element_layout)
} }
ListGetUnsafe => { ListGetUnsafe => {
// List.get : List elem, Nat -> [ Ok elem, OutOfBounds ]* // List.get : List elem, Nat -> [Ok elem, OutOfBounds]*
debug_assert_eq!(args.len(), 2); debug_assert_eq!(args.len(), 2);
let (wrapper_struct, list_layout) = load_symbol_and_layout(scope, &args[0]); let (wrapper_struct, list_layout) = load_symbol_and_layout(scope, &args[0]);
@ -7258,7 +7258,7 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
) )
} }
NumToIntChecked => { NumToIntChecked => {
// return_layout : Result N [ OutOfBounds ]* ~ { result: N, out_of_bounds: bool } // return_layout : Result N [OutOfBounds]* ~ { result: N, out_of_bounds: bool }
let target_int_width = match return_layout { let target_int_width = match return_layout {
Layout::Struct { field_layouts, .. } if field_layouts.len() == 2 => { Layout::Struct { field_layouts, .. } if field_layouts.len() == 2 => {

View file

@ -116,8 +116,8 @@ pub fn basic_type_from_builtin<'a, 'ctx, 'env>(
/// Current differences /// Current differences
/// ///
/// - tag unions are passed by-reference. That means that /// - tag unions are passed by-reference. That means that
/// * `f : [ Some I64, None ] -> I64` is typed `{ { i64, i8 }, i64 }* -> i64` /// * `f : [Some I64, None] -> I64` is typed `{ { i64, i8 }, i64 }* -> i64`
/// * `f : { x : [ Some I64, None ] } -> I64 is typed `{ { { i64, i8 }, i64 } } -> i64` /// * `f : { x : [Some I64, None] } -> I64 is typed `{ { { i64, i8 }, i64 } } -> i64`
/// ///
/// Ideas exist to have (bigger than 2 register) records also be passed by-reference, but this /// Ideas exist to have (bigger than 2 register) records also be passed by-reference, but this
/// is not currently implemented /// is not currently implemented

View file

@ -82,7 +82,7 @@ In this backend, each symbol in the Mono IR gets one WebAssembly local. To illus
The WebAssembly code below is completely unoptimised and uses far more locals than necessary. But that does help to illustrate the concept of locals. The WebAssembly code below is completely unoptimised and uses far more locals than necessary. But that does help to illustrate the concept of locals.
``` ```
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
main = main =
1 + 2 + 4 1 + 2 + 4

View file

@ -222,7 +222,7 @@ impl From<String> for IdentStr {
impl fmt::Debug for IdentStr { impl fmt::Debug for IdentStr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// IdentStr { is_small_str: false, storage: Refcounted(3), elements: [ 1,2,3,4] } // IdentStr { is_small_str: false, storage: Refcounted(3), elements: [1,2,3,4] }
f.debug_struct("IdentStr") f.debug_struct("IdentStr")
//.field("is_small_str", &self.is_small_str()) //.field("is_small_str", &self.is_small_str())
.field("string", &self.as_str()) .field("string", &self.as_str())
@ -233,7 +233,7 @@ impl fmt::Debug for IdentStr {
impl fmt::Display for IdentStr { impl fmt::Display for IdentStr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// IdentStr { is_small_str: false, storage: Refcounted(3), elements: [ 1,2,3,4] } // IdentStr { is_small_str: false, storage: Refcounted(3), elements: [1,2,3,4] }
f.write_str(self.as_str()) f.write_str(self.as_str())
} }
} }

View file

@ -3126,7 +3126,7 @@ fn send_header<'a>(
// For each of our imports, add an entry to deps_by_name // For each of our imports, add an entry to deps_by_name
// //
// e.g. for `imports [ pf.Foo.{ bar } ]`, add `Foo` to deps_by_name // e.g. for `imports [pf.Foo.{ bar }]`, add `Foo` to deps_by_name
// //
// Also build a list of imported_values_to_expose (like `bar` above.) // Also build a list of imported_values_to_expose (like `bar` above.)
for (qualified_module_name, exposed_idents, region) in imported.into_iter() { for (qualified_module_name, exposed_idents, region) in imported.into_iter() {
@ -3175,7 +3175,7 @@ fn send_header<'a>(
// created an IdentId for this, when it was imported exposed // created an IdentId for this, when it was imported exposed
// in a dependent module. // in a dependent module.
// //
// For example, if module A has [ B.{ foo } ], then // For example, if module A has [B.{ foo }], then
// when we get here for B, `foo` will already have // when we get here for B, `foo` will already have
// an IdentId. We must reuse that! // an IdentId. We must reuse that!
let ident_id = ident_ids.get_or_insert(&loc_exposed.value.as_str().into()); let ident_id = ident_ids.get_or_insert(&loc_exposed.value.as_str().into());
@ -3340,7 +3340,7 @@ fn send_header_two<'a>(
// For each of our imports, add an entry to deps_by_name // For each of our imports, add an entry to deps_by_name
// //
// e.g. for `imports [ pf.Foo.{ bar } ]`, add `Foo` to deps_by_name // e.g. for `imports [pf.Foo.{ bar }]`, add `Foo` to deps_by_name
// //
// Also build a list of imported_values_to_expose (like `bar` above.) // Also build a list of imported_values_to_expose (like `bar` above.)
for (qualified_module_name, exposed_idents, region) in imported.into_iter() { for (qualified_module_name, exposed_idents, region) in imported.into_iter() {
@ -3420,7 +3420,7 @@ fn send_header_two<'a>(
// created an IdentId for this, when it was imported exposed // created an IdentId for this, when it was imported exposed
// in a dependent module. // in a dependent module.
// //
// For example, if module A has [ B.{ foo } ], then // For example, if module A has [B.{ foo }], then
// when we get here for B, `foo` will already have // when we get here for B, `foo` will already have
// an IdentId. We must reuse that! // an IdentId. We must reuse that!
let ident_id = ident_ids.get_or_insert(&loc_exposed.value.as_str().into()); let ident_id = ident_ids.get_or_insert(&loc_exposed.value.as_str().into());

View file

@ -1,5 +1,5 @@
interface AStar interface AStar
exposes [ initialModel, reconstructPath, updateCost, cheapestOpen, astar, findPath ] exposes [initialModel, reconstructPath, updateCost, cheapestOpen, astar, findPath]
imports [] imports []
@ -22,7 +22,7 @@ initialModel = \start ->
} }
cheapestOpen : (position -> F64), Model position -> Result position [ KeyNotFound ]* cheapestOpen : (position -> F64), Model position -> Result position [KeyNotFound]*
cheapestOpen = \costFunction, model -> cheapestOpen = \costFunction, model ->
folder = \resSmallestSoFar, position -> folder = \resSmallestSoFar, position ->
@ -80,12 +80,12 @@ updateCost = \current, neighbour, model ->
model model
findPath : { costFunction: (position, position -> F64), moveFunction: (position -> Set position), start : position, end : position } -> Result (List position) [ KeyNotFound ]* findPath : { costFunction: (position, position -> F64), moveFunction: (position -> Set position), start : position, end : position } -> Result (List position) [KeyNotFound]*
findPath = \{ costFunction, moveFunction, start, end } -> findPath = \{ costFunction, moveFunction, start, end } ->
astar costFunction moveFunction end (initialModel start) astar costFunction moveFunction end (initialModel start)
astar : (position, position -> F64), (position -> Set position), position, Model position -> [ Err [ KeyNotFound ]*, Ok (List position) ]* astar : (position, position -> F64), (position -> Set position), position, Model position -> [Err [KeyNotFound]*, Ok (List position)]*
astar = \costFn, moveFn, goal, model -> astar = \costFn, moveFn, goal, model ->
when cheapestOpen (\position -> costFn goal position) model is when cheapestOpen (\position -> costFn goal position) model is
Err _ -> Err _ ->

View file

@ -1,6 +1,6 @@
interface Dep1 interface Dep1
exposes [ three, str, Unit, Identity, one, two ] exposes [three, str, Unit, Identity, one, two]
imports [ Dep3.Blah.{ foo } ] imports [Dep3.Blah.{ foo }]
one = 1 one = 1
@ -10,6 +10,6 @@ three = 3.0
str = "string!" str = "string!"
Unit : [ Unit ] Unit : [Unit]
Identity a : [ Identity a ] Identity a : [Identity a]

View file

@ -1,6 +1,6 @@
interface Dep2 interface Dep2
exposes [ one, two, blah ] exposes [one, two, blah]
imports [ Dep3.Blah.{ foo, bar } ] imports [Dep3.Blah.{ foo, bar }]
one = 1 one = 1

View file

@ -1,5 +1,5 @@
interface Dep3.Blah interface Dep3.Blah
exposes [ one, two, foo, bar ] exposes [one, two, foo, bar]
imports [] imports []
one = 1 one = 1

View file

@ -1,6 +1,6 @@
interface ImportAlias interface ImportAlias
exposes [ unit ] exposes [unit]
imports [ Dep1 ] imports [Dep1]
unit : Dep1.Unit unit : Dep1.Unit
unit = Unit unit = Unit

View file

@ -1,5 +1,5 @@
interface OneDep interface OneDep
exposes [ str ] exposes [str]
imports [ Dep3.Blah.{ foo } ] imports [Dep3.Blah.{ foo }]
str = foo str = foo

View file

@ -1,6 +1,6 @@
interface Primary interface Primary
exposes [ blah2, blah3, str, alwaysThree, identity, z, w, succeed, withDefault, yay ] exposes [blah2, blah3, str, alwaysThree, identity, z, w, succeed, withDefault, yay]
imports [ Dep1, Dep2.{ two, foo }, Dep3.Blah.{ bar }, Res ] imports [Dep1, Dep2.{ two, foo }, Dep3.Blah.{ bar }, Res]
blah2 = Dep2.two blah2 = Dep2.two
blah3 = bar blah3 = bar

View file

@ -1,4 +1,4 @@
app "quicksort" provides [ swap, partition, partitionHelp, quicksort ] to "./platform" app "quicksort" provides [swap, partition, partitionHelp, quicksort] to "./platform"
quicksort : List (Num a), Nat, Nat -> List (Num a) quicksort : List (Num a), Nat, Nat -> List (Num a)
quicksort = \list, low, high -> quicksort = \list, low, high ->
@ -21,7 +21,7 @@ swap = \i, j, list ->
[] []
partition : Nat, Nat, List (Num a) -> [ Pair Nat (List (Num a)) ] partition : Nat, Nat, List (Num a) -> [Pair Nat (List (Num a))]
partition = \low, high, initialList -> partition = \low, high, initialList ->
when List.get initialList high is when List.get initialList high is
Ok pivot -> Ok pivot ->
@ -33,7 +33,7 @@ partition = \low, high, initialList ->
Pair (low - 1) initialList Pair (low - 1) initialList
partitionHelp : Nat, Nat, List (Num a), Nat, (Num a) -> [ Pair Nat (List (Num a)) ] partitionHelp : Nat, Nat, List (Num a), Nat, (Num a) -> [Pair Nat (List (Num a))]
partitionHelp = \i, j, list, high, pivot -> partitionHelp = \i, j, list, high, pivot ->
if j < high then if j < high then
when List.get list j is when List.get list j is

View file

@ -1,4 +1,4 @@
app "quicksort" provides [ quicksort ] to "./platform" app "quicksort" provides [quicksort] to "./platform"
quicksort = \originalList -> quicksort = \originalList ->
quicksortHelp : List (Num a), Nat, Nat -> List (Num a) quicksortHelp : List (Num a), Nat, Nat -> List (Num a)
@ -24,7 +24,7 @@ quicksort = \originalList ->
_ -> _ ->
[] []
partition : Nat, Nat, List (Num a) -> [ Pair Nat (List (Num a)) ] partition : Nat, Nat, List (Num a) -> [Pair Nat (List (Num a))]
partition = \low, high, initialList -> partition = \low, high, initialList ->
when List.get initialList high is when List.get initialList high is
Ok pivot -> Ok pivot ->
@ -36,7 +36,7 @@ quicksort = \originalList ->
Pair (low - 1) initialList Pair (low - 1) initialList
partitionHelp : Nat, Nat, List (Num a), Nat, (Num a) -> [ Pair Nat (List (Num a)) ] partitionHelp : Nat, Nat, List (Num a), Nat, (Num a) -> [Pair Nat (List (Num a))]
partitionHelp = \i, j, list, high, pivot -> partitionHelp = \i, j, list, high, pivot ->
if j < high then if j < high then
when List.get list j is when List.get list j is

View file

@ -1,5 +1,5 @@
interface Records interface Records
exposes [ intVal ] exposes [intVal]
imports [] imports []
intVal = intVal =

View file

@ -1,10 +1,10 @@
interface Res interface Res
exposes [ Res, withDefault, map, andThen, ConsList ] exposes [Res, withDefault, map, andThen, ConsList]
imports [] imports []
Res ok err : [ Ok ok, Err err ] Res ok err : [Ok ok, Err err]
ConsList a : [ Cons a (ConsList a), Nil ] ConsList a : [Cons a (ConsList a), Nil]
listMap : ConsList a, (a -> b) -> ConsList b listMap : ConsList a, (a -> b) -> ConsList b
listMap = \list, f -> listMap = \list, f ->

View file

@ -1,6 +1,6 @@
interface WithBuiltins interface WithBuiltins
exposes [ floatTest, divisionFn, divisionTest, intTest, constantNum, fromDep2, divDep1ByDep2 ] exposes [floatTest, divisionFn, divisionTest, intTest, constantNum, fromDep2, divDep1ByDep2]
imports [ Dep1, Dep2.{ two } ] imports [Dep1, Dep2.{ two }]
floatTest = Num.maxF64 floatTest = Num.maxF64

View file

@ -1,5 +1,5 @@
interface AStar interface AStar
exposes [ initialModel, reconstructPath, updateCost, cheapestOpen, astar, findPath ] exposes [initialModel, reconstructPath, updateCost, cheapestOpen, astar, findPath]
imports [] imports []
@ -22,7 +22,7 @@ initialModel = \start ->
} }
cheapestOpen : (position -> F64), Model position -> Result position [ KeyNotFound ]* cheapestOpen : (position -> F64), Model position -> Result position [KeyNotFound]*
cheapestOpen = \costFunction, model -> cheapestOpen = \costFunction, model ->
folder = \resSmallestSoFar, position -> folder = \resSmallestSoFar, position ->
@ -80,12 +80,12 @@ updateCost = \current, neighbour, model ->
model model
findPath : { costFunction: (position, position -> F64), moveFunction: (position -> Set position), start : position, end : position } -> Result (List position) [ KeyNotFound ]* findPath : { costFunction: (position, position -> F64), moveFunction: (position -> Set position), start : position, end : position } -> Result (List position) [KeyNotFound]*
findPath = \{ costFunction, moveFunction, start, end } -> findPath = \{ costFunction, moveFunction, start, end } ->
astar costFunction moveFunction end (initialModel start) astar costFunction moveFunction end (initialModel start)
astar : (position, position -> F64), (position -> Set position), position, Model position -> [ Err [ KeyNotFound ]*, Ok (List position) ]* astar : (position, position -> F64), (position -> Set position), position, Model position -> [Err [KeyNotFound]*, Ok (List position)]*
astar = \costFn, moveFn, goal, model -> astar = \costFn, moveFn, goal, model ->
when cheapestOpen (\position -> costFn goal position) model is when cheapestOpen (\position -> costFn goal position) model is
Err _ -> Err _ ->

View file

@ -1,6 +1,6 @@
interface Dep1 interface Dep1
exposes [ three, str, Unit, Identity, one, two ] exposes [three, str, Unit, Identity, one, two]
imports [ Dep3.Blah.{ foo } ] imports [Dep3.Blah.{ foo }]
one = 1 one = 1
@ -10,6 +10,6 @@ three = 3.0
str = "string!" str = "string!"
Unit : [ Unit ] Unit : [Unit]
Identity a : [ Identity a ] Identity a : [Identity a]

View file

@ -1,6 +1,6 @@
interface Dep2 interface Dep2
exposes [ one, two, blah ] exposes [one, two, blah]
imports [ Dep3.Blah.{ foo, bar } ] imports [Dep3.Blah.{ foo, bar }]
one = 1 one = 1

View file

@ -1,5 +1,5 @@
interface Dep3.Blah interface Dep3.Blah
exposes [ one, two, foo, bar ] exposes [one, two, foo, bar]
imports [] imports []
one = 1 one = 1

View file

@ -1,6 +1,6 @@
interface ImportAlias interface ImportAlias
exposes [ unit ] exposes [unit]
imports [ Dep1 ] imports [Dep1]
unit : Dep1.Unit unit : Dep1.Unit
unit = Unit unit = Unit

View file

@ -1,5 +1,5 @@
interface OneDep interface OneDep
exposes [ str ] exposes [str]
imports [ Dep3.Blah.{ foo } ] imports [Dep3.Blah.{ foo }]
str = foo str = foo

View file

@ -1,6 +1,6 @@
interface Primary interface Primary
exposes [ blah2, blah3, str, alwaysThree, identity, z, w, succeed, withDefault, yay ] exposes [blah2, blah3, str, alwaysThree, identity, z, w, succeed, withDefault, yay]
imports [ Dep1, Dep2.{ two, foo }, Dep3.Blah.{ bar }, Res ] imports [Dep1, Dep2.{ two, foo }, Dep3.Blah.{ bar }, Res]
blah2 = Dep2.two blah2 = Dep2.two
blah3 = bar blah3 = bar

View file

@ -1,5 +1,5 @@
interface Quicksort interface Quicksort
exposes [ swap, partition, quicksort ] exposes [swap, partition, quicksort]
imports [] imports []
quicksort : List (Num a), Nat, Nat -> List (Num a) quicksort : List (Num a), Nat, Nat -> List (Num a)
@ -23,7 +23,7 @@ swap = \i, j, list ->
[] []
partition : Nat, Nat, List (Num a) -> [ Pair Nat (List (Num a)) ] partition : Nat, Nat, List (Num a) -> [Pair Nat (List (Num a))]
partition = \low, high, initialList -> partition = \low, high, initialList ->
when List.get initialList high is when List.get initialList high is
Ok pivot -> Ok pivot ->
@ -35,7 +35,7 @@ partition = \low, high, initialList ->
Pair (low - 1) initialList Pair (low - 1) initialList
partitionHelp : Nat, Nat, List (Num a), Nat, (Num a) -> [ Pair Nat (List (Num a)) ] partitionHelp : Nat, Nat, List (Num a), Nat, (Num a) -> [Pair Nat (List (Num a))]
partitionHelp = \i, j, list, high, pivot -> partitionHelp = \i, j, list, high, pivot ->
if j < high then if j < high then
when List.get list j is when List.get list j is

View file

@ -1,5 +1,5 @@
interface Records interface Records
exposes [ intVal ] exposes [intVal]
imports [] imports []
intVal = intVal =

View file

@ -1,10 +1,10 @@
interface Res interface Res
exposes [ Res, withDefault, map, listMap, andThen, ConsList ] exposes [Res, withDefault, map, listMap, andThen, ConsList]
imports [] imports []
Res ok err : [ Ok ok, Err err ] Res ok err : [Ok ok, Err err]
ConsList a : [ Cons a (ConsList a), Nil ] ConsList a : [Cons a (ConsList a), Nil]
listMap : ConsList a, (a -> b) -> ConsList b listMap : ConsList a, (a -> b) -> ConsList b
listMap = \list, f -> listMap = \list, f ->

View file

@ -1,6 +1,6 @@
interface WithBuiltins interface WithBuiltins
exposes [ floatTest, divisionFn, divisionTest, intTest, constantNum, fromDep2, divDep1ByDep2 ] exposes [floatTest, divisionFn, divisionTest, intTest, constantNum, fromDep2, divDep1ByDep2]
imports [ Dep1, Dep2.{ two } ] imports [Dep1, Dep2.{ two }]
floatTest = Num.maxF64 floatTest = Num.maxF64

View file

@ -1,8 +1,8 @@
interface MissingDep interface MissingDep
exposes [ unit ] exposes [unit]
imports [ ThisFileIsMissing ] imports [ThisFileIsMissing]
Unit : [ Unit ] Unit : [Unit]
unit : Unit unit : Unit
unit = Unit unit = Unit

View file

@ -1,5 +1,5 @@
interface Principal interface Principal
exposes [ identity, intVal ] exposes [identity, intVal]
imports [] imports []
identity = \a -> a identity = \a -> a

View file

@ -1,8 +1,8 @@
interface Unit interface Unit
exposes [ unit ] exposes [unit]
imports [] imports []
Unit : [ Unit ] Unit : [Unit]
unit : Unit unit : Unit
unit = Unit unit = Unit

View file

@ -309,12 +309,12 @@ mod test_load {
"RBTree", "RBTree",
indoc!( indoc!(
r#" r#"
interface RBTree exposes [ RedBlackTree, empty ] imports [] interface RBTree exposes [RedBlackTree, empty] imports []
# The color of a node. Leaves are considered Black. # The color of a node. Leaves are considered Black.
NodeColor : [ Red, Black ] NodeColor : [Red, Black]
RedBlackTree k v : [ Node NodeColor k v (RedBlackTree k v) (RedBlackTree k v), Empty ] RedBlackTree k v : [Node NodeColor k v (RedBlackTree k v) (RedBlackTree k v), Empty]
# Create an empty dictionary. # Create an empty dictionary.
empty : RedBlackTree k v empty : RedBlackTree k v
@ -327,7 +327,7 @@ mod test_load {
"Main", "Main",
indoc!( indoc!(
r#" r#"
interface Other exposes [ empty ] imports [ RBTree ] interface Other exposes [empty] imports [RBTree]
empty : RBTree.RedBlackTree I64 I64 empty : RBTree.RedBlackTree I64 I64
empty = RBTree.empty empty = RBTree.empty
@ -440,8 +440,8 @@ mod test_load {
loaded_module, loaded_module,
hashmap! { hashmap! {
"swap" => "Nat, Nat, List a -> List a", "swap" => "Nat, Nat, List a -> List a",
"partition" => "Nat, Nat, List (Num a) -> [ Pair Nat (List (Num a)) ]", "partition" => "Nat, Nat, List (Num a) -> [Pair Nat (List (Num a))]",
"partitionHelp" => "Nat, Nat, List (Num a), Nat, Num a -> [ Pair Nat (List (Num a)) ]", "partitionHelp" => "Nat, Nat, List (Num a), Nat, Num a -> [Pair Nat (List (Num a))]",
"quicksort" => "List (Num a), Nat, Nat -> List (Num a)", "quicksort" => "List (Num a), Nat, Nat -> List (Num a)",
}, },
); );
@ -469,8 +469,8 @@ mod test_load {
loaded_module, loaded_module,
hashmap! { hashmap! {
"swap" => "Nat, Nat, List a -> List a", "swap" => "Nat, Nat, List a -> List a",
"partition" => "Nat, Nat, List (Num a) -> [ Pair Nat (List (Num a)) ]", "partition" => "Nat, Nat, List (Num a) -> [Pair Nat (List (Num a))]",
"partitionHelp" => "Nat, Nat, List (Num a), Nat, Num a -> [ Pair Nat (List (Num a)) ]", "partitionHelp" => "Nat, Nat, List (Num a), Nat, Num a -> [Pair Nat (List (Num a))]",
"quicksort" => "List (Num a), Nat, Nat -> List (Num a)", "quicksort" => "List (Num a), Nat, Nat -> List (Num a)",
}, },
); );
@ -484,12 +484,12 @@ mod test_load {
expect_types( expect_types(
loaded_module, loaded_module,
hashmap! { hashmap! {
"findPath" => "{ costFunction : position, position -> F64, end : position, moveFunction : position -> Set position, start : position } -> Result (List position) [ KeyNotFound ]*", "findPath" => "{ costFunction : position, position -> F64, end : position, moveFunction : position -> Set position, start : position } -> Result (List position) [KeyNotFound]*",
"initialModel" => "position -> Model position", "initialModel" => "position -> Model position",
"reconstructPath" => "Dict position position, position -> List position", "reconstructPath" => "Dict position position, position -> List position",
"updateCost" => "position, position, Model position -> Model position", "updateCost" => "position, position, Model position -> Model position",
"cheapestOpen" => "(position -> F64), Model position -> Result position [ KeyNotFound ]*", "cheapestOpen" => "(position -> F64), Model position -> Result position [KeyNotFound]*",
"astar" => "(position, position -> F64), (position -> Set position), position, Model position -> [ Err [ KeyNotFound ]*, Ok (List position) ]*", "astar" => "(position, position -> F64), (position -> Set position), position, Model position -> [Err [KeyNotFound]*, Ok (List position)]*",
}, },
); );
} }
@ -571,7 +571,7 @@ mod test_load {
"Main", "Main",
indoc!( indoc!(
r#" r#"
interface Main exposes [ main ] imports [] interface Main exposes [main] imports []
main = [ main = [
"# "#
@ -590,7 +590,7 @@ mod test_load {
3 main = [ 3 main = [
^ ^
You could change it to something like [ 1, 2, 3 ] or even just []. You could change it to something like [1, 2, 3] or even just [].
Anything where there is an open and a close square bracket, and where Anything where there is an open and a close square bracket, and where
the elements of the list are separated by commas. the elements of the list are separated by commas.
@ -637,8 +637,8 @@ mod test_load {
r#" r#"
app "example" app "example"
packages { pf: "./zzz-does-not-exist" } packages { pf: "./zzz-does-not-exist" }
imports [ ] imports []
provides [ main ] to pf provides [main] to pf
main = "" main = ""
"# "#
@ -670,7 +670,7 @@ mod test_load {
exposes [] exposes []
packages {} packages {}
imports [] imports []
provides [ mainForHost ] provides [mainForHost]
blah 1 2 3 # causing a parse error on purpose blah 1 2 3 # causing a parse error on purpose
mainForHost : Str mainForHost : Str
@ -684,7 +684,7 @@ mod test_load {
app "hello-world" app "hello-world"
packages { pf: "platform" } packages { pf: "platform" }
imports [] imports []
provides [ main ] to pf provides [main] to pf
main = "Hello, World!\n" main = "Hello, World!\n"
"# "#
@ -714,7 +714,7 @@ mod test_load {
exposes [] exposes []
packages {} packages {}
imports [] imports []
provides [ mainForHost ] provides [mainForHost]
mainForHost : { content: Str, other: Str } mainForHost : { content: Str, other: Str }
mainForHost = main mainForHost = main
@ -728,7 +728,7 @@ mod test_load {
app "hello-world" app "hello-world"
packages { pf: "platform" } packages { pf: "platform" }
imports [] imports []
provides [ main ] to pf provides [main] to pf
main = { content: "Hello, World!\n", other: "" } main = { content: "Hello, World!\n", other: "" }
"# "#
@ -746,7 +746,7 @@ mod test_load {
"Age", "Age",
indoc!( indoc!(
r#" r#"
interface Age exposes [ Age ] imports [] interface Age exposes [Age] imports []
Age := U32 Age := U32
"# "#
@ -756,7 +756,7 @@ mod test_load {
"Main", "Main",
indoc!( indoc!(
r#" r#"
interface Main exposes [ twenty, readAge ] imports [ Age.{ Age } ] interface Main exposes [twenty, readAge] imports [Age.{ Age }]
twenty = @Age 20 twenty = @Age 20
@ -781,7 +781,7 @@ mod test_load {
is imported from another module: is imported from another module:
1 interface Main exposes [ twenty, readAge ] imports [ Age.{ Age } ] 1 interface Main exposes [twenty, readAge] imports [Age.{ Age }]
^^^^^^^^^^^ ^^^^^^^^^^^
Note: Opaque types can only be wrapped and unwrapped in the module they are defined in! Note: Opaque types can only be wrapped and unwrapped in the module they are defined in!
@ -795,7 +795,7 @@ mod test_load {
is imported from another module: is imported from another module:
1 interface Main exposes [ twenty, readAge ] imports [ Age.{ Age } ] 1 interface Main exposes [twenty, readAge] imports [Age.{ Age }]
^^^^^^^^^^^ ^^^^^^^^^^^
Note: Opaque types can only be wrapped and unwrapped in the module they are defined in! Note: Opaque types can only be wrapped and unwrapped in the module they are defined in!
@ -804,7 +804,7 @@ mod test_load {
Nothing from Age is used in this module. Nothing from Age is used in this module.
1 interface Main exposes [ twenty, readAge ] imports [ Age.{ Age } ] 1 interface Main exposes [twenty, readAge] imports [Age.{ Age }]
^^^^^^^^^^^ ^^^^^^^^^^^
Since Age isn't used, you don't need to import it. Since Age isn't used, you don't need to import it.
@ -827,7 +827,7 @@ mod test_load {
exposes [] exposes []
packages {} packages {}
imports [] imports []
provides [ mainForHost ] provides [mainForHost]
mainForHost : Str mainForHost : Str
mainForHost = main mainForHost = main
@ -840,7 +840,7 @@ mod test_load {
r#" r#"
app "test" app "test"
packages { pf: "platform" } packages { pf: "platform" }
provides [ main ] to pf provides [main] to pf
main : DoesNotExist main : DoesNotExist
main = 1 main = 1

View file

@ -1154,9 +1154,9 @@ define_builtins! {
} }
2 BOOL: "Bool" => { 2 BOOL: "Bool" => {
0 BOOL_BOOL: "Bool" // the Bool.Bool type alias 0 BOOL_BOOL: "Bool" // the Bool.Bool type alias
1 BOOL_FALSE: "False" imported // Bool.Bool = [ False, True ] 1 BOOL_FALSE: "False" imported // Bool.Bool = [False, True]
// NB: not strictly needed; used for finding tag names in error suggestions // NB: not strictly needed; used for finding tag names in error suggestions
2 BOOL_TRUE: "True" imported // Bool.Bool = [ False, True ] 2 BOOL_TRUE: "True" imported // Bool.Bool = [False, True]
// NB: not strictly needed; used for finding tag names in error suggestions // NB: not strictly needed; used for finding tag names in error suggestions
3 BOOL_AND: "and" 3 BOOL_AND: "and"
4 BOOL_OR: "or" 4 BOOL_OR: "or"
@ -1264,9 +1264,9 @@ define_builtins! {
} }
5 RESULT: "Result" => { 5 RESULT: "Result" => {
0 RESULT_RESULT: "Result" // the Result.Result type alias 0 RESULT_RESULT: "Result" // the Result.Result type alias
1 RESULT_OK: "Ok" imported // Result.Result a e = [ Ok a, Err e ] 1 RESULT_OK: "Ok" imported // Result.Result a e = [Ok a, Err e]
// NB: not strictly needed; used for finding tag names in error suggestions // NB: not strictly needed; used for finding tag names in error suggestions
2 RESULT_ERR: "Err" imported // Result.Result a e = [ Ok a, Err e ] 2 RESULT_ERR: "Err" imported // Result.Result a e = [Ok a, Err e]
// NB: not strictly needed; used for finding tag names in error suggestions // NB: not strictly needed; used for finding tag names in error suggestions
3 RESULT_MAP: "map" 3 RESULT_MAP: "map"
4 RESULT_MAP_ERR: "mapErr" 4 RESULT_MAP_ERR: "mapErr"

View file

@ -288,7 +288,7 @@ impl<'a> ParamMap<'a> {
fn visit_stmt(&mut self, arena: &'a Bump, _fnid: Symbol, stmt: &Stmt<'a>) { fn visit_stmt(&mut self, arena: &'a Bump, _fnid: Symbol, stmt: &Stmt<'a>) {
use Stmt::*; use Stmt::*;
let mut stack = bumpalo::vec![ in arena; stmt ]; let mut stack = bumpalo::vec![in arena; stmt];
while let Some(stmt) = stack.pop() { while let Some(stmt) = stack.pop() {
match stmt { match stmt {
@ -1001,7 +1001,7 @@ fn call_info_call<'a>(call: &crate::ir::Call<'a>, info: &mut CallInfo<'a>) {
fn call_info_stmt<'a>(arena: &'a Bump, stmt: &Stmt<'a>, info: &mut CallInfo<'a>) { fn call_info_stmt<'a>(arena: &'a Bump, stmt: &Stmt<'a>, info: &mut CallInfo<'a>) {
use Stmt::*; use Stmt::*;
let mut stack = bumpalo::vec![ in arena; stmt ]; let mut stack = bumpalo::vec![in arena; stmt];
while let Some(stmt) = stack.pop() { while let Some(stmt) = stack.pop() {
match stmt { match stmt {

View file

@ -401,7 +401,7 @@ impl<'a> CodeGenHelp<'a> {
// When creating or looking up Specializations, we need to replace RecursivePointer // When creating or looking up Specializations, we need to replace RecursivePointer
// with the particular Union layout it represents at this point in the tree. // with the particular Union layout it represents at this point in the tree.
// For example if a program uses `RoseTree a : [ Tree a (List (RoseTree a)) ]` // For example if a program uses `RoseTree a : [Tree a (List (RoseTree a))]`
// then it could have both `RoseTree I64` and `RoseTree Str`. In this case it // then it could have both `RoseTree I64` and `RoseTree Str`. In this case it
// needs *two* specializations for `List(RecursivePointer)`, not just one. // needs *two* specializations for `List(RecursivePointer)`, not just one.
fn replace_rec_ptr(&self, ctx: &Context<'a>, layout: Layout<'a>) -> Layout<'a> { fn replace_rec_ptr(&self, ctx: &Context<'a>, layout: Layout<'a>) -> Layout<'a> {

View file

@ -1455,11 +1455,11 @@ pub enum Literal<'a> {
/// Closed tag unions containing exactly two (0-arity) tags compile to Expr::Bool, /// Closed tag unions containing exactly two (0-arity) tags compile to Expr::Bool,
/// so they can (at least potentially) be emitted as 1-bit machine bools. /// so they can (at least potentially) be emitted as 1-bit machine bools.
/// ///
/// So [ True, False ] compiles to this, and so do [ A, B ] and [ Foo, Bar ]. /// So [True, False] compiles to this, and so do [A, B] and [Foo, Bar].
/// However, a union like [ True, False, Other Int ] would not. /// However, a union like [True, False, Other Int] would not.
Bool(bool), Bool(bool),
/// Closed tag unions containing between 3 and 256 tags (all of 0 arity) /// Closed tag unions containing between 3 and 256 tags (all of 0 arity)
/// compile to bytes, e.g. [ Blue, Black, Red, Green, White ] /// compile to bytes, e.g. [Blue, Black, Red, Green, White]
Byte(u8), Byte(u8),
} }

View file

@ -262,23 +262,23 @@ pub enum Layout<'a> {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum UnionLayout<'a> { pub enum UnionLayout<'a> {
/// A non-recursive tag union /// A non-recursive tag union
/// e.g. `Result a e : [ Ok a, Err e ]` /// e.g. `Result a e : [Ok a, Err e]`
NonRecursive(&'a [&'a [Layout<'a>]]), NonRecursive(&'a [&'a [Layout<'a>]]),
/// A recursive tag union (general case) /// A recursive tag union (general case)
/// e.g. `Expr : [ Sym Str, Add Expr Expr ]` /// e.g. `Expr : [Sym Str, Add Expr Expr]`
Recursive(&'a [&'a [Layout<'a>]]), Recursive(&'a [&'a [Layout<'a>]]),
/// A recursive tag union with just one constructor /// A recursive tag union with just one constructor
/// Optimization: No need to store a tag ID (the payload is "unwrapped") /// Optimization: No need to store a tag ID (the payload is "unwrapped")
/// e.g. `RoseTree a : [ Tree a (List (RoseTree a)) ]` /// e.g. `RoseTree a : [Tree a (List (RoseTree a))]`
NonNullableUnwrapped(&'a [Layout<'a>]), NonNullableUnwrapped(&'a [Layout<'a>]),
/// A recursive tag union that has an empty variant /// A recursive tag union that has an empty variant
/// Optimization: Represent the empty variant as null pointer => no memory usage & fast comparison /// Optimization: Represent the empty variant as null pointer => no memory usage & fast comparison
/// It has more than one other variant, so they need tag IDs (payloads are "wrapped") /// It has more than one other variant, so they need tag IDs (payloads are "wrapped")
/// e.g. `FingerTree a : [ Empty, Single a, More (Some a) (FingerTree (Tuple a)) (Some a) ]` /// e.g. `FingerTree a : [Empty, Single a, More (Some a) (FingerTree (Tuple a)) (Some a)]`
/// see also: https://youtu.be/ip92VMpf_-A?t=164 /// see also: https://youtu.be/ip92VMpf_-A?t=164
/// ///
/// nullable_id refers to the index of the tag that is represented at runtime as NULL. /// nullable_id refers to the index of the tag that is represented at runtime as NULL.
/// For example, in `FingerTree a : [ Empty, Single a, More (Some a) (FingerTree (Tuple a)) (Some a) ]`, /// For example, in `FingerTree a : [Empty, Single a, More (Some a) (FingerTree (Tuple a)) (Some a)]`,
/// the ids would be Empty = 0, More = 1, Single = 2, because that's how those tags are /// the ids would be Empty = 0, More = 1, Single = 2, because that's how those tags are
/// ordered alphabetically. Since the Empty tag will be represented at runtime as NULL, /// ordered alphabetically. Since the Empty tag will be represented at runtime as NULL,
/// and since Empty's tag id is 0, here nullable_id would be 0. /// and since Empty's tag id is 0, here nullable_id would be 0.
@ -288,12 +288,12 @@ pub enum UnionLayout<'a> {
}, },
/// A recursive tag union with only two variants, where one is empty. /// A recursive tag union with only two variants, where one is empty.
/// Optimizations: Use null for the empty variant AND don't store a tag ID for the other variant. /// Optimizations: Use null for the empty variant AND don't store a tag ID for the other variant.
/// e.g. `ConsList a : [ Nil, Cons a (ConsList a) ]` /// e.g. `ConsList a : [Nil, Cons a (ConsList a)]`
/// ///
/// nullable_id is a bool because it's only ever 0 or 1, but (as with the NullableWrapped /// nullable_id is a bool because it's only ever 0 or 1, but (as with the NullableWrapped
/// variant), it reprsents the index of the tag that will be represented at runtime as NULL. /// variant), it reprsents the index of the tag that will be represented at runtime as NULL.
/// ///
/// So for example, in `ConsList a : [ Nil, Cons a (ConsList a) ]`, Nil is tag id 1 and /// So for example, in `ConsList a : [Nil, Cons a (ConsList a)]`, Nil is tag id 1 and
/// Cons is tag id 0 because Nil comes alphabetically after Cons. Here, Nil will be /// Cons is tag id 0 because Nil comes alphabetically after Cons. Here, Nil will be
/// represented as NULL at runtime, so nullable_id is 1 - which is to say, `true`, because /// represented as NULL at runtime, so nullable_id is 1 - which is to say, `true`, because
/// `(1 as bool)` is `true`. /// `(1 as bool)` is `true`.
@ -2145,7 +2145,7 @@ pub fn union_sorted_tags<'a>(
Ok(()) Ok(())
// Admit type variables in the extension for now. This may come from things that never got // Admit type variables in the extension for now. This may come from things that never got
// monomorphized, like in // monomorphized, like in
// x : [ A ]* // x : [A]*
// x = A // x = A
// x // x
// In such cases it's fine to drop the variable. We may be proven wrong in the future... // In such cases it's fine to drop the variable. We may be proven wrong in the future...

View file

@ -392,7 +392,7 @@ pub struct HasClause<'a> {
#[derive(Debug, Copy, Clone, PartialEq)] #[derive(Debug, Copy, Clone, PartialEq)]
pub enum Derived<'a> { pub enum Derived<'a> {
/// `has [ Eq, Hash ]` /// `has [Eq, Hash]`
Has(Collection<'a, AbilityName<'a>>), Has(Collection<'a, AbilityName<'a>>),
// We preserve this for the formatter; canonicalization ignores it. // We preserve this for the formatter; canonicalization ignores it.
@ -429,7 +429,7 @@ pub enum TypeAnnotation<'a> {
/// A bound type variable, e.g. `a` in `(a -> a)` /// A bound type variable, e.g. `a` in `(a -> a)`
BoundVariable(&'a str), BoundVariable(&'a str),
/// Inline type alias, e.g. `as List a` in `[ Cons a (List a), Nil ] as List a` /// Inline type alias, e.g. `as List a` in `[Cons a (List a), Nil] as List a`
As( As(
&'a Loc<TypeAnnotation<'a>>, &'a Loc<TypeAnnotation<'a>>,
&'a [CommentOrNewline<'a>], &'a [CommentOrNewline<'a>],
@ -445,8 +445,8 @@ pub enum TypeAnnotation<'a> {
/// A tag union, e.g. `[ /// A tag union, e.g. `[
TagUnion { TagUnion {
/// The row type variable in an open tag union, e.g. the `a` in `[ Foo, Bar ]a`. /// The row type variable in an open tag union, e.g. the `a` in `[Foo, Bar]a`.
/// This is None if it's a closed tag union like `[ Foo, Bar]`. /// This is None if it's a closed tag union like `[Foo, Bar]`.
ext: Option<&'a Loc<TypeAnnotation<'a>>>, ext: Option<&'a Loc<TypeAnnotation<'a>>>,
tags: Collection<'a, Loc<Tag<'a>>>, tags: Collection<'a, Loc<Tag<'a>>>,
}, },

View file

@ -600,7 +600,7 @@ fn append_body_definition<'a>(
}), }),
)) => { )) => {
// This is a case like // This is a case like
// UserId x : [ UserId Int ] // UserId x : [UserId Int]
// UserId x = UserId 42 // UserId x = UserId 42
// We optimistically parsed the first line as an alias; we now turn it // We optimistically parsed the first line as an alias; we now turn it
// into an annotation. // into an annotation.

View file

@ -48,7 +48,7 @@ fn tag_union_type<'a>(
) )
.parse(arena, state)?; .parse(arena, state)?;
// This could be an open tag union, e.g. `[ Foo, Bar ]a` // This could be an open tag union, e.g. `[Foo, Bar]a`
let (_, ext, state) = optional(allocated(specialize_ref( let (_, ext, state) = optional(allocated(specialize_ref(
ETypeTagUnion::Type, ETypeTagUnion::Type,
term(min_indent, stop_at_surface_has), term(min_indent, stop_at_surface_has),
@ -135,7 +135,7 @@ fn term<'a>(
loc!(parse_type_variable(stop_at_surface_has)), loc!(parse_type_variable(stop_at_surface_has)),
fail_type_start(), fail_type_start(),
), ),
// Inline alias notation, e.g. [ Nil, Cons a (List a) ] as List a // Inline alias notation, e.g. [Nil, Cons a (List a)] as List a
one_of![ one_of![
map!( map!(
and!( and!(
@ -478,7 +478,7 @@ fn has_clause_chain<'a>(
} }
} }
/// Parse a has-derived clause, e.g. `has [ Eq, Hash ]`. /// Parse a has-derived clause, e.g. `has [Eq, Hash]`.
pub fn has_derived<'a>(min_indent: u32) -> impl Parser<'a, Loc<Derived<'a>>, EType<'a>> { pub fn has_derived<'a>(min_indent: u32) -> impl Parser<'a, Loc<Derived<'a>>, EType<'a>> {
skip_first!( skip_first!(
// Parse "has"; we don't care about this keyword // Parse "has"; we don't care about this keyword

View file

@ -704,7 +704,7 @@ mod test_parse {
// assert_parses_to( // assert_parses_to(
// indoc!( // indoc!(
// r#" // r#"
// foo : [ True, Perhaps Thing ]* // foo : [True, Perhaps Thing]*
// foo = True // foo = True
// 42 // 42
@ -757,7 +757,7 @@ mod test_parse {
// assert_parses_to( // assert_parses_to(
// indoc!( // indoc!(
// r#" // r#"
// foo : [ True, Perhaps Thing ] // foo : [True, Perhaps Thing]
// foo = True // foo = True
// 42 // 42

View file

@ -233,8 +233,8 @@ pub enum RuntimeError {
/// ```roc /// ```roc
/// app "hello" /// app "hello"
/// packages { pf: "platform" } /// packages { pf: "platform" }
/// imports [ pf.Stdout] /// imports [pf.Stdout]
/// provides [ main ] to pf /// provides [main] to pf
/// ///
/// main : Task.Task {} [] // Task isn't imported! /// main : Task.Task {} [] // Task isn't imported!
/// main = Stdout.line "I'm a Roc application!" /// main = Stdout.line "I'm a Roc application!"

View file

@ -2751,12 +2751,12 @@ fn adjust_rank_content(
// Normally this is not a problem because of the loop below that maximizes the // Normally this is not a problem because of the loop below that maximizes the
// rank from nested types in the union. But suppose we have the simple tag // rank from nested types in the union. But suppose we have the simple tag
// union // union
// [ Z ]{} // [Z]{}
// there are no nested types in the tags, and the empty tag union is at rank 0, // there are no nested types in the tags, and the empty tag union is at rank 0,
// so we promote the tag union to rank 0. Now if we introduce the presence // so we promote the tag union to rank 0. Now if we introduce the presence
// constraint // constraint
// [ Z ]{} += [ S a ] // [Z]{} += [S a]
// we'll wind up with [ Z, S a ]{}, but it will be at rank 0, and "a" will get // we'll wind up with [Z, S a]{}, but it will be at rank 0, and "a" will get
// over-generalized. Really, the empty tag union should be introduced at // over-generalized. Really, the empty tag union should be introduced at
// whatever current group rank we're at, and so that's how we encode it here. // whatever current group rank we're at, and so that's how we encode it here.
if *ext_var == Variable::EMPTY_TAG_UNION && rank.is_none() { if *ext_var == Variable::EMPTY_TAG_UNION && rank.is_none() {
@ -2798,7 +2798,7 @@ fn adjust_rank_content(
// For example, see the `recursion_var_specialization_error` reporting test - // For example, see the `recursion_var_specialization_error` reporting test -
// there, we have // there, we have
// //
// Job a : [ Job (List (Job a)) a ] // Job a : [Job (List (Job a)) a]
// //
// job : Job Str // job : Job Str
// //

File diff suppressed because it is too large Load diff

View file

@ -22,7 +22,7 @@ Here's what the fields mean:
## Nonempty list ## Nonempty list
Now let's say we define a `List Str` with two elements in it, like so: `[ "foo", "bar" ]`. Now let's say we define a `List Str` with two elements in it, like so: `["foo", "bar"]`.
First we'd have the `struct` above, with both `length` and `capacity` set to 2. Then, we'd have some memory allocated on the heap, and `pointer` would store that memory's address. First we'd have the `struct` above, with both `length` and `capacity` set to 2. Then, we'd have some memory allocated on the heap, and `pointer` would store that memory's address.
@ -49,7 +49,7 @@ This is memory-inefficient, but it's the price we pay for having all the 16B str
Let's go back to the refcount - short for "reference count." Let's go back to the refcount - short for "reference count."
The refcount is a `usize` integer which counts how many times this `List` has been shared. For example, if we named this list `myList` and then wrote `[ myList, myList, myList ]` then we'd increment that refcount 3 times because `myList` is now being shared three more times. The refcount is a `usize` integer which counts how many times this `List` has been shared. For example, if we named this list `myList` and then wrote `[myList, myList, myList]` then we'd increment that refcount 3 times because `myList` is now being shared three more times.
If we were to later call `List.pop` on that list, and the result was an in-place mutation that removed one of the `myList` entries, we'd decrement the refcount. If we did that again and again until the refcount got all the way down to 0, meaning nothing is using it anymore, then we'd deallocate these 48B of heap memory because nobody is using them anymore. If we were to later call `List.pop` on that list, and the result was an in-place mutation that removed one of the `myList` entries, we'd decrement the refcount. If we did that again and again until the refcount got all the way down to 0, meaning nothing is using it anymore, then we'd deallocate these 48B of heap memory because nobody is using them anymore.
@ -94,7 +94,7 @@ When you have a way to anticipate that a list will want to grow incrementally to
Some lists may end up beginning with excess capacity due to memory alignment requirements. Since the refcount is `usize`, all lists need a minimum of that alignment. For example, on a 64-bit system, a `List Bool` has an alignment of 8B even though bools can fit in 1B. Some lists may end up beginning with excess capacity due to memory alignment requirements. Since the refcount is `usize`, all lists need a minimum of that alignment. For example, on a 64-bit system, a `List Bool` has an alignment of 8B even though bools can fit in 1B.
This means the list `[ True, True, False ]` would have a memory layout like this): This means the list `[True, True, False]` would have a memory layout like this):
``` ```
|--------------8B--------------|--1B--|--1B--|--1B--|-----5B-----| |--------------8B--------------|--1B--|--1B--|--1B--|-----5B-----|

View file

@ -19,7 +19,7 @@ fn hash_specialization() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
Hash has Hash has
hash : a -> U64 | a has Hash hash : a -> U64 | a has Hash
@ -42,7 +42,7 @@ fn hash_specialization_multiple_add() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
Hash has Hash has
hash : a -> U64 | a has Hash hash : a -> U64 | a has Hash
@ -69,7 +69,7 @@ fn alias_member_specialization() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
Hash has Hash has
hash : a -> U64 | a has Hash hash : a -> U64 | a has Hash
@ -94,7 +94,7 @@ fn ability_constrained_in_non_member_usage() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ result ] to "./platform" app "test" provides [result] to "./platform"
Hash has Hash has
hash : a -> U64 | a has Hash hash : a -> U64 | a has Hash
@ -119,7 +119,7 @@ fn ability_constrained_in_non_member_usage_inferred() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ result ] to "./platform" app "test" provides [result] to "./platform"
Hash has Hash has
hash : a -> U64 | a has Hash hash : a -> U64 | a has Hash
@ -143,7 +143,7 @@ fn ability_constrained_in_non_member_multiple_specializations() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ result ] to "./platform" app "test" provides [result] to "./platform"
Hash has Hash has
hash : a -> U64 | a has Hash hash : a -> U64 | a has Hash
@ -171,7 +171,7 @@ fn ability_constrained_in_non_member_multiple_specializations_inferred() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ result ] to "./platform" app "test" provides [result] to "./platform"
Hash has Hash has
hash : a -> U64 | a has Hash hash : a -> U64 | a has Hash
@ -198,7 +198,7 @@ fn ability_used_as_type_still_compiles() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ result ] to "./platform" app "test" provides [result] to "./platform"
Hash has Hash has
hash : a -> U64 | a has Hash hash : a -> U64 | a has Hash
@ -226,7 +226,7 @@ fn encode() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ myU8Bytes ] to "./platform" app "test" provides [myU8Bytes] to "./platform"
Encoder fmt := List U8, fmt -> List U8 | fmt has Format Encoder fmt := List U8, fmt -> List U8 | fmt has Format
@ -272,9 +272,9 @@ fn decode() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ myU8 ] to "./platform" app "test" provides [myU8] to "./platform"
DecodeError : [ TooShort, Leftover (List U8) ] DecodeError : [TooShort, Leftover (List U8)]
Decoder val fmt := List U8, fmt -> { result: Result val DecodeError, rest: List U8 } | fmt has DecoderFormatting Decoder val fmt := List U8, fmt -> { result: Result val DecodeError, rest: List U8 } | fmt has DecoderFormatting
@ -314,7 +314,7 @@ fn decode() {
{ result: Result.map result (\n -> @MyU8 n), rest } { result: Result.map result (\n -> @MyU8 n), rest }
myU8 = myU8 =
when fromBytes [ 15 ] (@Linear {}) is when fromBytes [15] (@Linear {}) is
Ok (@MyU8 n) -> n Ok (@MyU8 n) -> n
_ -> 27u8 _ -> 27u8
"# "#

View file

@ -276,7 +276,7 @@ fn eq_expr() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
Expr : [ Add Expr Expr, Mul Expr Expr, Val I64, Var I64 ] Expr : [Add Expr Expr, Mul Expr Expr, Val I64, Var I64]
x : Expr x : Expr
x = Val 0 x = Val 0
@ -298,7 +298,7 @@ fn eq_linked_list() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
LinkedList a : [ Nil, Cons a (LinkedList a) ] LinkedList a : [Nil, Cons a (LinkedList a)]
x : LinkedList I64 x : LinkedList I64
x = Nil x = Nil
@ -316,7 +316,7 @@ fn eq_linked_list() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
LinkedList a : [ Nil, Cons a (LinkedList a) ] LinkedList a : [Nil, Cons a (LinkedList a)]
x : LinkedList I64 x : LinkedList I64
x = Cons 1 Nil x = Cons 1 Nil
@ -334,7 +334,7 @@ fn eq_linked_list() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
LinkedList a : [ Nil, Cons a (LinkedList a) ] LinkedList a : [Nil, Cons a (LinkedList a)]
x : LinkedList I64 x : LinkedList I64
x = Cons 1 (Cons 2 Nil) x = Cons 1 (Cons 2 Nil)
@ -356,7 +356,7 @@ fn eq_linked_list_false() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
LinkedList a : [ Nil, Cons a (LinkedList a) ] LinkedList a : [Nil, Cons a (LinkedList a)]
x : LinkedList I64 x : LinkedList I64
x = Cons 1 Nil x = Cons 1 Nil
@ -378,9 +378,9 @@ fn eq_linked_list_long() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
LinkedList a : [ Nil, Cons a (LinkedList a) ] LinkedList a : [Nil, Cons a (LinkedList a)]
prependOnes = \n, tail -> prependOnes = \n, tail ->
if n == 0 then if n == 0 then
@ -411,7 +411,7 @@ fn eq_nullable_expr() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
Expr : [ Add Expr Expr, Mul Expr Expr, Val I64, Empty ] Expr : [Add Expr Expr, Mul Expr Expr, Val I64, Empty]
x : Expr x : Expr
x = Val 0 x = Val 0
@ -434,7 +434,7 @@ fn eq_rosetree() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
Rose a : [ Rose a (List (Rose a)) ] Rose a : [Rose a (List (Rose a))]
x : Rose I64 x : Rose I64
x = Rose 0 [] x = Rose 0 []
@ -452,7 +452,7 @@ fn eq_rosetree() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
Rose a : [ Rose a (List (Rose a)) ] Rose a : [Rose a (List (Rose a))]
x : Rose I64 x : Rose I64
x = Rose 0 [] x = Rose 0 []
@ -470,7 +470,7 @@ fn eq_rosetree() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
Rose a : [ Rose a (List (Rose a)) ] Rose a : [Rose a (List (Rose a))]
a1 : Rose I64 a1 : Rose I64
a1 = Rose 999 [] a1 = Rose 999 []
@ -506,7 +506,7 @@ fn eq_different_rosetrees() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
Rose a : [ Rose a (List (Rose a)) ] Rose a : [Rose a (List (Rose a))]
a1 : Rose I64 a1 : Rose I64
a1 = Rose 999 [] a1 = Rose 999 []
@ -549,7 +549,7 @@ fn rosetree_with_tag() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
Rose a : [ Rose (Result (List (Rose a)) I64) ] Rose a : [Rose (Result (List (Rose a)) I64)]
x : Rose I64 x : Rose I64
x = (Rose (Ok [])) x = (Rose (Ok []))
@ -613,7 +613,7 @@ fn compare_union_same_content() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
Foo : [ A I64, B I64 ] Foo : [A I64, B I64]
a : Foo a : Foo
a = A 42 a = A 42
@ -635,7 +635,7 @@ fn compare_recursive_union_same_content() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
Expr : [ Add Expr Expr, Mul Expr Expr, Val1 I64, Val2 I64 ] Expr : [Add Expr Expr, Mul Expr Expr, Val1 I64, Val2 I64]
v1 : Expr v1 : Expr
v1 = Val1 42 v1 = Val1 42
@ -657,7 +657,7 @@ fn compare_nullable_recursive_union_same_content() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
Expr : [ Add Expr Expr, Mul Expr Expr, Val1 I64, Val2 I64, Empty ] Expr : [Add Expr Expr, Mul Expr Expr, Val1 I64, Val2 I64, Empty]
v1 : Expr v1 : Expr
v1 = Val1 42 v1 = Val1 42

View file

@ -46,9 +46,9 @@ fn int_singleton_list_literal() {
#[test] #[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn int_list_literal() { fn int_list_literal() {
assert_evals_to!("[ 12, 9 ]", RocList::from_slice(&[12, 9]), RocList<i64>); assert_evals_to!("[12, 9]", RocList::from_slice(&[12, 9]), RocList<i64>);
assert_evals_to!( assert_evals_to!(
"[ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 ]", "[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]",
RocList::from_slice(&[1i64; 23]), RocList::from_slice(&[1i64; 23]),
RocList<i64> RocList<i64>
); );
@ -59,7 +59,7 @@ fn int_list_literal() {
fn bool_list_literal() { fn bool_list_literal() {
// NOTE: make sure to explicitly declare the elements to be of type bool, or // NOTE: make sure to explicitly declare the elements to be of type bool, or
// use both True and False; only using one of them causes the list to in practice be // use both True and False; only using one of them causes the list to in practice be
// of type `List [ True ]` or `List [ False ]`, those are tag unions with one constructor // of type `List [True]` or `List [False]`, those are tag unions with one constructor
// and not fields, and don't have a runtime representation. // and not fields, and don't have a runtime representation.
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
@ -67,7 +67,7 @@ fn bool_list_literal() {
false : Bool false : Bool
false = False false = False
[ false ] [false]
"# "#
), ),
RocList::from_slice(&[false; 1]), RocList::from_slice(&[false; 1]),
@ -75,7 +75,7 @@ fn bool_list_literal() {
); );
assert_evals_to!( assert_evals_to!(
"[ True, False, True ]", "[True, False, True]",
RocList::from_slice(&[true, false, true]), RocList::from_slice(&[true, false, true]),
RocList<bool> RocList<bool>
); );
@ -86,7 +86,7 @@ fn bool_list_literal() {
false : Bool false : Bool
false = False false = False
[false ] [false]
"# "#
), ),
RocList::from_slice(&[false; 1]), RocList::from_slice(&[false; 1]),
@ -382,7 +382,7 @@ fn list_drop_at_shared() {
indoc!( indoc!(
r#" r#"
list : List I64 list : List I64
list = [ if True then 4 else 4, 5, 6 ] list = [if True then 4 else 4, 5, 6]
{ newList: List.dropAt list 0, original: list } { newList: List.dropAt list 0, original: list }
"# "#
@ -514,7 +514,7 @@ fn list_drop_last_mutable() {
indoc!( indoc!(
r#" r#"
list : List I64 list : List I64
list = [ if True then 4 else 4, 5, 6 ] list = [if True then 4 else 4, 5, 6]
{ newList: List.dropLast list, original: list } { newList: List.dropLast list, original: list }
"# "#
@ -557,33 +557,29 @@ fn list_swap() {
RocList::<i64>::from_slice(&[]), RocList::<i64>::from_slice(&[]),
RocList<i64> RocList<i64>
); );
assert_evals_to!("List.swap [0] 1 2", RocList::from_slice(&[0]), RocList<i64>);
assert_evals_to!( assert_evals_to!(
"List.swap [ 0 ] 1 2", "List.swap [1, 2] 0 1",
RocList::from_slice(&[0]),
RocList<i64>
);
assert_evals_to!(
"List.swap [ 1, 2 ] 0 1",
RocList::from_slice(&[2, 1]), RocList::from_slice(&[2, 1]),
RocList<i64> RocList<i64>
); );
assert_evals_to!( assert_evals_to!(
"List.swap [ 1, 2 ] 1 0", "List.swap [1, 2] 1 0",
RocList::from_slice(&[2, 1]), RocList::from_slice(&[2, 1]),
RocList<i64> RocList<i64>
); );
assert_evals_to!( assert_evals_to!(
"List.swap [ 0, 1, 2, 3, 4, 5 ] 2 4", "List.swap [0, 1, 2, 3, 4, 5] 2 4",
RocList::from_slice(&[0, 1, 4, 3, 2, 5]), RocList::from_slice(&[0, 1, 4, 3, 2, 5]),
RocList<i64> RocList<i64>
); );
assert_evals_to!( assert_evals_to!(
"List.swap [ 0, 1, 2 ] 1 3", "List.swap [0, 1, 2] 1 3",
RocList::from_slice(&[0, 1, 2]), RocList::from_slice(&[0, 1, 2]),
RocList<i64> RocList<i64>
); );
assert_evals_to!( assert_evals_to!(
"List.swap [ 1, 2, 3 ] 1 1", "List.swap [1, 2, 3] 1 1",
RocList::from_slice(&[1, 2, 3]), RocList::from_slice(&[1, 2, 3]),
RocList<i64> RocList<i64>
); );
@ -617,7 +613,7 @@ fn list_append_to_empty_list_of_int() {
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm"))]
fn list_append_bools() { fn list_append_bools() {
assert_evals_to!( assert_evals_to!(
"List.append [ True, False ] True", "List.append [True, False] True",
RocList::from_slice(&[true, false, true]), RocList::from_slice(&[true, false, true]),
RocList<bool> RocList<bool>
); );
@ -627,7 +623,7 @@ fn list_append_bools() {
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm"))]
fn list_append_longer_list() { fn list_append_longer_list() {
assert_evals_to!( assert_evals_to!(
"List.append [ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 ] 23", "List.append [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22] 23",
RocList::from_slice(&[11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]), RocList::from_slice(&[11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]),
RocList<i64> RocList<i64>
); );
@ -676,7 +672,7 @@ fn list_prepend() {
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm"))]
fn list_prepend_bools() { fn list_prepend_bools() {
assert_evals_to!( assert_evals_to!(
"List.prepend [ True, False ] True", "List.prepend [True, False] True",
RocList::from_slice(&[true, true, false]), RocList::from_slice(&[true, true, false]),
RocList<bool> RocList<bool>
); );
@ -686,7 +682,7 @@ fn list_prepend_bools() {
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm"))]
fn list_prepend_big_list() { fn list_prepend_big_list() {
assert_evals_to!( assert_evals_to!(
"List.prepend [ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 100, 100, 100, 100 ] 9", "List.prepend [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 100, 100, 100, 100] 9",
RocList::from_slice(&[ RocList::from_slice(&[
9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 100, 100, 100, 100 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 100, 100, 100, 100
]), ]),
@ -726,13 +722,13 @@ fn list_walk_backwards_empty_all_inline() {
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm"))]
fn list_walk_backwards_with_str() { fn list_walk_backwards_with_str() {
assert_evals_to!( assert_evals_to!(
r#"List.walkBackwards [ "x", "y", "z" ] "<" Str.concat"#, r#"List.walkBackwards ["x", "y", "z"] "<" Str.concat"#,
RocStr::from("<zyx"), RocStr::from("<zyx"),
RocStr RocStr
); );
assert_evals_to!( assert_evals_to!(
r#"List.walkBackwards [ "Second", "Third", "Fourth" ] "First" Str.concat"#, r#"List.walkBackwards ["Second", "Third", "Fourth"] "First" Str.concat"#,
RocStr::from("FirstFourthThirdSecond"), RocStr::from("FirstFourthThirdSecond"),
RocStr RocStr
); );
@ -744,10 +740,10 @@ fn list_walk_backwards_with_record() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
Bit : [ Zero, One ] Bit : [Zero, One]
byte : List Bit byte : List Bit
byte = [ Zero, One, Zero, One, Zero, Zero, One, Zero ] byte = [Zero, One, Zero, One, Zero, Zero, One, Zero]
initialCounts = { zeroes: 0, ones: 0 } initialCounts = { zeroes: 0, ones: 0 }
@ -770,13 +766,13 @@ fn list_walk_backwards_with_record() {
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm"))]
fn list_walk_with_str() { fn list_walk_with_str() {
assert_evals_to!( assert_evals_to!(
r#"List.walk [ "x", "y", "z" ] "<" Str.concat"#, r#"List.walk ["x", "y", "z"] "<" Str.concat"#,
RocStr::from("<xyz"), RocStr::from("<xyz"),
RocStr RocStr
); );
assert_evals_to!( assert_evals_to!(
r#"List.walk [ "Second", "Third", "Fourth" ] "First" Str.concat"#, r#"List.walk ["Second", "Third", "Fourth"] "First" Str.concat"#,
RocStr::from("FirstSecondThirdFourth"), RocStr::from("FirstSecondThirdFourth"),
RocStr RocStr
); );
@ -785,14 +781,14 @@ fn list_walk_with_str() {
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm"))]
fn list_walk_subtraction() { fn list_walk_subtraction() {
assert_evals_to!(r#"List.walk [ 1, 2 ] 1 Num.sub"#, (1 - 1) - 2, i64); assert_evals_to!(r#"List.walk [1, 2] 1 Num.sub"#, (1 - 1) - 2, i64);
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm"))]
fn list_walk_until_sum() { fn list_walk_until_sum() {
assert_evals_to!( assert_evals_to!(
r#"List.walkUntil [ 1, 2 ] 0 \a,b -> Continue (a + b)"#, r#"List.walkUntil [1, 2] 0 \a,b -> Continue (a + b)"#,
3, 3,
i64 i64
); );
@ -803,7 +799,7 @@ fn list_walk_until_sum() {
fn list_walk_implements_position() { fn list_walk_implements_position() {
assert_evals_to!( assert_evals_to!(
r#" r#"
Option a : [ Some a, None ] Option a : [Some a, None]
find : List a, a -> Option Nat find : List a, a -> Option Nat
find = \list, needle -> find = \list, needle ->
@ -817,7 +813,7 @@ fn list_walk_implements_position() {
else else
Continue { n: n + 1, v } Continue { n: n + 1, v }
when find [ 1, 2, 3 ] 3 is when find [1, 2, 3] 3 is
None -> 0 None -> 0
Some v -> v Some v -> v
"#, "#,
@ -838,7 +834,7 @@ fn list_walk_until_even_prefix_sum() {
else else
Stop a Stop a
List.walkUntil [ 2, 4, 8, 9 ] 0 helper"#, List.walkUntil [2, 4, 8, 9] 0 helper"#,
2 + 4 + 8, 2 + 4 + 8,
i64 i64
); );
@ -979,7 +975,7 @@ fn list_map_on_non_empty_list() {
r#" r#"
nonEmpty : List I64 nonEmpty : List I64
nonEmpty = nonEmpty =
[ 1 ] [1]
List.map nonEmpty (\x -> x) List.map nonEmpty (\x -> x)
"# "#
@ -997,7 +993,7 @@ fn list_map_changes_input() {
r#" r#"
nonEmpty : List I64 nonEmpty : List I64
nonEmpty = nonEmpty =
[ 1 ] [1]
List.map nonEmpty (\x -> x + 1) List.map nonEmpty (\x -> x + 1)
"# "#
@ -1015,7 +1011,7 @@ fn list_map_on_big_list() {
r#" r#"
nonEmpty : List I64 nonEmpty : List I64
nonEmpty = nonEmpty =
[ 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5 ] [1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
List.map nonEmpty (\x -> x * 2) List.map nonEmpty (\x -> x * 2)
"# "#
@ -1035,7 +1031,7 @@ fn list_map_with_type_change() {
r#" r#"
nonEmpty : List I64 nonEmpty : List I64
nonEmpty = nonEmpty =
[ 1, 1, -4, 1, 2 ] [1, 1, -4, 1, 2]
List.map nonEmpty (\x -> x > 0) List.map nonEmpty (\x -> x > 0)
@ -1054,7 +1050,7 @@ fn list_map_using_defined_function() {
r#" r#"
nonEmpty : List I64 nonEmpty : List I64
nonEmpty = nonEmpty =
[ 2, 2, -4, 2, 3 ] [2, 2, -4, 2, 3]
greaterThanOne : I64 -> Bool greaterThanOne : I64 -> Bool
greaterThanOne = \i -> greaterThanOne = \i ->
@ -1093,7 +1089,7 @@ fn list_map_closure() {
single : List F64 single : List F64
single = single =
[ 0 ] [0]
List.map single (\x -> x + float) List.map single (\x -> x + float)
"# "#
@ -1190,7 +1186,7 @@ fn list_map2_different_lengths() {
indoc!( indoc!(
r#" r#"
List.map2 List.map2
["a", "b", "lllllllllllllooooooooongnggg" ] ["a", "b", "lllllllllllllooooooooongnggg"]
["b"] ["b"]
(\a, b -> Str.concat a b) (\a, b -> Str.concat a b)
"# "#
@ -1214,7 +1210,7 @@ fn list_join_empty_list() {
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm"))]
fn list_join_one_list() { fn list_join_one_list() {
assert_evals_to!( assert_evals_to!(
"List.join [ [1, 2, 3 ] ]", "List.join [[1, 2, 3]]",
RocList::from_slice(&[1, 2, 3]), RocList::from_slice(&[1, 2, 3]),
RocList<i64> RocList<i64>
); );
@ -1224,7 +1220,7 @@ fn list_join_one_list() {
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm"))]
fn list_join_two_non_empty_lists() { fn list_join_two_non_empty_lists() {
assert_evals_to!( assert_evals_to!(
"List.join [ [1, 2, 3 ] , [4 ,5, 6] ]", "List.join [[1, 2, 3] , [4 ,5, 6]]",
RocList::from_slice(&[1, 2, 3, 4, 5, 6]), RocList::from_slice(&[1, 2, 3, 4, 5, 6]),
RocList<i64> RocList<i64>
); );
@ -1234,7 +1230,7 @@ fn list_join_two_non_empty_lists() {
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm"))]
fn list_join_two_non_empty_lists_of_float() { fn list_join_two_non_empty_lists_of_float() {
assert_evals_to!( assert_evals_to!(
"List.join [ [ 1.2, 1.1 ], [ 2.1, 2.2 ] ]", "List.join [[1.2, 1.1], [2.1, 2.2]]",
RocList::from_slice(&[1.2, 1.1, 2.1, 2.2]), RocList::from_slice(&[1.2, 1.1, 2.1, 2.2]),
RocList<f64> RocList<f64>
); );
@ -1248,13 +1244,13 @@ fn list_join_to_big_list() {
r#" r#"
List.join List.join
[ [
[ 1.2, 1.1 ], [1.2, 1.1],
[ 2.1, 2.2 ], [2.1, 2.2],
[ 3.0, 4.0, 5.0, 6.1, 9.0 ], [3.0, 4.0, 5.0, 6.1, 9.0],
[ 3.0, 4.0, 5.0, 6.1, 9.0 ], [3.0, 4.0, 5.0, 6.1, 9.0],
[ 3.0, 4.0, 5.0, 6.1, 9.0 ], [3.0, 4.0, 5.0, 6.1, 9.0],
[ 3.0, 4.0, 5.0, 6.1, 9.0 ], [3.0, 4.0, 5.0, 6.1, 9.0],
[ 3.0, 4.0, 5.0, 6.1, 9.0 ] [3.0, 4.0, 5.0, 6.1, 9.0]
] ]
"# "#
), ),
@ -1276,7 +1272,7 @@ fn list_join_defined_empty_list() {
empty = empty =
[] []
List.join [ [ 0.2, 11.11 ], empty ] List.join [[0.2, 11.11], empty]
"# "#
), ),
RocList::from_slice(&[0.2, 11.11]), RocList::from_slice(&[0.2, 11.11]),
@ -1288,7 +1284,7 @@ fn list_join_defined_empty_list() {
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm"))]
fn list_join_all_empty_lists() { fn list_join_all_empty_lists() {
assert_evals_to!( assert_evals_to!(
"List.join [ [], [], [] ]", "List.join [[], [], []]",
RocList::<f64>::from_slice(&[]), RocList::<f64>::from_slice(&[]),
RocList<f64> RocList<f64>
); );
@ -1298,7 +1294,7 @@ fn list_join_all_empty_lists() {
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm"))]
fn list_join_one_empty_list() { fn list_join_one_empty_list() {
assert_evals_to!( assert_evals_to!(
"List.join [ [ 1.2, 1.1 ], [] ]", "List.join [[1.2, 1.1], []]",
RocList::from_slice(&[1.2, 1.1]), RocList::from_slice(&[1.2, 1.1]),
RocList<f64> RocList<f64>
); );
@ -1356,7 +1352,7 @@ fn list_repeat() {
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm"))]
fn list_reverse() { fn list_reverse() {
assert_evals_to!( assert_evals_to!(
"List.reverse [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ]", "List.reverse [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]",
RocList::from_slice(&[12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]), RocList::from_slice(&[12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]),
RocList<i64> RocList<i64>
); );
@ -1454,12 +1450,12 @@ fn list_concat_two_empty_lists_of_int() {
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm"))]
fn list_concat_second_list_is_empty() { fn list_concat_second_list_is_empty() {
assert_evals_to!( assert_evals_to!(
"List.concat [ 12, 13 ] []", "List.concat [12, 13] []",
RocList::from_slice(&[12, 13]), RocList::from_slice(&[12, 13]),
RocList<i64> RocList<i64>
); );
assert_evals_to!( assert_evals_to!(
"List.concat [ 34, 43 ] [ 64, 55, 66 ]", "List.concat [34, 43] [64, 55, 66]",
RocList::from_slice(&[34, 43, 64, 55, 66]), RocList::from_slice(&[34, 43, 64, 55, 66]),
RocList<i64> RocList<i64>
); );
@ -1469,7 +1465,7 @@ fn list_concat_second_list_is_empty() {
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm"))]
fn list_concat_first_list_is_empty() { fn list_concat_first_list_is_empty() {
assert_evals_to!( assert_evals_to!(
"List.concat [] [ 23, 24 ]", "List.concat [] [23, 24]",
RocList::from_slice(&[23, 24]), RocList::from_slice(&[23, 24]),
RocList<i64> RocList<i64>
); );
@ -1479,7 +1475,7 @@ fn list_concat_first_list_is_empty() {
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm"))]
fn list_concat_two_non_empty_lists() { fn list_concat_two_non_empty_lists() {
assert_evals_to!( assert_evals_to!(
"List.concat [1, 2 ] [ 3, 4 ]", "List.concat [1, 2] [3, 4]",
RocList::from_slice(&[1, 2, 3, 4]), RocList::from_slice(&[1, 2, 3, 4]),
RocList<i64> RocList<i64>
); );
@ -1489,7 +1485,7 @@ fn list_concat_two_non_empty_lists() {
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm"))]
fn list_concat_two_bigger_non_empty_lists() { fn list_concat_two_bigger_non_empty_lists() {
assert_evals_to!( assert_evals_to!(
"List.concat [ 1.1, 2.2 ] [ 3.3, 4.4, 5.5 ]", "List.concat [1.1, 2.2] [3.3, 4.4, 5.5]",
RocList::from_slice(&[1.1, 2.2, 3.3, 4.4, 5.5]), RocList::from_slice(&[1.1, 2.2, 3.3, 4.4, 5.5]),
RocList<f64> RocList<f64>
); );
@ -1579,7 +1575,7 @@ fn empty_list_len() {
#[test] #[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn basic_int_list_len() { fn basic_int_list_len() {
assert_evals_to!("List.len [ 12, 9, 6, 3 ]", 4, usize); assert_evals_to!("List.len [12, 9, 6, 3]", 4, usize);
} }
#[test] #[test]
@ -1588,7 +1584,7 @@ fn loaded_int_list_len() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
nums = [ 2, 4, 6 ] nums = [2, 4, 6]
List.len nums List.len nums
"# "#
@ -1606,7 +1602,7 @@ fn fn_int_list_len() {
r#" r#"
getLen = \list -> List.len list getLen = \list -> List.len list
nums = [ 2, 4, 6, 8 ] nums = [2, 4, 6, 8]
getLen nums getLen nums
"# "#
@ -1619,7 +1615,7 @@ fn fn_int_list_len() {
#[test] #[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn int_list_is_empty() { fn int_list_is_empty() {
assert_evals_to!("List.isEmpty [ 12, 9, 6, 3 ]", false, bool); assert_evals_to!("List.isEmpty [12, 9, 6, 3]", false, bool);
} }
#[test] #[test]
@ -1634,7 +1630,7 @@ fn first_int_list() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
when List.first [ 12, 9, 6, 3 ] is when List.first [12, 9, 6, 3] is
Ok val -> val Ok val -> val
Err _ -> -1 Err _ -> -1
"# "#
@ -1683,7 +1679,7 @@ fn last_int_list() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
when List.last [ 12, 9, 6, 3 ] is when List.last [12, 9, 6, 3] is
Ok val -> val Ok val -> val
Err _ -> -1 Err _ -> -1
"# "#
@ -1765,7 +1761,7 @@ fn get_int_list_ok() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
when List.get [ 12, 9, 6 ] 1 is when List.get [12, 9, 6] 1 is
Ok val -> val Ok val -> val
Err _ -> -1 Err _ -> -1
"# "#
@ -1781,7 +1777,7 @@ fn get_int_list_oob() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
when List.get [ 12, 9, 6 ] 1000 is when List.get [12, 9, 6] 1000 is
Ok val -> val Ok val -> val
Err _ -> -1 Err _ -> -1
"# "#
@ -1797,7 +1793,7 @@ fn replace_unique_int_list() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
record = List.replace [ 12, 9, 7, 1, 5 ] 2 33 record = List.replace [12, 9, 7, 1, 5] 2 33
record.list record.list
"# "#
), ),
@ -1812,7 +1808,7 @@ fn replace_unique_int_list_out_of_bounds() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
record = List.replace [ 12, 9, 7, 1, 5 ] 5 33 record = List.replace [12, 9, 7, 1, 5] 5 33
record.value record.value
"# "#
), ),
@ -1827,7 +1823,7 @@ fn replace_unique_int_list_get_old_value() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
record = List.replace [ 12, 9, 7, 1, 5 ] 2 33 record = List.replace [12, 9, 7, 1, 5] 2 33
record.value record.value
"# "#
), ),
@ -1843,7 +1839,7 @@ fn replace_unique_get_large_value() {
indoc!( indoc!(
r#" r#"
list : List { a : U64, b: U64, c: U64, d: U64 } list : List { a : U64, b: U64, c: U64, d: U64 }
list = [ { a: 1, b: 2, c: 3, d: 4 }, { a: 5, b: 6, c: 7, d: 8 }, { a: 9, b: 10, c: 11, d: 12 } ] list = [{ a: 1, b: 2, c: 3, d: 4 }, { a: 5, b: 6, c: 7, d: 8 }, { a: 9, b: 10, c: 11, d: 12 }]
record = List.replace list 1 { a: 13, b: 14, c: 15, d: 16 } record = List.replace list 1 { a: 13, b: 14, c: 15, d: 16 }
record.value record.value
"# "#
@ -1874,7 +1870,7 @@ fn replace_shared_int_list() {
{ x, y } { x, y }
wrapper [ 2.1, 4.3 ] wrapper [2.1, 4.3]
"# "#
), ),
(7.7, 4.3), (7.7, 4.3),
@ -1888,7 +1884,7 @@ fn get_set_unique_int_list() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
when List.get (List.set [ 12, 9, 7, 3 ] 1 42) 1 is when List.get (List.set [12, 9, 7, 3] 1 42) 1 is
Ok val -> val Ok val -> val
Err _ -> -1 Err _ -> -1
"# "#
@ -1902,7 +1898,7 @@ fn get_set_unique_int_list() {
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm"))]
fn set_unique_int_list() { fn set_unique_int_list() {
assert_evals_to!( assert_evals_to!(
"List.set [ 12, 9, 7, 1, 5 ] 2 33", "List.set [12, 9, 7, 1, 5] 2 33",
RocList::from_slice(&[12, 9, 33, 1, 5]), RocList::from_slice(&[12, 9, 33, 1, 5]),
RocList<i64> RocList<i64>
); );
@ -1912,7 +1908,7 @@ fn set_unique_int_list() {
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm"))]
fn set_unique_list_oob() { fn set_unique_list_oob() {
assert_evals_to!( assert_evals_to!(
"List.set [ 3, 17, 4.1 ] 1337 9.25", "List.set [3, 17, 4.1] 1337 9.25",
RocList::from_slice(&[3.0, 17.0, 4.1]), RocList::from_slice(&[3.0, 17.0, 4.1]),
RocList<f64> RocList<f64>
); );
@ -1938,7 +1934,7 @@ fn set_shared_int_list() {
{ x, y } { x, y }
wrapper [ 2.1, 4.3 ] wrapper [2.1, 4.3]
"# "#
), ),
(7.7, 4.3), (7.7, 4.3),
@ -1952,7 +1948,7 @@ fn set_shared_list_oob() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
shared = [ 2, 4 ] shared = [2, 4]
# This List.set is out of bounds, and should have no effect # This List.set is out of bounds, and should have no effect
x = x =
@ -1979,7 +1975,7 @@ fn get_unique_int_list() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
unique = [ 2, 4 ] unique = [2, 4]
when List.get unique 1 is when List.get unique 1 is
Ok num -> num Ok num -> num
@ -1998,9 +1994,9 @@ fn gen_wrap_len() {
indoc!( indoc!(
r#" r#"
wrapLen = \list -> wrapLen = \list ->
[ List.len list ] [List.len list]
wrapLen [ 1, 7, 9 ] wrapLen [1, 7, 9]
"# "#
), ),
RocList::from_slice(&[3]), RocList::from_slice(&[3]),
@ -2015,9 +2011,9 @@ fn gen_wrap_first() {
indoc!( indoc!(
r#" r#"
wrapFirst = \list -> wrapFirst = \list ->
[ List.first list ] [List.first list]
wrapFirst [ 1, 2 ] wrapFirst [1, 2]
"# "#
), ),
RocList::from_slice(&[1]), RocList::from_slice(&[1]),
@ -2040,7 +2036,7 @@ fn gen_duplicate() {
_ -> _ ->
[] []
dupe [ 1, 2 ] dupe [1, 2]
"# "#
), ),
RocList::from_slice(&[1, 1]), RocList::from_slice(&[1, 1]),
@ -2054,7 +2050,7 @@ fn gen_swap() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "quicksort" provides [ main ] to "./platform" app "quicksort" provides [main] to "./platform"
swap : Nat, Nat, List a -> List a swap : Nat, Nat, List a -> List a
@ -2069,7 +2065,7 @@ fn gen_swap() {
[] []
main = main =
swap 0 1 [ 1, 2 ] swap 0 1 [1, 2]
"# "#
), ),
RocList::from_slice(&[2, 1]), RocList::from_slice(&[2, 1]),
@ -2113,7 +2109,7 @@ fn gen_quicksort() {
_ -> _ ->
[] []
partition : Nat, Nat, List (Num a) -> [ Pair Nat (List (Num a)) ] partition : Nat, Nat, List (Num a) -> [Pair Nat (List (Num a))]
partition = \low, high, initialList -> partition = \low, high, initialList ->
when List.get initialList high is when List.get initialList high is
Ok pivot -> Ok pivot ->
@ -2125,7 +2121,7 @@ fn gen_quicksort() {
Pair low initialList Pair low initialList
partitionHelp : Nat, Nat, List (Num a), Nat, (Num a) -> [ Pair Nat (List (Num a)) ] partitionHelp : Nat, Nat, List (Num a), Nat, (Num a) -> [Pair Nat (List (Num a))]
partitionHelp = \i, j, list, high, pivot -> partitionHelp = \i, j, list, high, pivot ->
if j < high then if j < high then
when List.get list j is when List.get list j is
@ -2140,7 +2136,7 @@ fn gen_quicksort() {
else else
Pair i list Pair i list
quicksort [ 7, 4, 21, 19 ] quicksort [7, 4, 21, 19]
"# "#
), ),
RocList::from_slice(&[4, 7, 19, 21]), RocList::from_slice(&[4, 7, 19, 21]),
@ -2184,7 +2180,7 @@ fn quicksort() {
_ -> _ ->
[] []
partition : Nat, Nat, List (Num a) -> [ Pair Nat (List (Num a)) ] partition : Nat, Nat, List (Num a) -> [Pair Nat (List (Num a))]
partition = \low, high, initialList -> partition = \low, high, initialList ->
when List.get initialList high is when List.get initialList high is
Ok pivot -> Ok pivot ->
@ -2196,7 +2192,7 @@ fn quicksort() {
Pair low initialList Pair low initialList
partitionHelp : Nat, Nat, List (Num a), Nat, Num a -> [ Pair Nat (List (Num a)) ] partitionHelp : Nat, Nat, List (Num a), Nat, Num a -> [Pair Nat (List (Num a))]
partitionHelp = \i, j, list, high, pivot -> partitionHelp = \i, j, list, high, pivot ->
# if j < high then # if j < high then
if False then if False then
@ -2214,7 +2210,7 @@ fn quicksort() {
quicksort [ 7, 4, 21, 19 ] quicksort [7, 4, 21, 19]
"# "#
), ),
RocList::from_slice(&[19, 7, 4, 21]), RocList::from_slice(&[19, 7, 4, 21]),
@ -2258,7 +2254,7 @@ fn quicksort_singleton() {
_ -> _ ->
[] []
partition : Nat, Nat, List (Num a) -> [ Pair Nat (List (Num a)) ] partition : Nat, Nat, List (Num a) -> [Pair Nat (List (Num a))]
partition = \low, high, initialList -> partition = \low, high, initialList ->
when List.get initialList high is when List.get initialList high is
Ok pivot -> Ok pivot ->
@ -2270,7 +2266,7 @@ fn quicksort_singleton() {
Pair low initialList Pair low initialList
partitionHelp : Nat, Nat, List (Num a), Nat, Num a -> [ Pair Nat (List (Num a)) ] partitionHelp : Nat, Nat, List (Num a), Nat, Num a -> [Pair Nat (List (Num a))]
partitionHelp = \i, j, list, high, pivot -> partitionHelp = \i, j, list, high, pivot ->
if j < high then if j < high then
when List.get list j is when List.get list j is
@ -2377,7 +2373,7 @@ fn list_wrap_in_tag() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
id : List I64 -> [ Pair (List I64) I64 ] id : List I64 -> [Pair (List I64) I64]
id = \y -> Pair y 4 id = \y -> Pair y 4
when id [1,2,3] is when id [1,2,3] is
@ -2426,7 +2422,7 @@ fn list_manual_range() {
else else
accum accum
range 0 5 [ 42 ] range 0 5 [42]
"# "#
), ),
RocList::from_slice(&[42, 0, 1, 2, 3, 4]), RocList::from_slice(&[42, 0, 1, 2, 3, 4]),
@ -2492,16 +2488,16 @@ fn list_max() {
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm"))]
fn list_sum() { fn list_sum() {
assert_evals_to!("List.sum []", 0, i64); assert_evals_to!("List.sum []", 0, i64);
assert_evals_to!("List.sum [ 1, 2, 3 ]", 6, i64); assert_evals_to!("List.sum [1, 2, 3]", 6, i64);
assert_evals_to!("List.sum [ 1.1, 2.2, 3.3 ]", 6.6, f64); assert_evals_to!("List.sum [1.1, 2.2, 3.3]", 6.6, f64);
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm"))]
fn list_product() { fn list_product() {
assert_evals_to!("List.product []", 1, i64); assert_evals_to!("List.product []", 1, i64);
assert_evals_to!("List.product [ 1, 2, 3 ]", 6, i64); assert_evals_to!("List.product [1, 2, 3]", 6, i64);
assert_evals_to!("List.product [ 1.1, 2.2, 3.3 ]", 1.1 * 2.2 * 3.3, f64); assert_evals_to!("List.product [1.1, 2.2, 3.3]", 1.1 * 2.2 * 3.3, f64);
} }
#[test] #[test]
@ -2592,7 +2588,7 @@ fn cleanup_because_exception() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
x = [ 1,2 ] x = [1,2]
five : I64 five : I64
five = 5 five = 5
@ -2630,12 +2626,12 @@ fn list_sort_with() {
RocList<i64> RocList<i64>
); );
assert_evals_to!( assert_evals_to!(
"List.sortWith [ 4,3,2,1 ] Num.compare", "List.sortWith [4,3,2,1] Num.compare",
RocList::from_slice(&[1, 2, 3, 4]), RocList::from_slice(&[1, 2, 3, 4]),
RocList<i64> RocList<i64>
); );
assert_evals_to!( assert_evals_to!(
"List.sortWith [ 1,2,3,4] (\\a,b -> Num.compare b a)", "List.sortWith [1,2,3,4] (\\a,b -> Num.compare b a)",
RocList::from_slice(&[4, 3, 2, 1]), RocList::from_slice(&[4, 3, 2, 1]),
RocList<i64> RocList<i64>
); );
@ -2650,7 +2646,7 @@ fn list_sort_asc() {
RocList<i64> RocList<i64>
); );
assert_evals_to!( assert_evals_to!(
"List.sortAsc [ 4,3,2,1 ]", "List.sortAsc [4,3,2,1]",
RocList::from_slice(&[1, 2, 3, 4]), RocList::from_slice(&[1, 2, 3, 4]),
RocList<i64> RocList<i64>
); );
@ -2665,7 +2661,7 @@ fn list_sort_desc() {
RocList<i64> RocList<i64>
); );
assert_evals_to!( assert_evals_to!(
"List.sortDesc [ 1,2,3,4 ]", "List.sortDesc [1,2,3,4]",
RocList::from_slice(&[4, 3, 2, 1]), RocList::from_slice(&[4, 3, 2, 1]),
RocList<i64> RocList<i64>
); );
@ -2675,8 +2671,8 @@ fn list_sort_desc() {
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm"))]
fn list_any() { fn list_any() {
assert_evals_to!("List.any [] (\\e -> e > 3)", false, bool); assert_evals_to!("List.any [] (\\e -> e > 3)", false, bool);
assert_evals_to!("List.any [ 1, 2, 3 ] (\\e -> e > 3)", false, bool); assert_evals_to!("List.any [1, 2, 3] (\\e -> e > 3)", false, bool);
assert_evals_to!("List.any [ 1, 2, 4 ] (\\e -> e > 3)", true, bool); assert_evals_to!("List.any [1, 2, 4] (\\e -> e > 3)", true, bool);
} }
#[test] #[test]
@ -2699,9 +2695,9 @@ fn list_any_empty_with_unknown_element_type() {
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm"))]
fn list_all() { fn list_all() {
assert_evals_to!("List.all [] (\\e -> e > 3)", true, bool); assert_evals_to!("List.all [] (\\e -> e > 3)", true, bool);
assert_evals_to!("List.all [ 1, 2, 3 ] (\\e -> e > 3)", false, bool); assert_evals_to!("List.all [1, 2, 3] (\\e -> e > 3)", false, bool);
assert_evals_to!("List.all [ 1, 2, 4 ] (\\e -> e > 3)", false, bool); assert_evals_to!("List.all [1, 2, 4] (\\e -> e > 3)", false, bool);
assert_evals_to!("List.all [ 1, 2, 3 ] (\\e -> e >= 1)", true, bool); assert_evals_to!("List.all [1, 2, 3] (\\e -> e >= 1)", true, bool);
} }
#[test] #[test]
@ -2727,9 +2723,9 @@ fn lists_with_incompatible_type_param_in_if() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
list1 = [ {} ] list1 = [{}]
list2 = [ "" ] list2 = [""]
x = if True then list1 else list2 x = if True then list1 else list2
@ -2748,7 +2744,7 @@ fn map_with_index_multi_record() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
List.mapWithIndex [ { x: {}, y: {} } ] \_, _ -> {} List.mapWithIndex [{ x: {}, y: {} }] \_, _ -> {}
"# "#
), ),
RocList::from_slice(&[((), ())]), RocList::from_slice(&[((), ())]),
@ -2773,7 +2769,7 @@ fn empty_list_of_function_type() {
if False then if False then
myList myList
else else
[ myClosure ] [myClosure]
when List.get choose 0 is when List.get choose 0 is
Ok f -> f "foo" Ok f -> f "foo"

View file

@ -52,7 +52,7 @@ fn i64_signed_int_alias() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
main = main =
i : I64 i : I64
@ -2381,7 +2381,7 @@ fn min_f32() {
} }
macro_rules! num_conversion_tests { macro_rules! num_conversion_tests {
($($fn:expr, $typ:ty, ($($test_name:ident, $input:expr, $output:expr $(, [ $($support_gen:literal),* ])? )*))*) => {$($( ($($fn:expr, $typ:ty, ($($test_name:ident, $input:expr, $output:expr $(, [$($support_gen:literal),*])? )*))*) => {$($(
#[test] #[test]
#[cfg(any(feature = "gen-llvm", $($(feature = $support_gen)*)?))] #[cfg(any(feature = "gen-llvm", $($(feature = $support_gen)*)?))]
fn $test_name() { fn $test_name() {
@ -2816,7 +2816,7 @@ fn when_on_i32() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
x : I32 x : I32
x = 0 x = 0
@ -2839,7 +2839,7 @@ fn when_on_i16() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
x : I16 x : I16
x = 0 x = 0

View file

@ -161,7 +161,7 @@ fn when_one_element_tag() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
x : [ Pair (Int a) (Int a) ] x : [Pair (Int a) (Int a)]
x = Pair 0x2 0x3 x = Pair 0x2 0x3
when x is when x is
@ -537,7 +537,7 @@ fn peano1() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
Peano : [ S Peano, Z ] Peano : [S Peano, Z]
three : Peano three : Peano
three = S (S (S Z)) three = S (S (S Z))
@ -558,7 +558,7 @@ fn peano2() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
Peano : [ S Peano, Z ] Peano : [S Peano, Z]
three : Peano three : Peano
three = S (S (S Z)) three = S (S (S Z))
@ -580,7 +580,7 @@ fn top_level_constant() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
float = 1.2315 float = 1.2315
@ -600,7 +600,7 @@ fn top_level_destructure() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
{a, b} = { a: 1, b: 2 } {a, b} = { a: 1, b: 2 }
@ -620,9 +620,9 @@ fn linked_list_len_0() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
LinkedList a : [ Nil, Cons a (LinkedList a) ] LinkedList a : [Nil, Cons a (LinkedList a)]
len : LinkedList a -> Int * len : LinkedList a -> Int *
len = \list -> len = \list ->
@ -648,9 +648,9 @@ fn linked_list_len_twice_0() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
LinkedList a : [ Nil, Cons a (LinkedList a) ] LinkedList a : [Nil, Cons a (LinkedList a)]
nil : LinkedList I64 nil : LinkedList I64
nil = Nil nil = Nil
@ -676,9 +676,9 @@ fn linked_list_len_1() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
LinkedList a : [ Nil, Cons a (LinkedList a) ] LinkedList a : [Nil, Cons a (LinkedList a)]
one : LinkedList (Int *) one : LinkedList (Int *)
one = Cons 1 Nil one = Cons 1 Nil
@ -704,9 +704,9 @@ fn linked_list_len_twice_1() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
LinkedList a : [ Nil, Cons a (LinkedList a) ] LinkedList a : [Nil, Cons a (LinkedList a)]
one : LinkedList (Int *) one : LinkedList (Int *)
one = Cons 1 Nil one = Cons 1 Nil
@ -732,9 +732,9 @@ fn linked_list_len_3() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
LinkedList a : [ Nil, Cons a (LinkedList a) ] LinkedList a : [Nil, Cons a (LinkedList a)]
three : LinkedList (Int *) three : LinkedList (Int *)
three = Cons 3 (Cons 2 (Cons 1 Nil)) three = Cons 3 (Cons 2 (Cons 1 Nil))
@ -761,9 +761,9 @@ fn linked_list_sum_num_a() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
LinkedList a : [ Nil, Cons a (LinkedList a) ] LinkedList a : [Nil, Cons a (LinkedList a)]
three : LinkedList (Int *) three : LinkedList (Int *)
three = Cons 3 (Cons 2 (Cons 1 Nil)) three = Cons 3 (Cons 2 (Cons 1 Nil))
@ -790,9 +790,9 @@ fn linked_list_sum_int() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
LinkedList a : [ Nil, Cons a (LinkedList a) ] LinkedList a : [Nil, Cons a (LinkedList a)]
zero : LinkedList (Int *) zero : LinkedList (Int *)
zero = Nil zero = Nil
@ -818,9 +818,9 @@ fn linked_list_map() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
LinkedList a : [ Nil, Cons a (LinkedList a) ] LinkedList a : [Nil, Cons a (LinkedList a)]
three : LinkedList (Int *) three : LinkedList (Int *)
three = Cons 3 (Cons 2 (Cons 1 Nil)) three = Cons 3 (Cons 2 (Cons 1 Nil))
@ -852,7 +852,7 @@ fn when_nested_maybe() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
Maybe a : [ Nothing, Just a ] Maybe a : [Nothing, Just a]
x : Maybe (Maybe (Int a)) x : Maybe (Maybe (Int a))
x = Just (Just 41) x = Just (Just 41)
@ -869,7 +869,7 @@ fn when_nested_maybe() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
Maybe a : [ Nothing, Just a ] Maybe a : [Nothing, Just a]
x : Maybe (Maybe (Int *)) x : Maybe (Maybe (Int *))
x = Just Nothing x = Just Nothing
@ -887,7 +887,7 @@ fn when_nested_maybe() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
Maybe a : [ Nothing, Just a ] Maybe a : [Nothing, Just a]
x : Maybe (Maybe (Int *)) x : Maybe (Maybe (Int *))
x = Nothing x = Nothing
@ -909,7 +909,7 @@ fn when_peano() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
Peano : [ S Peano, Z ] Peano : [S Peano, Z]
three : Peano three : Peano
three = S (S (S Z)) three = S (S (S Z))
@ -927,7 +927,7 @@ fn when_peano() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
Peano : [ S Peano, Z ] Peano : [S Peano, Z]
three : Peano three : Peano
three = S Z three = S Z
@ -945,7 +945,7 @@ fn when_peano() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
Peano : [ S Peano, Z ] Peano : [S Peano, Z]
three : Peano three : Peano
three = Z three = Z
@ -1028,7 +1028,7 @@ fn simple_closure() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
x = 42 x = 42
@ -1050,7 +1050,7 @@ fn nested_closure() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
foo = \{} -> foo = \{} ->
x = 41 x = 41
@ -1074,14 +1074,14 @@ fn closure_in_list() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
foo = \{} -> foo = \{} ->
x = 41 x = 41
f = \{} -> x f = \{} -> x
[ f ] [f]
main = main =
items = foo {} items = foo {}
@ -1102,7 +1102,7 @@ fn specialize_closure() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
foo = \{} -> foo = \{} ->
x = 41 x = 41
@ -1111,7 +1111,7 @@ fn specialize_closure() {
f = \{} -> x f = \{} -> x
g = \{} -> x + Num.intCast (List.len y) g = \{} -> x + Num.intCast (List.len y)
[ f, g ] [f, g]
apply = \f -> f {} apply = \f -> f {}
@ -1132,7 +1132,7 @@ fn io_poc_effect() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
Effect a := {} -> a Effect a := {} -> a
@ -1163,7 +1163,7 @@ fn io_poc_desugared() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
# succeed : a -> ({} -> a) # succeed : a -> ({} -> a)
succeed = \x -> \_ -> x succeed = \x -> \_ -> x
@ -1191,7 +1191,7 @@ fn return_wrapped_function_pointer() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
Effect a := {} -> a Effect a := {} -> a
@ -1214,7 +1214,7 @@ fn return_wrapped_function_pointer_b() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
foo : { x: (I64 -> Str) } foo : { x: (I64 -> Str) }
@ -1236,7 +1236,7 @@ fn return_wrapped_closure() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
Effect a := {} -> a Effect a := {} -> a
@ -1262,9 +1262,9 @@ fn linked_list_is_singleton() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
ConsList a : [ Cons a (ConsList a), Nil ] ConsList a : [Cons a (ConsList a), Nil]
empty : ConsList a empty : ConsList a
empty = Nil empty = Nil
@ -1297,9 +1297,9 @@ fn linked_list_is_empty_1() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
ConsList a : [ Cons a (ConsList a), Nil ] ConsList a : [Cons a (ConsList a), Nil]
empty : ConsList a empty : ConsList a
empty = Nil empty = Nil
@ -1332,9 +1332,9 @@ fn linked_list_is_empty_2() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
ConsList a : [ Cons a (ConsList a), Nil ] ConsList a : [Cons a (ConsList a), Nil]
isEmpty : ConsList a -> Bool isEmpty : ConsList a -> Bool
isEmpty = \list -> isEmpty = \list ->
@ -1365,9 +1365,9 @@ fn linked_list_singleton() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
ConsList a : [ Cons a (ConsList a), Nil ] ConsList a : [Cons a (ConsList a), Nil]
main : ConsList I64 main : ConsList I64
main = Cons 0x1 Nil main = Cons 0x1 Nil
@ -1385,7 +1385,7 @@ fn recursive_function_with_rigid() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
State a : { count : I64, x : a } State a : { count : I64, x : a }
@ -1412,11 +1412,11 @@ fn rbtree_insert() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
NodeColor : [ Red, Black ] NodeColor : [Red, Black]
RedBlackTree k v : [ Node NodeColor k v (RedBlackTree k v) (RedBlackTree k v), Empty ] RedBlackTree k v : [Node NodeColor k v (RedBlackTree k v) (RedBlackTree k v), Empty]
Key k : Num k Key k : Num k
@ -1500,9 +1500,9 @@ fn rbtree_balance_3() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
RedBlackTree k : [ Node k (RedBlackTree k) (RedBlackTree k), Empty ] RedBlackTree k : [Node k (RedBlackTree k) (RedBlackTree k), Empty]
balance : k, RedBlackTree k -> RedBlackTree k balance : k, RedBlackTree k -> RedBlackTree k
balance = \key, left -> balance = \key, left ->
@ -1527,11 +1527,11 @@ fn rbtree_layout_issue() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
NodeColor : [ Red, Black ] NodeColor : [Red, Black]
RedBlackTree k v : [ Node NodeColor k v (RedBlackTree k v) (RedBlackTree k v), Empty ] RedBlackTree k v : [Node NodeColor k v (RedBlackTree k v) (RedBlackTree k v), Empty]
# balance : NodeColor, k, v, RedBlackTree k v -> RedBlackTree k v # balance : NodeColor, k, v, RedBlackTree k v -> RedBlackTree k v
balance = \color, key, value, right -> balance = \color, key, value, right ->
@ -1574,11 +1574,11 @@ fn rbtree_balance_mono_problem() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
NodeColor : [ Red, Black ] NodeColor : [Red, Black]
RedBlackTree k v : [ Node NodeColor k v (RedBlackTree k v) (RedBlackTree k v), Empty ] RedBlackTree k v : [Node NodeColor k v (RedBlackTree k v) (RedBlackTree k v), Empty]
# balance : NodeColor, k, v, RedBlackTree k v, RedBlackTree k v -> RedBlackTree k v # balance : NodeColor, k, v, RedBlackTree k v, RedBlackTree k v -> RedBlackTree k v
balance = \color, key, value, left, right -> balance = \color, key, value, left, right ->
@ -1621,11 +1621,11 @@ fn rbtree_balance_full() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
NodeColor : [ Red, Black ] NodeColor : [Red, Black]
RedBlackTree k v : [ Node NodeColor k v (RedBlackTree k v) (RedBlackTree k v), Empty ] RedBlackTree k v : [Node NodeColor k v (RedBlackTree k v) (RedBlackTree k v), Empty]
balance : NodeColor, k, v, RedBlackTree k v, RedBlackTree k v -> RedBlackTree k v balance : NodeColor, k, v, RedBlackTree k v, RedBlackTree k v -> RedBlackTree k v
balance = \color, key, value, left, right -> balance = \color, key, value, left, right ->
@ -1674,9 +1674,9 @@ fn nested_pattern_match_two_ways() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
ConsList a : [ Cons a (ConsList a), Nil ] ConsList a : [Cons a (ConsList a), Nil]
balance : ConsList (Int *) -> Int * balance : ConsList (Int *) -> Int *
balance = \right -> balance = \right ->
@ -1700,9 +1700,9 @@ fn nested_pattern_match_two_ways() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
ConsList a : [ Cons a (ConsList a), Nil ] ConsList a : [Cons a (ConsList a), Nil]
balance : ConsList (Int *) -> Int * balance : ConsList (Int *) -> Int *
balance = \right -> balance = \right ->
@ -1729,9 +1729,9 @@ fn linked_list_guarded_double_pattern_match() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
ConsList a : [ Cons a (ConsList a), Nil ] ConsList a : [Cons a (ConsList a), Nil]
balance : ConsList (Int *) -> Int * balance : ConsList (Int *) -> Int *
balance = \right -> balance = \right ->
@ -1759,9 +1759,9 @@ fn linked_list_double_pattern_match() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
ConsList a : [ Cons a (ConsList a), Nil ] ConsList a : [Cons a (ConsList a), Nil]
foo : ConsList (Int a) -> Int a foo : ConsList (Int a) -> Int a
foo = \list -> foo = \list ->
@ -1785,9 +1785,9 @@ fn binary_tree_double_pattern_match() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
BTree : [ Node BTree BTree, Leaf I64 ] BTree : [Node BTree BTree, Leaf I64]
foo : BTree -> I64 foo : BTree -> I64
foo = \btree -> foo = \btree ->
@ -1813,7 +1813,7 @@ fn unified_empty_closure_bool() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
foo = \{} -> foo = \{} ->
when A is when A is
@ -1838,7 +1838,7 @@ fn unified_empty_closure_byte() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
foo = \{} -> foo = \{} ->
when A is when A is
@ -1862,7 +1862,7 @@ fn task_always_twice() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
Effect a := {} -> a Effect a := {} -> a
@ -1907,7 +1907,7 @@ fn wildcard_rigid() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
Effect a := {} -> a Effect a := {} -> a
@ -1937,7 +1937,7 @@ fn alias_of_alias_with_type_arguments() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
Effect a := a Effect a := a
@ -1967,7 +1967,7 @@ fn todo_bad_error_message() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
Effect a := {} -> a Effect a := {} -> a
@ -2028,7 +2028,7 @@ fn hof_conditional() {
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm"))]
#[should_panic( #[should_panic(
expected = "Roc failed with message: \"Shadowing { original_region: @57-58, shadow: @90-91 Ident" expected = "Roc failed with message: \"Shadowing { original_region: @55-56, shadow: @88-89 Ident"
)] )]
fn pattern_shadowing() { fn pattern_shadowing() {
assert_evals_to!( assert_evals_to!(
@ -2070,14 +2070,14 @@ fn fingertree_basic() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
Some a : [ One a, Two a a, Three a a a ] Some a : [One a, Two a a, Three a a a]
Tuple a : [ Pair a a, Triple a a a ] Tuple a : [Pair a a, Triple a a a]
# a FingerTree implementation # a FingerTree implementation
Seq a : [ Nil, Unit a, More (Some a) (Seq (Tuple a)) (Some a) ] Seq a : [Nil, Unit a, More (Some a) (Seq (Tuple a)) (Some a)]
# cons : a, Seq a -> Seq a # cons : a, Seq a -> Seq a
cons = \x, s -> cons = \x, s ->
@ -2113,7 +2113,7 @@ fn case_or_pattern() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
x : [ Red, Green, Blue ] x : [Red, Green, Blue]
x = Red x = Red
when x is when x is
@ -2133,9 +2133,9 @@ fn rosetree_basic() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
Tree a : [ Tree a (List (Tree a)) ] Tree a : [Tree a (List (Tree a))]
singleton : a -> Tree a singleton : a -> Tree a
singleton = \x -> Tree x [] singleton = \x -> Tree x []
@ -2161,9 +2161,9 @@ fn case_jump() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
ConsList a : [ Cons a (ConsList a), Nil ] ConsList a : [Cons a (ConsList a), Nil]
x : ConsList I64 x : ConsList I64
x = Nil x = Nil
@ -2187,9 +2187,9 @@ fn nullable_eval_cfold() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
Expr : [ Var, Val I64, Add Expr Expr, Mul Expr Expr ] Expr : [Var, Val I64, Add Expr Expr, Mul Expr Expr]
mkExpr : I64, I64 -> Expr mkExpr : I64, I64 -> Expr
mkExpr = \n , v -> mkExpr = \n , v ->
@ -2224,9 +2224,9 @@ fn nested_switch() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
Expr : [ ZAdd Expr Expr, Val I64, Var I64 ] Expr : [ZAdd Expr Expr, Val I64, Var I64]
eval : Expr -> I64 eval : Expr -> I64
eval = \e -> eval = \e ->
@ -2267,9 +2267,9 @@ fn count_deriv_x() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
Expr : [ Ln Expr, Pow Expr Expr, Var Str ] Expr : [Ln Expr, Pow Expr Expr, Var Str]
count : Expr -> I64 count : Expr -> I64
count = \expr -> count = \expr ->
@ -2294,9 +2294,9 @@ fn deriv_pow() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
Expr : [ Ln Expr, Pow Expr Expr, Var Str, Val I64 ] Expr : [Ln Expr, Pow Expr Expr, Var Str, Val I64]
count : Expr -> I64 count : Expr -> I64
count = \expr -> count = \expr ->
@ -2331,12 +2331,12 @@ fn multiple_increment() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
Color : [ Red, Black ] Color : [Red, Black]
Tree a b : [ Leaf, Node Color (Tree a b) a b (Tree a b) ] Tree a b : [Leaf, Node Color (Tree a b) a b (Tree a b)]
Map : Tree I64 Bool Map : Tree I64 Bool
@ -2364,9 +2364,9 @@ fn switch_fuse_rc_non_exhaustive() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
Foo : [ A I64 Foo, B I64 Foo, C I64 Foo, Empty ] Foo : [A I64 Foo, B I64 Foo, C I64 Foo, Empty]
sum : Foo, I64 -> I64 sum : Foo, I64 -> I64
sum = \foo, accum -> sum = \foo, accum ->
@ -2394,9 +2394,9 @@ fn switch_fuse_rc_exhaustive() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
Foo : [ A I64 Foo, B I64 Foo, C I64 Foo, Empty ] Foo : [A I64 Foo, B I64 Foo, C I64 Foo, Empty]
sum : Foo, I64 -> I64 sum : Foo, I64 -> I64
sum = \foo, accum -> sum = \foo, accum ->
@ -2423,7 +2423,7 @@ fn build_then_apply_closure() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
main : Str main : Str
main = main =
@ -2443,7 +2443,7 @@ fn expanded_result() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
a : Result I64 Str a : Result I64 Str
a = Ok 4 a = Ok 4
@ -2475,7 +2475,7 @@ fn backpassing_result() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
a : Result I64 Str a : Result I64 Str
a = Ok 1 a = Ok 1
@ -2504,7 +2504,7 @@ fn backpassing_result() {
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm"))]
#[should_panic(expected = "Shadowing { original_region: @57-58, shadow: @74-75 Ident")] #[should_panic(expected = "Shadowing { original_region: @55-56, shadow: @72-73 Ident")]
fn function_malformed_pattern() { fn function_malformed_pattern() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
@ -2562,7 +2562,7 @@ fn increment_or_double_closure() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
apply : (a -> a), a -> a apply : (a -> a), a -> a
@ -2600,7 +2600,7 @@ fn module_thunk_is_function() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
main = helper "foo" "bar" main = helper "foo" "bar"
helper = Str.concat helper = Str.concat
@ -2618,7 +2618,7 @@ fn hit_unresolved_type_variable() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
main : Str main : Str
main = main =
@ -2641,7 +2641,7 @@ fn pattern_match_empty_record() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
main : I64 main : I64
main = main =
@ -2661,9 +2661,9 @@ fn pattern_match_unit_tag() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
unit : [ Unit ] unit : [Unit]
unit = Unit unit = Unit
main : I64 main : I64
@ -2687,13 +2687,13 @@ fn mirror_llvm_alignment_padding() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
main : Str main : Str
main = main =
p1 = {name : "test1", test: 1 == 1 } p1 = {name : "test1", test: 1 == 1 }
List.map [p1, p1 ] (\{ test } -> if test then "pass" else "fail") List.map [p1, p1] (\{ test } -> if test then "pass" else "fail")
|> Str.joinWith "\n" |> Str.joinWith "\n"
"# "#
@ -2709,7 +2709,7 @@ fn lambda_set_bool() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
p1 = (\u -> u == 97) p1 = (\u -> u == 97)
p2 = (\u -> u == 98) p2 = (\u -> u == 98)
@ -2734,7 +2734,7 @@ fn lambda_set_byte() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
p1 = (\u -> u == 97) p1 = (\u -> u == 97)
p2 = (\u -> u == 98) p2 = (\u -> u == 98)
@ -2760,12 +2760,12 @@ fn lambda_set_struct_byte() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
main : I64 main : I64
main = main =
r : [ Red, Green, Blue ] r : [Red, Green, Blue]
r = Red r = Red
p1 = (\u -> r == u) p1 = (\u -> r == u)
@ -2788,15 +2788,15 @@ fn lambda_set_enum_byte_byte() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
main : I64 main : I64
main = main =
r : [ Red, Green, Blue ] r : [Red, Green, Blue]
r = Red r = Red
g : [ Red, Green, Blue ] g : [Red, Green, Blue]
g = Green g = Green
p1 = (\u -> r == u) p1 = (\u -> r == u)
@ -2820,14 +2820,14 @@ fn list_walk_until() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
satisfyA : {} -> List {} satisfyA : {} -> List {}
satisfyA = \_ -> [] satisfyA = \_ -> []
oneOfResult = oneOfResult =
List.walkUntil [ satisfyA ] [] \_, _ -> Stop [] List.walkUntil [satisfyA] [] \_, _ -> Stop []
main = main =
when oneOfResult is when oneOfResult is
@ -2846,7 +2846,7 @@ fn int_literal_not_specialized_with_annotation() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
main = main =
satisfy : (U8 -> Str) -> Str satisfy : (U8 -> Str) -> Str
@ -2874,7 +2874,7 @@ fn int_literal_not_specialized_no_annotation() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
main = main =
satisfy : (U8 -> Str) -> Str satisfy : (U8 -> Str) -> Str
@ -2901,7 +2901,7 @@ fn unresolved_tvar_when_capture_is_unused() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
main : I64 main : I64
main = main =
@ -2928,7 +2928,7 @@ fn value_not_exposed_hits_panic() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
main : I64 main : I64
main = main =
@ -2947,7 +2947,7 @@ fn mix_function_and_closure() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
# foo does not capture any variables # foo does not capture any variables
# but through unification will get a lambda set that does store information # but through unification will get a lambda set that does store information
@ -2973,7 +2973,7 @@ fn mix_function_and_closure_level_of_indirection() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
foo = \x -> x foo = \x -> x
@ -3001,7 +3001,7 @@ fn do_pass_bool_byte_closure_layout() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
## PARSER ## PARSER
@ -3016,7 +3016,7 @@ fn do_pass_bool_byte_closure_layout() {
any = \inp -> any = \inp ->
when List.first inp is when List.first inp is
Ok u -> [Pair u (List.drop inp 1)] Ok u -> [Pair u (List.drop inp 1)]
_ -> [ ] _ -> []
@ -3027,7 +3027,7 @@ fn do_pass_bool_byte_closure_layout() {
\input -> \input ->
walker = \accum, (Pair u rest) -> walker = \accum, (Pair u rest) ->
if predicate u then if predicate u then
Stop [ Pair u rest ] Stop [Pair u rest]
else else
Stop accum Stop accum
@ -3074,7 +3074,7 @@ fn nested_rigid_list() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
foo : List a -> List a foo : List a -> List a
foo = \list -> foo = \list ->
@ -3099,7 +3099,7 @@ fn nested_rigid_alias() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
Identity a := a Identity a := a
@ -3126,11 +3126,11 @@ fn nested_rigid_tag_union() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
foo : [ Identity a ] -> [ Identity a ] foo : [Identity a] -> [Identity a]
foo = \list -> foo = \list ->
p2 : [ Identity a ] p2 : [Identity a]
p2 = list p2 = list
p2 p2
@ -3153,15 +3153,15 @@ fn call_that_needs_closure_parameter() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
Step state a : [ Loop state, Done a ] Step state a : [Loop state, Done a]
manyAux : List a -> [ Pair (Step (List a) (List a))] manyAux : List a -> [Pair (Step (List a) (List a))]
manyAux = \list -> manyAux = \list ->
p2 = \_ -> Pair (Done list) p2 = \_ -> Pair (Done list)
p2 "foo" p2 "foo"
manyAuxTest = (manyAux [ ]) == Pair (Loop [97]) manyAuxTest = (manyAux []) == Pair (Loop [97])
runTest = \t -> if t then "PASS" else "FAIL" runTest = \t -> if t then "PASS" else "FAIL"
@ -3179,7 +3179,7 @@ fn alias_defined_out_of_order() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
main : Foo main : Foo
main = "foo" main = "foo"
@ -3200,7 +3200,7 @@ fn recursively_build_effect() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
greeting = greeting =
hi = "Hello" hi = "Hello"
@ -3247,7 +3247,7 @@ fn polymophic_expression_captured_inside_closure() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
asU8 : U8 -> U8 asU8 : U8 -> U8
asU8 = \_ -> 30 asU8 = \_ -> 30
@ -3334,7 +3334,7 @@ fn box_and_unbox_tag_union() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
v : [ A U8, B U8 ] # usually stack allocated v : [A U8, B U8] # usually stack allocated
v = B 27u8 v = B 27u8
Box.unbox (Box.box v) Box.unbox (Box.box v)
@ -3351,7 +3351,7 @@ fn closure_called_in_its_defining_scope() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
main : Str main : Str
main = main =
@ -3376,7 +3376,7 @@ fn issue_2894() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
main : U32 main : U32
main = main =
@ -3461,10 +3461,10 @@ fn list_map2_conslist() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
ConsList a : [ Nil, Cons a (ConsList a) ] ConsList a : [Nil, Cons a (ConsList a)]
x : List (ConsList Str) x : List (ConsList Str)
x = List.map2 [ ] [ Nil ] Cons x = List.map2 [] [Nil] Cons
when List.first x is when List.first x is
_ -> "" _ -> ""

View file

@ -423,7 +423,7 @@ fn optional_field_when_use_default() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
f = \r -> f = \r ->
when r is when r is
@ -475,7 +475,7 @@ fn optional_field_when_no_use_default() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
f = \r -> f = \r ->
{ x ? 10, y } = r { x ? 10, y } = r
@ -514,7 +514,7 @@ fn optional_field_let_use_default() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
f = \r -> f = \r ->
{ x ? 10, y } = r { x ? 10, y } = r
@ -535,7 +535,7 @@ fn optional_field_let_no_use_default() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
f = \r -> f = \r ->
{ x ? 10, y } = r { x ? 10, y } = r
@ -591,7 +591,7 @@ fn optional_field_function_no_use_default() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
f = \{ x ? 10, y } -> x + y f = \{ x ? 10, y } -> x + y
@ -1014,7 +1014,7 @@ fn different_proc_types_specialized_to_same_layout() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
app "test" provides [ nums ] to "./platform" app "test" provides [nums] to "./platform"
# Top-level values compile to procedure calls with no args # Top-level values compile to procedure calls with no args
# alpha has the generic type { a: Num *, b: Num * } # alpha has the generic type { a: Num *, b: Num * }
@ -1047,7 +1047,7 @@ fn different_proc_types_specialized_to_same_layout() {
fn call_with_bad_record_runtime_error() { fn call_with_bad_record_runtime_error() {
expect_runtime_error_panic!(indoc!( expect_runtime_error_panic!(indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
main = main =
get : {a: Bool} -> Bool get : {a: Bool} -> Bool
@ -1063,7 +1063,7 @@ fn call_with_bad_record_runtime_error() {
fn call_with_bad_record_runtime_error() { fn call_with_bad_record_runtime_error() {
expect_runtime_error_panic!(indoc!( expect_runtime_error_panic!(indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
main = main =
get : {a: Bool} -> Bool get : {a: Bool} -> Bool

View file

@ -166,7 +166,7 @@ fn union_nonrecursive_inc() {
assert_refcounts!( assert_refcounts!(
indoc!( indoc!(
r#" r#"
TwoOrNone a: [ Two a a, None ] TwoOrNone a: [Two a a, None]
s = Str.concat "A long enough string " "to be heap-allocated" s = Str.concat "A long enough string " "to be heap-allocated"
@ -190,7 +190,7 @@ fn union_nonrecursive_dec() {
assert_refcounts!( assert_refcounts!(
indoc!( indoc!(
r#" r#"
TwoOrNone a: [ Two a a, None ] TwoOrNone a: [Two a a, None]
s = Str.concat "A long enough string " "to be heap-allocated" s = Str.concat "A long enough string " "to be heap-allocated"
@ -213,7 +213,7 @@ fn union_recursive_inc() {
assert_refcounts!( assert_refcounts!(
indoc!( indoc!(
r#" r#"
Expr : [ Sym Str, Add Expr Expr ] Expr : [Sym Str, Add Expr Expr]
s = Str.concat "heap_allocated" "_symbol_name" s = Str.concat "heap_allocated" "_symbol_name"
@ -241,7 +241,7 @@ fn union_recursive_dec() {
assert_refcounts!( assert_refcounts!(
indoc!( indoc!(
r#" r#"
Expr : [ Sym Str, Add Expr Expr ] Expr : [Sym Str, Add Expr Expr]
s = Str.concat "heap_allocated" "_symbol_name" s = Str.concat "heap_allocated" "_symbol_name"
@ -273,7 +273,7 @@ fn refcount_different_rosetrees_inc() {
assert_refcounts!( assert_refcounts!(
indoc!( indoc!(
r#" r#"
Rose a : [ Rose a (List (Rose a)) ] Rose a : [Rose a (List (Rose a))]
s = Str.concat "A long enough string " "to be heap-allocated" s = Str.concat "A long enough string " "to be heap-allocated"
@ -313,7 +313,7 @@ fn refcount_different_rosetrees_dec() {
assert_refcounts!( assert_refcounts!(
indoc!( indoc!(
r#" r#"
Rose a : [ Rose a (List (Rose a)) ] Rose a : [Rose a (List (Rose a))]
s = Str.concat "A long enough string " "to be heap-allocated" s = Str.concat "A long enough string " "to be heap-allocated"
@ -352,7 +352,7 @@ fn union_linked_list_inc() {
assert_refcounts!( assert_refcounts!(
indoc!( indoc!(
r#" r#"
LinkedList a : [ Nil, Cons a (LinkedList a) ] LinkedList a : [Nil, Cons a (LinkedList a)]
s = Str.concat "A long enough string " "to be heap-allocated" s = Str.concat "A long enough string " "to be heap-allocated"
@ -378,7 +378,7 @@ fn union_linked_list_dec() {
assert_refcounts!( assert_refcounts!(
indoc!( indoc!(
r#" r#"
LinkedList a : [ Nil, Cons a (LinkedList a) ] LinkedList a : [Nil, Cons a (LinkedList a)]
s = Str.concat "A long enough string " "to be heap-allocated" s = Str.concat "A long enough string " "to be heap-allocated"
@ -406,9 +406,9 @@ fn union_linked_list_long_dec() {
assert_refcounts!( assert_refcounts!(
indoc!( indoc!(
r#" r#"
app "test" provides [ main ] to "./platform" app "test" provides [main] to "./platform"
LinkedList a : [ Nil, Cons a (LinkedList a) ] LinkedList a : [Nil, Cons a (LinkedList a)]
prependOnes = \n, tail -> prependOnes = \n, tail ->
if n == 0 then if n == 0 then

View file

@ -268,7 +268,7 @@ fn from_list_result() {
x : Result Str {} x : Result Str {}
x = Ok "foo" x = Ok "foo"
[ x ] [x]
|> Set.fromList |> Set.fromList
|> Set.toList |> Set.toList
|> List.len |> List.len

View file

@ -582,7 +582,7 @@ fn str_from_utf8_pass_single_ascii() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
when Str.fromUtf8 [ 97 ] is when Str.fromUtf8 [97] is
Ok val -> val Ok val -> val
Err _ -> "" Err _ -> ""
"# "#
@ -598,7 +598,7 @@ fn str_from_utf8_pass_many_ascii() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
when Str.fromUtf8 [ 97, 98, 99, 0x7E ] is when Str.fromUtf8 [97, 98, 99, 0x7E] is
Ok val -> val Ok val -> val
Err _ -> "" Err _ -> ""
"# "#
@ -614,7 +614,7 @@ fn str_from_utf8_pass_single_unicode() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
when Str.fromUtf8 [ 0xE2, 0x88, 0x86 ] is when Str.fromUtf8 [0xE2, 0x88, 0x86] is
Ok val -> val Ok val -> val
Err _ -> "" Err _ -> ""
"# "#
@ -630,7 +630,7 @@ fn str_from_utf8_pass_many_unicode() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
when Str.fromUtf8 [ 0xE2, 0x88, 0x86, 0xC5, 0x93, 0xC2, 0xAC ] is when Str.fromUtf8 [0xE2, 0x88, 0x86, 0xC5, 0x93, 0xC2, 0xAC] is
Ok val -> val Ok val -> val
Err _ -> "" Err _ -> ""
"# "#
@ -646,7 +646,7 @@ fn str_from_utf8_pass_single_grapheme() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
when Str.fromUtf8 [ 0xF0, 0x9F, 0x92, 0x96 ] is when Str.fromUtf8 [0xF0, 0x9F, 0x92, 0x96] is
Ok val -> val Ok val -> val
Err _ -> "" Err _ -> ""
"# "#
@ -662,7 +662,7 @@ fn str_from_utf8_pass_many_grapheme() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
when Str.fromUtf8 [ 0xF0, 0x9F, 0x92, 0x96, 0xF0, 0x9F, 0xA4, 0xA0, 0xF0, 0x9F, 0x9A, 0x80 ] is when Str.fromUtf8 [0xF0, 0x9F, 0x92, 0x96, 0xF0, 0x9F, 0xA4, 0xA0, 0xF0, 0x9F, 0x9A, 0x80] is
Ok val -> val Ok val -> val
Err _ -> "" Err _ -> ""
"# "#
@ -678,7 +678,7 @@ fn str_from_utf8_pass_all() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
when Str.fromUtf8 [ 0xF0, 0x9F, 0x92, 0x96, 98, 0xE2, 0x88, 0x86 ] is when Str.fromUtf8 [0xF0, 0x9F, 0x92, 0x96, 98, 0xE2, 0x88, 0x86] is
Ok val -> val Ok val -> val
Err _ -> "" Err _ -> ""
"# "#
@ -694,7 +694,7 @@ fn str_from_utf8_fail_invalid_start_byte() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
when Str.fromUtf8 [ 97, 98, 0x80, 99 ] is when Str.fromUtf8 [97, 98, 0x80, 99] is
Err (BadUtf8 InvalidStartByte byteIndex) -> Err (BadUtf8 InvalidStartByte byteIndex) ->
if byteIndex == 2 then if byteIndex == 2 then
"a" "a"
@ -714,7 +714,7 @@ fn str_from_utf8_fail_unexpected_end_of_sequence() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
when Str.fromUtf8 [ 97, 98, 99, 0xC2 ] is when Str.fromUtf8 [97, 98, 99, 0xC2] is
Err (BadUtf8 UnexpectedEndOfSequence byteIndex) -> Err (BadUtf8 UnexpectedEndOfSequence byteIndex) ->
if byteIndex == 3 then if byteIndex == 3 then
"a" "a"
@ -734,7 +734,7 @@ fn str_from_utf8_fail_expected_continuation() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
when Str.fromUtf8 [ 97, 98, 99, 0xC2, 0x00 ] is when Str.fromUtf8 [97, 98, 99, 0xC2, 0x00] is
Err (BadUtf8 ExpectedContinuation byteIndex) -> Err (BadUtf8 ExpectedContinuation byteIndex) ->
if byteIndex == 3 then if byteIndex == 3 then
"a" "a"
@ -754,7 +754,7 @@ fn str_from_utf8_fail_overlong_encoding() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
when Str.fromUtf8 [ 97, 0xF0, 0x80, 0x80, 0x80 ] is when Str.fromUtf8 [97, 0xF0, 0x80, 0x80, 0x80] is
Err (BadUtf8 OverlongEncoding byteIndex) -> Err (BadUtf8 OverlongEncoding byteIndex) ->
if byteIndex == 1 then if byteIndex == 1 then
"a" "a"
@ -774,7 +774,7 @@ fn str_from_utf8_fail_codepoint_too_large() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
when Str.fromUtf8 [ 97, 0xF4, 0x90, 0x80, 0x80 ] is when Str.fromUtf8 [97, 0xF4, 0x90, 0x80, 0x80] is
Err (BadUtf8 CodepointTooLarge byteIndex) -> Err (BadUtf8 CodepointTooLarge byteIndex) ->
if byteIndex == 1 then if byteIndex == 1 then
"a" "a"
@ -794,7 +794,7 @@ fn str_from_utf8_fail_surrogate_half() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
when Str.fromUtf8 [ 97, 98, 0xED, 0xA0, 0x80 ] is when Str.fromUtf8 [97, 98, 0xED, 0xA0, 0x80] is
Err (BadUtf8 EncodesSurrogateHalf byteIndex) -> Err (BadUtf8 EncodesSurrogateHalf byteIndex) ->
if byteIndex == 2 then if byteIndex == 2 then
"a" "a"
@ -839,7 +839,7 @@ fn nested_recursive_literal() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
Expr : [ Add Expr Expr, Val I64, Var I64 ] Expr : [Add Expr Expr, Val I64, Var I64]
expr : Expr expr : Expr
expr = Add (Add (Val 3) (Val 1)) (Add (Val 1) (Var 1)) expr = Add (Add (Val 3) (Val 1)) (Add (Val 1) (Var 1))

Some files were not shown because too many files have changed in this diff Show more