mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 05:49:08 +00:00
Update ListLen and ListGetUnsafe to not use Nat
This commit is contained in:
parent
2e72021a74
commit
97f21e65fe
4 changed files with 60 additions and 49 deletions
|
@ -74,7 +74,7 @@ interface List
|
||||||
imports [
|
imports [
|
||||||
Bool.{ Bool, Eq },
|
Bool.{ Bool, Eq },
|
||||||
Result.{ Result },
|
Result.{ Result },
|
||||||
Num.{ Nat, Num, Int },
|
Num.{ U64, Num, Int },
|
||||||
]
|
]
|
||||||
|
|
||||||
## ## Types
|
## ## Types
|
||||||
|
@ -91,14 +91,14 @@ interface List
|
||||||
## is normally enabled, not having enough memory could result in the list appearing
|
## is normally enabled, not having enough memory could result in the list appearing
|
||||||
## to be created just fine, but then crashing later.)
|
## to be created just fine, but then crashing later.)
|
||||||
##
|
##
|
||||||
## > The theoretical maximum length for a list created in Roc is half of
|
## > The theoretical maximum length for a list created in Roc is `Num.maxI32` on 32-bit systems
|
||||||
## > `Num.maxNat`. Attempting to create a list bigger than that
|
## > and `Num.maxI64` on 64-bit systems. Attempting to create a list bigger than that
|
||||||
## > in Roc code will always fail, although in practice it is likely to fail
|
## > in Roc code will always fail, although in practice it is likely to fail
|
||||||
## > at much smaller lengths due to insufficient memory being available.
|
## > at much smaller lengths due to insufficient memory being available.
|
||||||
##
|
##
|
||||||
## ## Performance Details
|
## ## Performance Details
|
||||||
##
|
##
|
||||||
## Under the hood, a list is a record containing a `len : Nat` field, a `capacity : Nat`
|
## Under the hood, a list is a record containing a `len : U64` field, a `capacity : U64`
|
||||||
## field, and a pointer to a reference count and a flat array of bytes.
|
## field, and a pointer to a reference count and a flat array of bytes.
|
||||||
##
|
##
|
||||||
## ## Shared Lists
|
## ## Shared Lists
|
||||||
|
@ -227,7 +227,7 @@ isEmpty = \list ->
|
||||||
|
|
||||||
# unsafe primitive that does not perform a bounds check
|
# unsafe primitive that does not perform a bounds check
|
||||||
# but will cause a reference count increment on the value it got out of the list
|
# but will cause a reference count increment on the value it got out of the list
|
||||||
getUnsafe : List a, Nat -> a
|
getUnsafe : List a, U64 -> a
|
||||||
|
|
||||||
## Returns an element from a list at the given index.
|
## Returns an element from a list at the given index.
|
||||||
##
|
##
|
||||||
|
@ -236,7 +236,7 @@ getUnsafe : List a, Nat -> a
|
||||||
## expect List.get [100, 200, 300] 1 == Ok 200
|
## expect List.get [100, 200, 300] 1 == Ok 200
|
||||||
## expect List.get [100, 200, 300] 5 == Err OutOfBounds
|
## expect List.get [100, 200, 300] 5 == Err OutOfBounds
|
||||||
## ```
|
## ```
|
||||||
get : List a, Nat -> Result a [OutOfBounds]
|
get : List a, U64 -> Result a [OutOfBounds]
|
||||||
get = \list, index ->
|
get = \list, index ->
|
||||||
if index < List.len list then
|
if index < List.len list then
|
||||||
Ok (List.getUnsafe list index)
|
Ok (List.getUnsafe list index)
|
||||||
|
@ -245,9 +245,9 @@ get = \list, index ->
|
||||||
|
|
||||||
# unsafe primitive that does not perform a bounds check
|
# unsafe primitive that does not perform a bounds check
|
||||||
# but will cause a reference count increment on the value it got out of the list
|
# but will cause a reference count increment on the value it got out of the list
|
||||||
replaceUnsafe : List a, Nat, a -> { list : List a, value : a }
|
replaceUnsafe : List a, U64, a -> { list : List a, value : a }
|
||||||
|
|
||||||
replace : List a, Nat, a -> { list : List a, value : a }
|
replace : List a, U64, a -> { list : List a, value : a }
|
||||||
replace = \list, index, newValue ->
|
replace = \list, index, newValue ->
|
||||||
if index < List.len list then
|
if index < List.len list then
|
||||||
List.replaceUnsafe list index newValue
|
List.replaceUnsafe list index newValue
|
||||||
|
@ -262,7 +262,7 @@ replace = \list, index, newValue ->
|
||||||
## list unmodified.
|
## list unmodified.
|
||||||
##
|
##
|
||||||
## To drop the element at a given index, instead of replacing it, see [List.dropAt].
|
## To drop the element at a given index, instead of replacing it, see [List.dropAt].
|
||||||
set : List a, Nat, a -> List a
|
set : List a, U64, a -> List a
|
||||||
set = \list, index, value ->
|
set = \list, index, value ->
|
||||||
(List.replace list index value).list
|
(List.replace list index value).list
|
||||||
|
|
||||||
|
@ -275,7 +275,7 @@ set = \list, index, value ->
|
||||||
##
|
##
|
||||||
## To replace the element at a given index, instead of updating based on the current value,
|
## To replace the element at a given index, instead of updating based on the current value,
|
||||||
## see [List.set] and [List.replace]
|
## see [List.set] and [List.replace]
|
||||||
update : List a, Nat, (a -> a) -> List a
|
update : List a, U64, (a -> a) -> List a
|
||||||
update = \list, index, func ->
|
update = \list, index, func ->
|
||||||
when List.get list index is
|
when List.get list index is
|
||||||
Err OutOfBounds -> list
|
Err OutOfBounds -> list
|
||||||
|
@ -285,7 +285,7 @@ update = \list, index, func ->
|
||||||
|
|
||||||
# Update one element in bounds
|
# Update one element in bounds
|
||||||
expect
|
expect
|
||||||
list : List Nat
|
list : List U64
|
||||||
list = [1, 2, 3]
|
list = [1, 2, 3]
|
||||||
got = update list 1 (\x -> x + 42)
|
got = update list 1 (\x -> x + 42)
|
||||||
want = [1, 44, 3]
|
want = [1, 44, 3]
|
||||||
|
@ -293,14 +293,14 @@ expect
|
||||||
|
|
||||||
# Update out of bounds
|
# Update out of bounds
|
||||||
expect
|
expect
|
||||||
list : List Nat
|
list : List U64
|
||||||
list = [1, 2, 3]
|
list = [1, 2, 3]
|
||||||
got = update list 5 (\x -> x + 42)
|
got = update list 5 (\x -> x + 42)
|
||||||
got == list
|
got == list
|
||||||
|
|
||||||
# Update chain
|
# Update chain
|
||||||
expect
|
expect
|
||||||
list : List Nat
|
list : List U64
|
||||||
list = [1, 2, 3]
|
list = [1, 2, 3]
|
||||||
got =
|
got =
|
||||||
list
|
list
|
||||||
|
@ -374,13 +374,13 @@ prependIfOk = \list, result ->
|
||||||
## One [List] can store up to 2,147,483,648 elements (just over 2 billion), which
|
## One [List] can store up to 2,147,483,648 elements (just over 2 billion), which
|
||||||
## is exactly equal to the highest valid #I32 value. This means the #U32 this function
|
## is exactly equal to the highest valid #I32 value. This means the #U32 this function
|
||||||
## returns can always be safely converted to an #I32 without losing any data.
|
## returns can always be safely converted to an #I32 without losing any data.
|
||||||
len : List * -> Nat
|
len : List * -> U64
|
||||||
|
|
||||||
## Create a list with space for at least capacity elements
|
## Create a list with space for at least capacity elements
|
||||||
withCapacity : Nat -> List *
|
withCapacity : U64 -> List *
|
||||||
|
|
||||||
## Enlarge the list for at least capacity additional elements
|
## Enlarge the list for at least capacity additional elements
|
||||||
reserve : List a, Nat -> List a
|
reserve : List a, U64 -> List a
|
||||||
|
|
||||||
## Shrink the memory footprint of a list such that it's capacity and length are equal.
|
## Shrink the memory footprint of a list such that it's capacity and length are equal.
|
||||||
## Note: This will also convert seamless slices to regular lists.
|
## Note: This will also convert seamless slices to regular lists.
|
||||||
|
@ -418,11 +418,11 @@ single : a -> List a
|
||||||
single = \x -> [x]
|
single = \x -> [x]
|
||||||
|
|
||||||
## Returns a list with the given length, where every element is the given value.
|
## Returns a list with the given length, where every element is the given value.
|
||||||
repeat : a, Nat -> List a
|
repeat : a, U64 -> List a
|
||||||
repeat = \value, count ->
|
repeat = \value, count ->
|
||||||
repeatHelp value count (List.withCapacity count)
|
repeatHelp value count (List.withCapacity count)
|
||||||
|
|
||||||
repeatHelp : a, Nat, List a -> List a
|
repeatHelp : a, U64, List a -> List a
|
||||||
repeatHelp = \value, count, accum ->
|
repeatHelp = \value, count, accum ->
|
||||||
if count > 0 then
|
if count > 0 then
|
||||||
repeatHelp value (Num.subWrap count 1) (List.appendUnsafe accum value)
|
repeatHelp value (Num.subWrap count 1) (List.appendUnsafe accum value)
|
||||||
|
@ -501,7 +501,7 @@ walk = \list, init, func ->
|
||||||
walkHelp list init func 0 (List.len list)
|
walkHelp list init func 0 (List.len list)
|
||||||
|
|
||||||
## internal helper
|
## internal helper
|
||||||
walkHelp : List elem, s, (s, elem -> s), Nat, Nat -> s
|
walkHelp : List elem, s, (s, elem -> s), U64, U64 -> s
|
||||||
walkHelp = \list, state, f, index, length ->
|
walkHelp = \list, state, f, index, length ->
|
||||||
if index < length then
|
if index < length then
|
||||||
nextState = f state (List.getUnsafe list index)
|
nextState = f state (List.getUnsafe list index)
|
||||||
|
@ -511,12 +511,12 @@ walkHelp = \list, state, f, index, length ->
|
||||||
state
|
state
|
||||||
|
|
||||||
## Like [walk], but at each step the function also receives the index of the current element.
|
## Like [walk], but at each step the function also receives the index of the current element.
|
||||||
walkWithIndex : List elem, state, (state, elem, Nat -> state) -> state
|
walkWithIndex : List elem, state, (state, elem, U64 -> state) -> state
|
||||||
walkWithIndex = \list, init, func ->
|
walkWithIndex = \list, init, func ->
|
||||||
walkWithIndexHelp list init func 0 (List.len list)
|
walkWithIndexHelp list init func 0 (List.len list)
|
||||||
|
|
||||||
## internal helper
|
## internal helper
|
||||||
walkWithIndexHelp : List elem, s, (s, elem, Nat -> s), Nat, Nat -> s
|
walkWithIndexHelp : List elem, s, (s, elem, U64 -> s), U64, U64 -> s
|
||||||
walkWithIndexHelp = \list, state, f, index, length ->
|
walkWithIndexHelp = \list, state, f, index, length ->
|
||||||
if index < length then
|
if index < length then
|
||||||
nextState = f state (List.getUnsafe list index) index
|
nextState = f state (List.getUnsafe list index) index
|
||||||
|
@ -526,14 +526,14 @@ walkWithIndexHelp = \list, state, f, index, length ->
|
||||||
state
|
state
|
||||||
|
|
||||||
## Like [walkUntil], but at each step the function also receives the index of the current element.
|
## Like [walkUntil], but at each step the function also receives the index of the current element.
|
||||||
walkWithIndexUntil : List elem, state, (state, elem, Nat -> [Continue state, Break state]) -> state
|
walkWithIndexUntil : List elem, state, (state, elem, U64 -> [Continue state, Break state]) -> state
|
||||||
walkWithIndexUntil = \list, state, f ->
|
walkWithIndexUntil = \list, state, f ->
|
||||||
when walkWithIndexUntilHelp list state f 0 (List.len list) is
|
when walkWithIndexUntilHelp list state f 0 (List.len list) is
|
||||||
Continue new -> new
|
Continue new -> new
|
||||||
Break new -> new
|
Break new -> new
|
||||||
|
|
||||||
## internal helper
|
## internal helper
|
||||||
walkWithIndexUntilHelp : List elem, s, (s, elem, Nat -> [Continue s, Break b]), Nat, Nat -> [Continue s, Break b]
|
walkWithIndexUntilHelp : List elem, s, (s, elem, U64 -> [Continue s, Break b]), U64, U64 -> [Continue s, Break b]
|
||||||
walkWithIndexUntilHelp = \list, state, f, index, length ->
|
walkWithIndexUntilHelp = \list, state, f, index, length ->
|
||||||
if index < length then
|
if index < length then
|
||||||
when f state (List.getUnsafe list index) index is
|
when f state (List.getUnsafe list index) index is
|
||||||
|
@ -551,7 +551,7 @@ walkBackwards = \list, state, func ->
|
||||||
walkBackwardsHelp list state func (len list)
|
walkBackwardsHelp list state func (len list)
|
||||||
|
|
||||||
## internal helper
|
## internal helper
|
||||||
walkBackwardsHelp : List elem, state, (state, elem -> state), Nat -> state
|
walkBackwardsHelp : List elem, state, (state, elem -> state), U64 -> state
|
||||||
walkBackwardsHelp = \list, state, f, indexPlusOne ->
|
walkBackwardsHelp = \list, state, f, indexPlusOne ->
|
||||||
if indexPlusOne == 0 then
|
if indexPlusOne == 0 then
|
||||||
state
|
state
|
||||||
|
@ -586,7 +586,7 @@ walkBackwardsUntil = \list, initial, func ->
|
||||||
Break new -> new
|
Break new -> new
|
||||||
|
|
||||||
## Walks to the end of the list from a specified starting index
|
## Walks to the end of the list from a specified starting index
|
||||||
walkFrom : List elem, Nat, state, (state, elem -> state) -> state
|
walkFrom : List elem, U64, state, (state, elem -> state) -> state
|
||||||
walkFrom = \list, index, state, func ->
|
walkFrom = \list, index, state, func ->
|
||||||
step : _, _ -> [Continue _, Break []]
|
step : _, _ -> [Continue _, Break []]
|
||||||
step = \currentState, element -> Continue (func currentState element)
|
step = \currentState, element -> Continue (func currentState element)
|
||||||
|
@ -595,7 +595,7 @@ walkFrom = \list, index, state, func ->
|
||||||
Continue new -> new
|
Continue new -> new
|
||||||
|
|
||||||
## A combination of [List.walkFrom] and [List.walkUntil]
|
## A combination of [List.walkFrom] and [List.walkUntil]
|
||||||
walkFromUntil : List elem, Nat, state, (state, elem -> [Continue state, Break state]) -> state
|
walkFromUntil : List elem, U64, state, (state, elem -> [Continue state, Break state]) -> state
|
||||||
walkFromUntil = \list, index, state, func ->
|
walkFromUntil = \list, index, state, func ->
|
||||||
when List.iterHelp list state func index (List.len list) is
|
when List.iterHelp list state func index (List.len list) is
|
||||||
Continue new -> new
|
Continue new -> new
|
||||||
|
@ -664,7 +664,7 @@ keepIf = \list, predicate ->
|
||||||
|
|
||||||
keepIfHelp list predicate 0 0 length
|
keepIfHelp list predicate 0 0 length
|
||||||
|
|
||||||
keepIfHelp : List a, (a -> Bool), Nat, Nat, Nat -> List a
|
keepIfHelp : List a, (a -> Bool), U64, U64, U64 -> List a
|
||||||
keepIfHelp = \list, predicate, kept, index, length ->
|
keepIfHelp = \list, predicate, kept, index, length ->
|
||||||
if index < length then
|
if index < length then
|
||||||
if predicate (List.getUnsafe list index) then
|
if predicate (List.getUnsafe list index) then
|
||||||
|
@ -693,7 +693,7 @@ dropIf = \list, predicate ->
|
||||||
## expect List.countIf [1, -2, -3] Num.isNegative == 2
|
## expect List.countIf [1, -2, -3] Num.isNegative == 2
|
||||||
## expect List.countIf [1, 2, 3] (\num -> num > 1 ) == 2
|
## expect List.countIf [1, 2, 3] (\num -> num > 1 ) == 2
|
||||||
## ```
|
## ```
|
||||||
countIf : List a, (a -> Bool) -> Nat
|
countIf : List a, (a -> Bool) -> U64
|
||||||
countIf = \list, predicate ->
|
countIf = \list, predicate ->
|
||||||
walkState = \state, elem ->
|
walkState = \state, elem ->
|
||||||
if predicate elem then
|
if predicate elem then
|
||||||
|
@ -775,7 +775,7 @@ map4 : List a, List b, List c, List d, (a, b, c, d -> e) -> List e
|
||||||
## ```
|
## ```
|
||||||
## expect List.mapWithIndex [10, 20, 30] (\num, index -> num + index) == [10, 21, 32]
|
## expect List.mapWithIndex [10, 20, 30] (\num, index -> num + index) == [10, 21, 32]
|
||||||
## ```
|
## ```
|
||||||
mapWithIndex : List a, (a, Nat -> b) -> List b
|
mapWithIndex : List a, (a, U64 -> b) -> List b
|
||||||
mapWithIndex = \src, func ->
|
mapWithIndex = \src, func ->
|
||||||
length = len src
|
length = len src
|
||||||
dest = withCapacity length
|
dest = withCapacity length
|
||||||
|
@ -783,7 +783,7 @@ mapWithIndex = \src, func ->
|
||||||
mapWithIndexHelp src dest func 0 length
|
mapWithIndexHelp src dest func 0 length
|
||||||
|
|
||||||
# Internal helper
|
# Internal helper
|
||||||
mapWithIndexHelp : List a, List b, (a, Nat -> b), Nat, Nat -> List b
|
mapWithIndexHelp : List a, List b, (a, U64 -> b), U64, U64 -> List b
|
||||||
mapWithIndexHelp = \src, dest, func, index, length ->
|
mapWithIndexHelp = \src, dest, func, index, length ->
|
||||||
if index < length then
|
if index < length then
|
||||||
elem = getUnsafe src index
|
elem = getUnsafe src index
|
||||||
|
@ -958,7 +958,7 @@ sortAsc = \list -> List.sortWith list Num.compare
|
||||||
sortDesc : List (Num a) -> List (Num a)
|
sortDesc : List (Num a) -> List (Num a)
|
||||||
sortDesc = \list -> List.sortWith list (\a, b -> Num.compare b a)
|
sortDesc = \list -> List.sortWith list (\a, b -> Num.compare b a)
|
||||||
|
|
||||||
swap : List a, Nat, Nat -> List a
|
swap : List a, U64, U64 -> List a
|
||||||
|
|
||||||
## Returns the first element in the list, or `ListWasEmpty` if it was empty.
|
## Returns the first element in the list, or `ListWasEmpty` if it was empty.
|
||||||
first : List a -> Result a [ListWasEmpty]
|
first : List a -> Result a [ListWasEmpty]
|
||||||
|
@ -983,7 +983,7 @@ first = \list ->
|
||||||
##
|
##
|
||||||
## To split the list into two lists, use `List.split`.
|
## To split the list into two lists, use `List.split`.
|
||||||
##
|
##
|
||||||
takeFirst : List elem, Nat -> List elem
|
takeFirst : List elem, U64 -> List elem
|
||||||
takeFirst = \list, outputLength ->
|
takeFirst = \list, outputLength ->
|
||||||
List.sublist list { start: 0, len: outputLength }
|
List.sublist list { start: 0, len: outputLength }
|
||||||
|
|
||||||
|
@ -1003,19 +1003,19 @@ takeFirst = \list, outputLength ->
|
||||||
##
|
##
|
||||||
## To split the list into two lists, use `List.split`.
|
## To split the list into two lists, use `List.split`.
|
||||||
##
|
##
|
||||||
takeLast : List elem, Nat -> List elem
|
takeLast : List elem, U64 -> List elem
|
||||||
takeLast = \list, outputLength ->
|
takeLast = \list, outputLength ->
|
||||||
List.sublist list { start: Num.subSaturated (List.len list) outputLength, len: outputLength }
|
List.sublist list { start: Num.subSaturated (List.len list) outputLength, len: outputLength }
|
||||||
|
|
||||||
## Drops n elements from the beginning of the list.
|
## Drops n elements from the beginning of the list.
|
||||||
dropFirst : List elem, Nat -> List elem
|
dropFirst : List elem, U64 -> List elem
|
||||||
dropFirst = \list, n ->
|
dropFirst = \list, n ->
|
||||||
remaining = Num.subSaturated (List.len list) n
|
remaining = Num.subSaturated (List.len list) n
|
||||||
|
|
||||||
List.takeLast list remaining
|
List.takeLast list remaining
|
||||||
|
|
||||||
## Drops n elements from the end of the list.
|
## Drops n elements from the end of the list.
|
||||||
dropLast : List elem, Nat -> List elem
|
dropLast : List elem, U64 -> List elem
|
||||||
dropLast = \list, n ->
|
dropLast = \list, n ->
|
||||||
remaining = Num.subSaturated (List.len list) n
|
remaining = Num.subSaturated (List.len list) n
|
||||||
|
|
||||||
|
@ -1026,7 +1026,7 @@ dropLast = \list, n ->
|
||||||
## This has no effect if the given index is outside the bounds of the list.
|
## This has no effect if the given index is outside the bounds of the list.
|
||||||
##
|
##
|
||||||
## To replace the element at a given index, instead of dropping it, see [List.set].
|
## To replace the element at a given index, instead of dropping it, see [List.set].
|
||||||
dropAt : List elem, Nat -> List elem
|
dropAt : List elem, U64 -> List elem
|
||||||
|
|
||||||
min : List (Num a) -> Result (Num a) [ListWasEmpty]
|
min : List (Num a) -> Result (Num a) [ListWasEmpty]
|
||||||
min = \list ->
|
min = \list ->
|
||||||
|
@ -1101,7 +1101,7 @@ findLast = \list, pred ->
|
||||||
## Returns the index at which the first element in the list
|
## Returns the index at which the first element in the list
|
||||||
## satisfying a predicate function can be found.
|
## satisfying a predicate function can be found.
|
||||||
## If no satisfying element is found, an `Err NotFound` is returned.
|
## If no satisfying element is found, an `Err NotFound` is returned.
|
||||||
findFirstIndex : List elem, (elem -> Bool) -> Result Nat [NotFound]
|
findFirstIndex : List elem, (elem -> Bool) -> Result U64 [NotFound]
|
||||||
findFirstIndex = \list, matcher ->
|
findFirstIndex = \list, matcher ->
|
||||||
foundIndex = List.iterate list 0 \index, elem ->
|
foundIndex = List.iterate list 0 \index, elem ->
|
||||||
if matcher elem then
|
if matcher elem then
|
||||||
|
@ -1116,7 +1116,7 @@ findFirstIndex = \list, matcher ->
|
||||||
## Returns the last index at which the first element in the list
|
## Returns the last index at which the first element in the list
|
||||||
## satisfying a predicate function can be found.
|
## satisfying a predicate function can be found.
|
||||||
## If no satisfying element is found, an `Err NotFound` is returned.
|
## If no satisfying element is found, an `Err NotFound` is returned.
|
||||||
findLastIndex : List elem, (elem -> Bool) -> Result Nat [NotFound]
|
findLastIndex : List elem, (elem -> Bool) -> Result U64 [NotFound]
|
||||||
findLastIndex = \list, matches ->
|
findLastIndex = \list, matches ->
|
||||||
foundIndex = List.iterateBackwards list (List.len list) \prevIndex, elem ->
|
foundIndex = List.iterateBackwards list (List.len list) \prevIndex, elem ->
|
||||||
answer = Num.subWrap prevIndex 1
|
answer = Num.subWrap prevIndex 1
|
||||||
|
@ -1145,12 +1145,12 @@ findLastIndex = \list, matches ->
|
||||||
## > 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.
|
||||||
##
|
##
|
||||||
## Some languages have a function called **`slice`** which works similarly to this.
|
## Some languages have a function called **`slice`** which works similarly to this.
|
||||||
sublist : List elem, { start : Nat, len : Nat } -> List elem
|
sublist : List elem, { start : U64, len : U64 } -> List elem
|
||||||
sublist = \list, config ->
|
sublist = \list, config ->
|
||||||
sublistLowlevel list config.start config.len
|
sublistLowlevel list config.start config.len
|
||||||
|
|
||||||
## low-level slicing operation that does no bounds checking
|
## low-level slicing operation that does no bounds checking
|
||||||
sublistLowlevel : List elem, Nat, Nat -> List elem
|
sublistLowlevel : List elem, U64, U64 -> List elem
|
||||||
|
|
||||||
## Intersperses `sep` between the elements of `list`
|
## Intersperses `sep` between the elements of `list`
|
||||||
## ```
|
## ```
|
||||||
|
@ -1202,7 +1202,7 @@ endsWith = \list, suffix ->
|
||||||
## than the given index, # and the `others` list will be all the others. (This
|
## than the given index, # and the `others` list will be all the others. (This
|
||||||
## means if you give an index of 0, the `before` list will be empty and the
|
## means if you give an index of 0, the `before` list will be empty and the
|
||||||
## `others` list will have the same elements as the original list.)
|
## `others` list will have the same elements as the original list.)
|
||||||
split : List elem, Nat -> { before : List elem, others : List elem }
|
split : List elem, U64 -> { before : List elem, others : List elem }
|
||||||
split = \elements, userSplitIndex ->
|
split = \elements, userSplitIndex ->
|
||||||
length = List.len elements
|
length = List.len elements
|
||||||
splitIndex = if length > userSplitIndex then userSplitIndex else length
|
splitIndex = if length > userSplitIndex then userSplitIndex else length
|
||||||
|
@ -1247,7 +1247,7 @@ splitLast = \list, delimiter ->
|
||||||
## size. The last chunk will be shorter if the list does not evenly divide by the
|
## size. The last chunk will be shorter if the list does not evenly divide by the
|
||||||
## chunk size. If the provided list is empty or if the chunk size is 0 then the
|
## chunk size. If the provided list is empty or if the chunk size is 0 then the
|
||||||
## result is an empty list.
|
## result is an empty list.
|
||||||
chunksOf : List a, Nat -> List (List a)
|
chunksOf : List a, U64 -> List (List a)
|
||||||
chunksOf = \list, chunkSize ->
|
chunksOf = \list, chunkSize ->
|
||||||
if chunkSize == 0 || List.isEmpty list then
|
if chunkSize == 0 || List.isEmpty list then
|
||||||
[]
|
[]
|
||||||
|
@ -1255,7 +1255,7 @@ chunksOf = \list, chunkSize ->
|
||||||
chunkCapacity = Num.divCeil (List.len list) chunkSize
|
chunkCapacity = Num.divCeil (List.len list) chunkSize
|
||||||
chunksOfHelp list chunkSize (List.withCapacity chunkCapacity)
|
chunksOfHelp list chunkSize (List.withCapacity chunkCapacity)
|
||||||
|
|
||||||
chunksOfHelp : List a, Nat, List (List a) -> List (List a)
|
chunksOfHelp : List a, U64, List (List a) -> List (List a)
|
||||||
chunksOfHelp = \listRest, chunkSize, chunks ->
|
chunksOfHelp = \listRest, chunkSize, chunks ->
|
||||||
if List.isEmpty listRest then
|
if List.isEmpty listRest then
|
||||||
chunks
|
chunks
|
||||||
|
@ -1288,7 +1288,7 @@ walkTry = \list, init, func ->
|
||||||
walkTryHelp list init func 0 (List.len list)
|
walkTryHelp list init func 0 (List.len list)
|
||||||
|
|
||||||
## internal helper
|
## internal helper
|
||||||
walkTryHelp : List elem, state, (state, elem -> Result state err), Nat, Nat -> Result state err
|
walkTryHelp : List elem, state, (state, elem -> Result state err), U64, U64 -> Result state err
|
||||||
walkTryHelp = \list, state, f, index, length ->
|
walkTryHelp = \list, state, f, index, length ->
|
||||||
if index < length then
|
if index < length then
|
||||||
when f state (List.getUnsafe list index) is
|
when f state (List.getUnsafe list index) is
|
||||||
|
@ -1303,7 +1303,7 @@ iterate = \list, init, func ->
|
||||||
iterHelp list init func 0 (List.len list)
|
iterHelp list init func 0 (List.len list)
|
||||||
|
|
||||||
## internal helper
|
## internal helper
|
||||||
iterHelp : List elem, s, (s, elem -> [Continue s, Break b]), Nat, Nat -> [Continue s, Break b]
|
iterHelp : List elem, s, (s, elem -> [Continue s, Break b]), U64, U64 -> [Continue s, Break b]
|
||||||
iterHelp = \list, state, f, index, length ->
|
iterHelp = \list, state, f, index, length ->
|
||||||
if index < length then
|
if index < length then
|
||||||
when f state (List.getUnsafe list index) is
|
when f state (List.getUnsafe list index) is
|
||||||
|
@ -1319,7 +1319,7 @@ iterateBackwards = \list, init, func ->
|
||||||
iterBackwardsHelp list init func (List.len list)
|
iterBackwardsHelp list init func (List.len list)
|
||||||
|
|
||||||
## internal helper
|
## internal helper
|
||||||
iterBackwardsHelp : List elem, s, (s, elem -> [Continue s, Break b]), Nat -> [Continue s, Break b]
|
iterBackwardsHelp : List elem, s, (s, elem -> [Continue s, Break b]), U64 -> [Continue s, Break b]
|
||||||
iterBackwardsHelp = \list, state, f, prevIndex ->
|
iterBackwardsHelp = \list, state, f, prevIndex ->
|
||||||
if prevIndex > 0 then
|
if prevIndex > 0 then
|
||||||
index = Num.subWrap prevIndex 1
|
index = Num.subWrap prevIndex 1
|
||||||
|
|
|
@ -143,6 +143,8 @@ pub(crate) fn list_get_unsafe<'a, 'ctx>(
|
||||||
layout_interner,
|
layout_interner,
|
||||||
layout_interner.get_repr(element_layout),
|
layout_interner.get_repr(element_layout),
|
||||||
);
|
);
|
||||||
|
// listGetUnsafe takes a U64, but we need to convert that to usize for index calculation.
|
||||||
|
let elem_index = builder.new_build_int_cast(elem_index, env.ptr_int(), "u64_to_usize");
|
||||||
let ptr_type = elem_type.ptr_type(AddressSpace::default());
|
let ptr_type = elem_type.ptr_type(AddressSpace::default());
|
||||||
// Load the pointer to the array data
|
// Load the pointer to the array data
|
||||||
let array_data_ptr = load_list_ptr(builder, wrapper_struct, ptr_type);
|
let array_data_ptr = load_list_ptr(builder, wrapper_struct, ptr_type);
|
||||||
|
@ -423,7 +425,7 @@ fn bounds_check_comparison<'ctx>(
|
||||||
builder.new_build_int_compare(IntPredicate::ULT, elem_index, len, "bounds_check")
|
builder.new_build_int_compare(IntPredicate::ULT, elem_index, len, "bounds_check")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// List.len : List * -> Nat
|
/// List.len : List * -> usize (return value will be cast to usize in user-facing API)
|
||||||
pub(crate) fn list_len<'ctx>(
|
pub(crate) fn list_len<'ctx>(
|
||||||
builder: &Builder<'ctx>,
|
builder: &Builder<'ctx>,
|
||||||
wrapper_struct: StructValue<'ctx>,
|
wrapper_struct: StructValue<'ctx>,
|
||||||
|
|
|
@ -618,10 +618,15 @@ pub(crate) fn run_low_level<'a, 'ctx>(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ListLen => {
|
ListLen => {
|
||||||
// List.len : List * -> Nat
|
// List.len : List * -> U64
|
||||||
arguments!(list);
|
arguments!(list);
|
||||||
|
|
||||||
list_len(env.builder, list.into_struct_value()).into()
|
let len_usize = list_len(env.builder, list.into_struct_value());
|
||||||
|
|
||||||
|
// List.len returns U64, although length is stored as usize
|
||||||
|
env.builder
|
||||||
|
.new_build_int_cast(len_usize, env.context.i64_type(), "usize_to_u64")
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
ListGetCapacity => {
|
ListGetCapacity => {
|
||||||
// List.capacity: List a -> Nat
|
// List.capacity: List a -> Nat
|
||||||
|
|
|
@ -279,6 +279,9 @@ impl<'a> LowLevelCall<'a> {
|
||||||
backend
|
backend
|
||||||
.code_builder
|
.code_builder
|
||||||
.i32_load(Align::Bytes4, offset + (4 * Builtin::WRAPPER_LEN));
|
.i32_load(Align::Bytes4, offset + (4 * Builtin::WRAPPER_LEN));
|
||||||
|
|
||||||
|
// Length is stored as 32 bits in memory, but List.len returns U64
|
||||||
|
backend.code_builder.i64_extend_u_i32();
|
||||||
}
|
}
|
||||||
_ => internal_error!("invalid storage for List"),
|
_ => internal_error!("invalid storage for List"),
|
||||||
},
|
},
|
||||||
|
@ -321,6 +324,7 @@ impl<'a> LowLevelCall<'a> {
|
||||||
backend
|
backend
|
||||||
.storage
|
.storage
|
||||||
.load_symbols(&mut backend.code_builder, &[index]);
|
.load_symbols(&mut backend.code_builder, &[index]);
|
||||||
|
backend.code_builder.i32_wrap_i64(); // listGetUnsafe takes a U64, but we do 32-bit indexing on wasm.
|
||||||
let elem_size = backend.layout_interner.stack_size(self.ret_layout);
|
let elem_size = backend.layout_interner.stack_size(self.ret_layout);
|
||||||
backend.code_builder.i32_const(elem_size as i32);
|
backend.code_builder.i32_const(elem_size as i32);
|
||||||
backend.code_builder.i32_mul(); // index*size
|
backend.code_builder.i32_mul(); // index*size
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue