mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 03:42:17 +00:00
Weaken records in let-bindings
This change also means we must update the interface of `Dict.empty` and `Set.empty` from ``` Dict.empty : Dict k v ``` to ``` Dict.empty : {} -> Dict k v ```
This commit is contained in:
parent
61ac9bf9b2
commit
b8712bcb30
9 changed files with 70 additions and 75 deletions
|
@ -47,7 +47,7 @@ interface Dict
|
|||
## its population as the associated value.
|
||||
##
|
||||
## populationByCity =
|
||||
## Dict.empty
|
||||
## Dict.empty {}
|
||||
## |> Dict.insert "London" 8_961_989
|
||||
## |> Dict.insert "Philadelphia" 1_603_797
|
||||
## |> Dict.insert "Shanghai" 24_870_895
|
||||
|
@ -100,8 +100,8 @@ Dict k v := {
|
|||
} | k has Hash & Eq
|
||||
|
||||
## Return an empty dictionary.
|
||||
empty : Dict k v | k has Hash & Eq
|
||||
empty =
|
||||
empty : {} -> Dict k v | k has Hash & Eq
|
||||
empty = \{} ->
|
||||
@Dict {
|
||||
metadata: List.repeat emptySlot 8,
|
||||
dataIndices: List.repeat 0 8,
|
||||
|
@ -122,16 +122,16 @@ capacity = \@Dict { dataIndices } ->
|
|||
withCapacity : Nat -> Dict k v | k has Hash & Eq
|
||||
withCapacity = \_ ->
|
||||
# TODO: power of 2 * 8 and actual implementation
|
||||
empty
|
||||
empty {}
|
||||
|
||||
## Returns a dictionary containing the key and value provided as input.
|
||||
##
|
||||
## expect
|
||||
## Dict.single "A" "B"
|
||||
## |> Bool.isEq (Dict.insert Dict.empty "A" "B")
|
||||
## |> Bool.isEq (Dict.insert (Dict.empty {}) "A" "B")
|
||||
single : k, v -> Dict k v | k has Hash & Eq
|
||||
single = \k, v ->
|
||||
insert empty k v
|
||||
insert (empty {}) k v
|
||||
|
||||
## Returns dictionary with the keys and values specified by the input [List].
|
||||
##
|
||||
|
@ -144,12 +144,12 @@ single = \k, v ->
|
|||
fromList : List (T k v) -> Dict k v | k has Hash & Eq
|
||||
fromList = \data ->
|
||||
# TODO: make this efficient. Should just set data and then set all indicies in the hashmap.
|
||||
List.walk data empty (\dict, T k v -> insert dict k v)
|
||||
List.walk data (empty {}) (\dict, T k v -> insert dict k v)
|
||||
|
||||
## Returns the number of values in the dictionary.
|
||||
##
|
||||
## expect
|
||||
## Dict.empty
|
||||
## Dict.empty {}
|
||||
## |> Dict.insert "One" "A Song"
|
||||
## |> Dict.insert "Two" "Candy Canes"
|
||||
## |> Dict.insert "Three" "Boughs of Holly"
|
||||
|
@ -166,7 +166,7 @@ clear = \@Dict { metadata, dataIndices, data } ->
|
|||
|
||||
# Only clear large allocations.
|
||||
if cap > 128 * 8 then
|
||||
empty
|
||||
empty {}
|
||||
else
|
||||
@Dict {
|
||||
metadata: List.map metadata (\_ -> emptySlot),
|
||||
|
@ -182,7 +182,7 @@ clear = \@Dict { metadata, dataIndices, data } ->
|
|||
## initial `state` value provided for the first call.
|
||||
##
|
||||
## expect
|
||||
## Dict.empty
|
||||
## Dict.empty {}
|
||||
## |> Dict.insert "Apples" 12
|
||||
## |> Dict.insert "Orange" 24
|
||||
## |> Dict.walk 0 (\count, _, qty -> count + qty)
|
||||
|
@ -210,7 +210,7 @@ walkUntil = \@Dict { data }, initialState, transform ->
|
|||
## will return [Ok value], otherwise return [Err KeyNotFound].
|
||||
##
|
||||
## dictionary =
|
||||
## Dict.empty
|
||||
## Dict.empty {}
|
||||
## |> Dict.insert 1 "Apple"
|
||||
## |> Dict.insert 2 "Orange"
|
||||
##
|
||||
|
@ -239,7 +239,7 @@ get = \@Dict { metadata, dataIndices, data }, key ->
|
|||
## Check if the dictionary has a value for a specified key.
|
||||
##
|
||||
## expect
|
||||
## Dict.empty
|
||||
## Dict.empty {}
|
||||
## |> Dict.insert 1234 "5678"
|
||||
## |> Dict.contains 1234
|
||||
## |> Bool.isEq Bool.true
|
||||
|
@ -263,7 +263,7 @@ contains = \@Dict { metadata, dataIndices, data }, key ->
|
|||
## Insert a value into the dictionary at a specified key.
|
||||
##
|
||||
## expect
|
||||
## Dict.empty
|
||||
## Dict.empty {}
|
||||
## |> Dict.insert "Apples" 12
|
||||
## |> Dict.get "Apples"
|
||||
## |> Bool.isEq (Ok 12)
|
||||
|
@ -307,7 +307,7 @@ insert = \@Dict { metadata, dataIndices, data, size }, key, value ->
|
|||
## Remove a value from the dictionary for a specified key.
|
||||
##
|
||||
## expect
|
||||
## Dict.empty
|
||||
## Dict.empty {}
|
||||
## |> Dict.insert "Some" "Value"
|
||||
## |> Dict.remove "Some"
|
||||
## |> Dict.len
|
||||
|
@ -352,9 +352,9 @@ remove = \@Dict { metadata, dataIndices, data, size }, key ->
|
|||
## Missing -> Present Bool.false
|
||||
## Present value -> if value then Missing else Present Bool.true
|
||||
##
|
||||
## expect Dict.update Dict.empty "a" alterValue == Dict.single "a" Bool.false
|
||||
## expect Dict.update (Dict.empty {}) "a" alterValue == Dict.single "a" Bool.false
|
||||
## expect Dict.update (Dict.single "a" Bool.false) "a" alterValue == Dict.single "a" Bool.true
|
||||
## expect Dict.update (Dict.single "a" Bool.true) "a" alterValue == Dict.empty
|
||||
## expect Dict.update (Dict.single "a" Bool.true) "a" alterValue == Dict.empty {}
|
||||
update : Dict k v, k, ([Present v, Missing] -> [Present v, Missing]) -> Dict k v | k has Hash & Eq
|
||||
update = \dict, key, alter ->
|
||||
# TODO: look into optimizing by merging substeps and reducing lookups.
|
||||
|
@ -457,7 +457,7 @@ keepShared : Dict k v, Dict k v -> Dict k v | k has Hash & Eq
|
|||
keepShared = \xs, ys ->
|
||||
walk
|
||||
xs
|
||||
empty
|
||||
(empty {})
|
||||
(\state, k, v ->
|
||||
if contains ys k then
|
||||
insert state k v
|
||||
|
@ -688,7 +688,7 @@ h2 = \hashKey ->
|
|||
|
||||
expect
|
||||
val =
|
||||
empty
|
||||
empty {}
|
||||
|> insert "foo" "bar"
|
||||
|> get "foo"
|
||||
|
||||
|
@ -696,7 +696,7 @@ expect
|
|||
|
||||
expect
|
||||
val =
|
||||
empty
|
||||
empty {}
|
||||
|> insert "foo" "bar"
|
||||
|> insert "foo" "baz"
|
||||
|> get "foo"
|
||||
|
@ -705,20 +705,20 @@ expect
|
|||
|
||||
expect
|
||||
val =
|
||||
empty
|
||||
empty {}
|
||||
|> insert "foo" "bar"
|
||||
|> get "bar"
|
||||
|
||||
val == Err KeyNotFound
|
||||
|
||||
expect
|
||||
empty
|
||||
empty {}
|
||||
|> insert "foo" {}
|
||||
|> contains "foo"
|
||||
|
||||
expect
|
||||
dict =
|
||||
empty
|
||||
empty {}
|
||||
|> insert "foo" {}
|
||||
|> insert "bar" {}
|
||||
|> insert "baz" {}
|
||||
|
@ -746,7 +746,7 @@ expect
|
|||
# Reach capacity, no rehash.
|
||||
expect
|
||||
val =
|
||||
empty
|
||||
empty {}
|
||||
|> insert "a" 0
|
||||
|> insert "b" 1
|
||||
|> insert "c" 2
|
||||
|
@ -760,7 +760,7 @@ expect
|
|||
|
||||
expect
|
||||
dict =
|
||||
empty
|
||||
empty {}
|
||||
|> insert "a" 0
|
||||
|> insert "b" 1
|
||||
|> insert "c" 2
|
||||
|
@ -780,7 +780,7 @@ expect
|
|||
# Force rehash.
|
||||
expect
|
||||
val =
|
||||
empty
|
||||
empty {}
|
||||
|> insert "a" 0
|
||||
|> insert "b" 1
|
||||
|> insert "c" 2
|
||||
|
@ -795,7 +795,7 @@ expect
|
|||
|
||||
expect
|
||||
dict =
|
||||
empty
|
||||
empty {}
|
||||
|> insert "a" 0
|
||||
|> insert "b" 1
|
||||
|> insert "c" 2
|
||||
|
@ -815,7 +815,7 @@ expect
|
|||
&& (get dict "h" == Ok 7)
|
||||
|
||||
expect
|
||||
empty
|
||||
empty {}
|
||||
|> insert "Some" "Value"
|
||||
|> remove "Some"
|
||||
|> len
|
||||
|
@ -823,7 +823,7 @@ expect
|
|||
|
||||
# Makes sure a Dict with Nat keys works
|
||||
expect
|
||||
empty
|
||||
empty {}
|
||||
|> insert 7nat "Testing"
|
||||
|> get 7
|
||||
|> Bool.isEq (Ok "Testing")
|
||||
|
|
|
@ -43,9 +43,9 @@ isEq = \xs, ys ->
|
|||
else
|
||||
Break Bool.false
|
||||
|
||||
## An empty set.
|
||||
empty : Set k | k has Hash & Eq
|
||||
empty = @Set Dict.empty
|
||||
## Creates a new empty set.
|
||||
empty : {} -> Set k | k has Hash & Eq
|
||||
empty = \{} -> @Set (Dict.empty {})
|
||||
|
||||
single : k -> Set k | k has Hash & Eq
|
||||
single = \key ->
|
||||
|
@ -58,14 +58,14 @@ insert = \@Set dict, key ->
|
|||
# Inserting a duplicate key has no effect.
|
||||
expect
|
||||
actual =
|
||||
empty
|
||||
empty {}
|
||||
|> insert "foo"
|
||||
|> insert "bar"
|
||||
|> insert "foo"
|
||||
|> insert "baz"
|
||||
|
||||
expected =
|
||||
empty
|
||||
empty {}
|
||||
|> insert "foo"
|
||||
|> insert "bar"
|
||||
|> insert "baz"
|
||||
|
@ -79,7 +79,7 @@ len = \@Set dict ->
|
|||
# Inserting a duplicate key has no effect on length.
|
||||
expect
|
||||
actual =
|
||||
empty
|
||||
empty {}
|
||||
|> insert "foo"
|
||||
|> insert "bar"
|
||||
|> insert "foo"
|
||||
|
|
|
@ -3833,13 +3833,13 @@ fn is_generalizable_expr(mut expr: &Expr) -> bool {
|
|||
| RunLowLevel { .. }
|
||||
| ForeignCall { .. }
|
||||
| EmptyRecord
|
||||
| Expr::Record { .. }
|
||||
=> {
|
||||
return false
|
||||
}
|
||||
// TODO(weakening)
|
||||
Var(_, _)
|
||||
| AbilityMember(_, _, _)
|
||||
| Expr::Record { .. }
|
||||
| Crash { .. }
|
||||
| Access { .. }
|
||||
| Accessor(_)
|
||||
|
|
|
@ -8476,10 +8476,10 @@ mod solve_expr {
|
|||
|
||||
main =
|
||||
s1 : Set U8
|
||||
s1 = Set.empty
|
||||
s1 = Set.empty {}
|
||||
|
||||
s2 : Set Str
|
||||
s2 = Set.empty
|
||||
s2 = Set.empty {}
|
||||
|
||||
Bool.isEq s1 s1 && Bool.isEq s2 s2
|
||||
# ^^^^^^^^^ ^^^^^^^^^
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
procedure Dict.1 ():
|
||||
let Dict.520 : List {[], []} = Array [];
|
||||
let Dict.527 : U64 = 0i64;
|
||||
let Dict.528 : U64 = 8i64;
|
||||
let Dict.521 : List U64 = CallByName List.11 Dict.527 Dict.528;
|
||||
let Dict.524 : I8 = CallByName Dict.34;
|
||||
let Dict.525 : U64 = 8i64;
|
||||
let Dict.522 : List I8 = CallByName List.11 Dict.524 Dict.525;
|
||||
let Dict.523 : U64 = 0i64;
|
||||
let Dict.519 : {List {[], []}, List U64, List I8, U64} = Struct {Dict.520, Dict.521, Dict.522, Dict.523};
|
||||
ret Dict.519;
|
||||
procedure Dict.1 (Dict.518):
|
||||
let Dict.521 : List {[], []} = Array [];
|
||||
let Dict.528 : U64 = 0i64;
|
||||
let Dict.529 : U64 = 8i64;
|
||||
let Dict.522 : List U64 = CallByName List.11 Dict.528 Dict.529;
|
||||
let Dict.525 : I8 = CallByName Dict.34;
|
||||
let Dict.526 : U64 = 8i64;
|
||||
let Dict.523 : List I8 = CallByName List.11 Dict.525 Dict.526;
|
||||
let Dict.524 : U64 = 0i64;
|
||||
let Dict.520 : {List {[], []}, List U64, List I8, U64} = Struct {Dict.521, Dict.522, Dict.523, Dict.524};
|
||||
ret Dict.520;
|
||||
|
||||
procedure Dict.34 ():
|
||||
let Dict.526 : I8 = -128i64;
|
||||
ret Dict.526;
|
||||
let Dict.527 : I8 = -128i64;
|
||||
ret Dict.527;
|
||||
|
||||
procedure Dict.4 (Dict.507):
|
||||
let Dict.85 : U64 = StructAtIndex 3 Dict.507;
|
||||
|
@ -82,6 +82,7 @@ procedure Num.24 (#Attr.2, #Attr.3):
|
|||
ret Num.259;
|
||||
|
||||
procedure Test.0 ():
|
||||
let Test.2 : {List {[], []}, List U64, List I8, U64} = CallByName Dict.1;
|
||||
let Test.3 : {} = Struct {};
|
||||
let Test.2 : {List {[], []}, List U64, List I8, U64} = CallByName Dict.1 Test.3;
|
||||
let Test.1 : U64 = CallByName Dict.4 Test.2;
|
||||
ret Test.1;
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
procedure Test.1 ():
|
||||
let Test.7 : U8 = 1i64;
|
||||
let Test.8 : U8 = 2i64;
|
||||
let Test.6 : {U8, U8} = Struct {Test.7, Test.8};
|
||||
ret Test.6;
|
||||
|
||||
procedure Test.0 ():
|
||||
let Test.9 : {U8, U8} = CallByName Test.1;
|
||||
let Test.3 : U8 = StructAtIndex 0 Test.9;
|
||||
let Test.5 : {U8, U8} = CallByName Test.1;
|
||||
let Test.4 : U8 = StructAtIndex 1 Test.5;
|
||||
let Test.2 : List U8 = Array [Test.3, Test.4];
|
||||
ret Test.2;
|
|
@ -1,19 +0,0 @@
|
|||
procedure Test.1 ():
|
||||
let Test.11 : I64 = 2i64;
|
||||
let Test.12 : U8 = 1i64;
|
||||
let Test.10 : {I64, U8} = Struct {Test.11, Test.12};
|
||||
ret Test.10;
|
||||
|
||||
procedure Test.1 ():
|
||||
let Test.7 : I64 = 1i64;
|
||||
let Test.8 : U8 = 2i64;
|
||||
let Test.6 : {I64, U8} = Struct {Test.7, Test.8};
|
||||
ret Test.6;
|
||||
|
||||
procedure Test.0 ():
|
||||
let Test.9 : {I64, U8} = CallByName Test.1;
|
||||
let Test.3 : U8 = StructAtIndex 1 Test.9;
|
||||
let Test.5 : {I64, U8} = CallByName Test.1;
|
||||
let Test.4 : U8 = StructAtIndex 1 Test.5;
|
||||
let Test.2 : List U8 = Array [Test.3, Test.4];
|
||||
ret Test.2;
|
|
@ -385,7 +385,7 @@ fn when_on_two_values() {
|
|||
#[mono_test]
|
||||
fn dict() {
|
||||
r#"
|
||||
Dict.len Dict.empty
|
||||
Dict.len (Dict.empty {})
|
||||
"#
|
||||
}
|
||||
|
||||
|
@ -1273,7 +1273,7 @@ fn aliased_polymorphic_closure() {
|
|||
}
|
||||
|
||||
#[mono_test]
|
||||
fn issue_2535_polymorphic_fields_referenced_in_list() {
|
||||
fn issue_2535_let_weakened_fields_referenced_in_list() {
|
||||
indoc!(
|
||||
r#"
|
||||
app "test" provides [nums] to "./platform"
|
||||
|
|
|
@ -4777,7 +4777,7 @@ Tab characters are not allowed."###,
|
|||
app "dict" imports [ Dict ] provides [main] to "./platform"
|
||||
|
||||
myDict : Dict.Dict Num.I64 Str
|
||||
myDict = Dict.insert Dict.empty "foo" 42
|
||||
myDict = Dict.insert (Dict.empty {}) "foo" 42
|
||||
|
||||
main = myDict
|
||||
"#
|
||||
|
@ -4788,8 +4788,8 @@ Tab characters are not allowed."###,
|
|||
Something is off with the body of the `myDict` definition:
|
||||
|
||||
3│ myDict : Dict.Dict Num.I64 Str
|
||||
4│ myDict = Dict.insert Dict.empty "foo" 42
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
4│ myDict = Dict.insert (Dict.empty {}) "foo" 42
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This `insert` call produces:
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue