Skip to content

Commit 652f86e

Browse files
committed
fix: sorted dictionary keys, entries and values
1 parent 3ad17bd commit 652f86e

File tree

2 files changed

+30
-6
lines changed

2 files changed

+30
-6
lines changed

runtime/prelude-dict.go

+21-4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package runtime
22

33
import (
44
"fmt"
5+
"sort"
56
"strings"
67
)
78

@@ -105,7 +106,8 @@ func (rv PreludeDict) Lookup(member string) (Evaluatable, *RuntimeError) {
105106
})), nil
106107
case "entries":
107108
pairs := make([]RuntimeValue, 0, len(rv.dict))
108-
for k, v := range rv.dict {
109+
for _, k := range rv.orderedKeys() {
110+
v := rv.dict[k]
109111
pair, err := rv.context.environment.MakePair(NewConstantRuntimeValue(k), v)
110112
if err != nil {
111113
return nil, err
@@ -116,15 +118,15 @@ func (rv PreludeDict) Lookup(member string) (Evaluatable, *RuntimeError) {
116118
return NewConstantRuntimeValue(dataList), err
117119
case "keys":
118120
keys := make([]RuntimeValue, 0, len(rv.dict))
119-
for k := range rv.dict {
121+
for _, k := range rv.orderedKeys() {
120122
keys = append(keys, k)
121123
}
122124
dataList, err := rv.context.environment.MakeEagerList(keys)
123125
return NewConstantRuntimeValue(dataList), err
124126
case "values":
125127
values := make([]Evaluatable, 0, len(rv.dict))
126-
for _, v := range rv.dict {
127-
values = append(values, v)
128+
for _, k := range rv.orderedKeys() {
129+
values = append(values, rv.dict[k])
128130
}
129131
dataList, err := rv.context.environment.MakeList(values)
130132
return NewConstantRuntimeValue(dataList), err
@@ -136,3 +138,18 @@ func (rv PreludeDict) Lookup(member string) (Evaluatable, *RuntimeError) {
136138
func (rv PreludeDict) copy() PreludeDict {
137139
return MakePreludeDict(rv.context, rv.dict)
138140
}
141+
142+
func (rv PreludeDict) orderedKeys() []PreludeString {
143+
keys := make([]PreludeString, 0, len(rv.dict))
144+
for k := range rv.dict {
145+
keys = append(keys, k)
146+
}
147+
sort.Sort(preludeStringSlice(keys))
148+
return keys
149+
}
150+
151+
type preludeStringSlice []PreludeString
152+
153+
func (x preludeStringSlice) Len() int { return len(x) }
154+
func (x preludeStringSlice) Less(i, j int) bool { return x[i] < x[j] }
155+
func (x preludeStringSlice) Swap(i, j int) { x[i], x[j] = x[j], x[i] }

stdlib/stdlib-tests.lithia

+9-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import tests {
66
import tests.tests_t
77
import os
88
import lists
9+
import strings
910

1011
test "any in enums matches all types", { fail =>
1112
enum AnyEnum {
@@ -120,7 +121,10 @@ test "dict keys", { fail =>
120121
"id": 123
121122
]
122123
unless user.keys == ["username", "id"] ||
123-
user.keys == ["id", "username"], fail "must list all keys"
124+
user.keys == ["id", "username"], fail (strings.join " ", [
125+
"must list all keys, got",
126+
user.keys
127+
])
124128
}
125129

126130
test "dict values", { fail =>
@@ -129,7 +133,10 @@ test "dict values", { fail =>
129133
"id": 123
130134
]
131135
unless user.values == ["vknabel", 123] ||
132-
user.values == [123, "vknabel"], fail "must list all values"
136+
user.values == [123, "vknabel"], fail (strings.join " ", [
137+
"must list all values, got",
138+
user.values
139+
])
133140
}
134141

135142
func main { =>

0 commit comments

Comments
 (0)