Skip to content

Commit

Permalink
Preserve collection metadata in basilisp.walk/walk (#1124)
Browse files Browse the repository at this point in the history
Fixes #1123
  • Loading branch information
chrisrink10 authored Nov 12, 2024
1 parent 20ad65b commit 2fe510b
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 9 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Fixed
* Fix a bug where `basilisp test` command fails due to an invalid `argparse` configuration (#1119)
* Fix a bug where `basilisp.walk/walk` (and any functions that depend on it) did not preserve collection metadata (#1123)
* Fix a bug where the private `postwalk` implementation in the reader did not preserve collection metadata (#1123)

## [v0.3.1]
### Added
Expand Down
20 changes: 16 additions & 4 deletions src/basilisp/lang/reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -1116,22 +1116,34 @@ def _walk(form, _, outer_f):
@_walk.register(IPersistentList)
@_walk.register(ISeq)
def _walk_ipersistentlist(form: Union[IPersistentList, ISeq], inner_f, outer_f):
return outer_f(llist.list(map(inner_f, form)))
coll = llist.list(map(inner_f, form))
if isinstance(form, IMeta) and form.meta is not None:
coll = coll.with_meta(form.meta)
return outer_f(coll)


@_walk.register(IPersistentVector)
def _walk_ipersistentvector(form: IPersistentVector, inner_f, outer_f):
return outer_f(vec.vector(map(inner_f, form)))
coll = vec.vector(map(inner_f, form))
if isinstance(form, IMeta) and form.meta is not None:
coll = coll.with_meta(form.meta)
return outer_f(coll)


@_walk.register(IPersistentMap)
def _walk_ipersistentmap(form: IPersistentMap, inner_f, outer_f):
return outer_f(lmap.hash_map(*chain.from_iterable(map(inner_f, form.seq() or ()))))
coll = lmap.hash_map(*chain.from_iterable(map(inner_f, form.seq() or ())))
if isinstance(form, IMeta) and form.meta is not None:
coll = coll.with_meta(form.meta)
return outer_f(coll)


@_walk.register(IPersistentSet)
def _walk_ipersistentset(form: IPersistentSet, inner_f, outer_f):
return outer_f(lset.set(map(inner_f, form)))
coll = lset.set(map(inner_f, form))
if isinstance(form, IMeta) and form.meta is not None:
coll = coll.with_meta(form.meta)
return outer_f(coll)


def _postwalk(f, form):
Expand Down
10 changes: 5 additions & 5 deletions src/basilisp/walk.lpy
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,27 @@
(extend-protocol IWalkable
basilisp.lang.interfaces/IPersistentList
(walk* [this inner outer]
(outer (apply list (map inner this))))
(outer (with-meta (apply list (map inner this)) (meta this))))

basilisp.lang.interfaces/IMapEntry
(walk* [this inner outer]
(outer (map-entry (inner (key this)) (inner (val this)))))

basilisp.lang.interfaces/ISeq
(walk* [this inner outer]
(outer (doall (map inner this))))
(outer (with-meta (doall (map inner this)) (meta this))))

basilisp.lang.interfaces/IPersistentVector
(walk* [this inner outer]
(outer (apply vector (map inner this))))
(outer (with-meta (apply vector (map inner this)) (meta this))))

basilisp.lang.interfaces/IPersistentMap
(walk* [this inner outer]
(outer (apply hash-map (mapcat inner this))))
(outer (with-meta (apply hash-map (mapcat inner this)) (meta this))))

basilisp.lang.interfaces/IPersistentSet
(walk* [this inner outer]
(outer (apply hash-set (map inner this))))
(outer (with-meta (apply hash-set (map inner this)) (meta this))))

basilisp.lang.interfaces/IRecord
(walk* [this inner outer]
Expand Down

0 comments on commit 2fe510b

Please sign in to comment.