Skip to content

Commit

Permalink
Merge pull request #91 from skx/80-hash
Browse files Browse the repository at this point in the history
Correct the iteration of key/values of hashes
  • Loading branch information
skx authored Nov 11, 2023
2 parents fda4152 + 7775341 commit 8f86ab9
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 4 deletions.
4 changes: 4 additions & 0 deletions .github/build
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
# The basename of our binary
BASE="monkey"


# I don't even ..
go env -w GOFLAGS="-buildvcs=false"

#
# We build on multiple platforms/archs
#
Expand Down
8 changes: 6 additions & 2 deletions .github/run-tests.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
#!/bin/sh


# I don't even ..
go env -w GOFLAGS="-buildvcs=false"

# Install the lint-tool, and the shadow-tool
go get -u golang.org/x/lint/golint
go get -u golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow
go install golang.org/x/lint/golint@latest
go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow@latest

# At this point failures cause aborts
set -e
Expand Down
34 changes: 34 additions & 0 deletions evaluator/evaluator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ func testEval(input string) object.Object {
p := parser.New(l)
program := p.ParseProgram()
env := object.NewEnvironment()

ctx, cancel := context.WithTimeout(context.Background(), 5000*time.Millisecond)
defer cancel()
SetContext(ctx)

return Eval(program, env)
}

Expand Down Expand Up @@ -654,3 +659,32 @@ for ( true ) {
}

}

// Test90 tests hash-key iteration, which was reported in #90
func Test90(t *testing.T) {
input := `
a = { 1: "one", 2: "two", 3: "three" }
total = 0
foreach key in a {
total += key
}
return total;
`
count := 0

for count < 10 {

evaluated := testEval(input)
result, ok := evaluated.(*object.Integer)
if !ok {
t.Fatalf("Eval did't return number. got=%T(%+v)",
evaluated, evaluated)
}
if result.Value != 6 {
t.Fatalf("key iteration %d resulted in %d != 6", count, result)
}

count++
}

}
30 changes: 28 additions & 2 deletions object/object_hash.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,36 @@ func (h *Hash) Next() (Object, Object, bool) {
if h.offset < len(h.Pairs) {
idx := 0

for _, pair := range h.Pairs {
//
// Bug: #90
//
// Using "range" to iterate over a map will
// return the values in a random order.
//
// We need to sort the keys, that will give us
// a standard order.
//
// x -> sorted keys
// y -> key/val map, for simplicity
//
x := []Object{}
y := make(map[Object]Object)
// x is now the keys
for _, ent := range h.Pairs {
x = append(x, ent.Key)
y[ent.Key] = ent.Value
}

// sort the keys
sort.Slice(x, func(i, j int) bool {
return x[i].Inspect() < x[j].Inspect()
})

// Now range over the keys
for _, key := range x {
if h.offset == idx {
h.offset++
return pair.Key, pair.Value, true
return key, y[key], true
}
idx++
}
Expand Down

0 comments on commit 8f86ab9

Please sign in to comment.