Skip to content

Commit 2e6a695

Browse files
committed
split hash deep transform recursion helpers
1 parent 8c96102 commit 2e6a695

3 files changed

Lines changed: 72 additions & 66 deletions

File tree

docs/architecture.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ Key files:
3131
- `vibes/execution_state.go` (runtime call/env/module/receiver stack helpers)
3232
- `vibes/execution_members.go` (member dispatch for runtime values)
3333
- `vibes/execution_members_hash.go` (hash/object member behavior)
34+
- `vibes/execution_members_hash_deep.go` (`hash.deep_transform_keys` recursion/cycle handling)
3435
- `vibes/execution_members_string.go` (string member dispatch)
3536
- `vibes/execution_members_string_query.go` (string query/search member methods)
3637
- `vibes/execution_members_string_transforms.go` (string transform/normalization member methods)

vibes/execution_members_hash.go

Lines changed: 0 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package vibes
33
import (
44
"fmt"
55
"maps"
6-
"reflect"
76
"sort"
87
)
98

@@ -344,68 +343,3 @@ func sortedHashKeys(entries map[string]Value) []string {
344343
sort.Strings(keys)
345344
return keys
346345
}
347-
348-
func deepTransformKeys(exec *Execution, value Value, block Value) (Value, error) {
349-
return deepTransformKeysWithState(exec, value, block, &deepTransformState{
350-
seenHashes: make(map[uintptr]struct{}),
351-
seenArrays: make(map[uintptr]struct{}),
352-
})
353-
}
354-
355-
type deepTransformState struct {
356-
seenHashes map[uintptr]struct{}
357-
seenArrays map[uintptr]struct{}
358-
}
359-
360-
func deepTransformKeysWithState(exec *Execution, value Value, block Value, state *deepTransformState) (Value, error) {
361-
switch value.Kind() {
362-
case KindHash, KindObject:
363-
entries := value.Hash()
364-
id := reflect.ValueOf(entries).Pointer()
365-
if id != 0 {
366-
if _, seen := state.seenHashes[id]; seen {
367-
return NewNil(), fmt.Errorf("hash.deep_transform_keys does not support cyclic structures")
368-
}
369-
state.seenHashes[id] = struct{}{}
370-
defer delete(state.seenHashes, id)
371-
}
372-
out := make(map[string]Value, len(entries))
373-
for _, key := range sortedHashKeys(entries) {
374-
nextKeyValue, err := exec.CallBlock(block, []Value{NewSymbol(key)})
375-
if err != nil {
376-
return NewNil(), err
377-
}
378-
nextKey, err := valueToHashKey(nextKeyValue)
379-
if err != nil {
380-
return NewNil(), fmt.Errorf("hash.deep_transform_keys block must return symbol or string")
381-
}
382-
nextValue, err := deepTransformKeysWithState(exec, entries[key], block, state)
383-
if err != nil {
384-
return NewNil(), err
385-
}
386-
out[nextKey] = nextValue
387-
}
388-
return NewHash(out), nil
389-
case KindArray:
390-
items := value.Array()
391-
id := reflect.ValueOf(items).Pointer()
392-
if id != 0 {
393-
if _, seen := state.seenArrays[id]; seen {
394-
return NewNil(), fmt.Errorf("hash.deep_transform_keys does not support cyclic structures")
395-
}
396-
state.seenArrays[id] = struct{}{}
397-
defer delete(state.seenArrays, id)
398-
}
399-
out := make([]Value, len(items))
400-
for i, item := range items {
401-
nextValue, err := deepTransformKeysWithState(exec, item, block, state)
402-
if err != nil {
403-
return NewNil(), err
404-
}
405-
out[i] = nextValue
406-
}
407-
return NewArray(out), nil
408-
default:
409-
return value, nil
410-
}
411-
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package vibes
2+
3+
import (
4+
"fmt"
5+
"reflect"
6+
)
7+
8+
func deepTransformKeys(exec *Execution, value Value, block Value) (Value, error) {
9+
return deepTransformKeysWithState(exec, value, block, &deepTransformState{
10+
seenHashes: make(map[uintptr]struct{}),
11+
seenArrays: make(map[uintptr]struct{}),
12+
})
13+
}
14+
15+
type deepTransformState struct {
16+
seenHashes map[uintptr]struct{}
17+
seenArrays map[uintptr]struct{}
18+
}
19+
20+
func deepTransformKeysWithState(exec *Execution, value Value, block Value, state *deepTransformState) (Value, error) {
21+
switch value.Kind() {
22+
case KindHash, KindObject:
23+
entries := value.Hash()
24+
id := reflect.ValueOf(entries).Pointer()
25+
if id != 0 {
26+
if _, seen := state.seenHashes[id]; seen {
27+
return NewNil(), fmt.Errorf("hash.deep_transform_keys does not support cyclic structures")
28+
}
29+
state.seenHashes[id] = struct{}{}
30+
defer delete(state.seenHashes, id)
31+
}
32+
out := make(map[string]Value, len(entries))
33+
for _, key := range sortedHashKeys(entries) {
34+
nextKeyValue, err := exec.CallBlock(block, []Value{NewSymbol(key)})
35+
if err != nil {
36+
return NewNil(), err
37+
}
38+
nextKey, err := valueToHashKey(nextKeyValue)
39+
if err != nil {
40+
return NewNil(), fmt.Errorf("hash.deep_transform_keys block must return symbol or string")
41+
}
42+
nextValue, err := deepTransformKeysWithState(exec, entries[key], block, state)
43+
if err != nil {
44+
return NewNil(), err
45+
}
46+
out[nextKey] = nextValue
47+
}
48+
return NewHash(out), nil
49+
case KindArray:
50+
items := value.Array()
51+
id := reflect.ValueOf(items).Pointer()
52+
if id != 0 {
53+
if _, seen := state.seenArrays[id]; seen {
54+
return NewNil(), fmt.Errorf("hash.deep_transform_keys does not support cyclic structures")
55+
}
56+
state.seenArrays[id] = struct{}{}
57+
defer delete(state.seenArrays, id)
58+
}
59+
out := make([]Value, len(items))
60+
for i, item := range items {
61+
nextValue, err := deepTransformKeysWithState(exec, item, block, state)
62+
if err != nil {
63+
return NewNil(), err
64+
}
65+
out[i] = nextValue
66+
}
67+
return NewArray(out), nil
68+
default:
69+
return value, nil
70+
}
71+
}

0 commit comments

Comments
 (0)