hy.contrib.walk: New contrib module for walking the Hy AST
The hy.contrib.walk module provides a few functions to walk the Hy AST, and potentially transform it along the way. The main entry point is (walk), which takes two functions and a form as arguments, and applies the first (inner) function to each element of the form, building up a data structure of the same type as the original. Then applies outer (the second function) to the result. Two convenience functions are provided: (postwalk) and (prewalk), which do a depth-first, post/pre-order traversal of the form. Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
This commit is contained in:
parent
4b54e3c748
commit
817b4688d8
47
hy/contrib/walk.hy
Normal file
47
hy/contrib/walk.hy
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
;;; Hy AST walker
|
||||||
|
;;
|
||||||
|
;; Copyright (c) 2014 Gergely Nagy <algernon@madhouse-project.org>
|
||||||
|
;;
|
||||||
|
;; Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
;; copy of this software and associated documentation files (the "Software"),
|
||||||
|
;; to deal in the Software without restriction, including without limitation
|
||||||
|
;; the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
;; and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
;; Software is furnished to do so, subject to the following conditions:
|
||||||
|
;;
|
||||||
|
;; The above copyright notice and this permission notice shall be included in
|
||||||
|
;; all copies or substantial portions of the Software.
|
||||||
|
;;
|
||||||
|
;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
;; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
;; DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
(import [hy [HyExpression HyDict]]
|
||||||
|
[functools [partial]])
|
||||||
|
|
||||||
|
(defn walk [inner outer form]
|
||||||
|
"Traverses form, an arbitrary data structure. Applies inner to each
|
||||||
|
element of form, building up a data structure of the same type.
|
||||||
|
Applies outer to the result."
|
||||||
|
(cond
|
||||||
|
[(instance? HyExpression form)
|
||||||
|
(outer (HyExpression (map inner form)))]
|
||||||
|
[(instance? HyDict form)
|
||||||
|
(HyDict (outer (HyExpression (map inner form))))]
|
||||||
|
[(instance? list form)
|
||||||
|
((type form) (outer (HyExpression (map inner form))))]
|
||||||
|
[true (outer form)]))
|
||||||
|
|
||||||
|
(defn postwalk [f form]
|
||||||
|
"Performs depth-first, post-order traversal of form. Calls f on each
|
||||||
|
sub-form, uses f's return value in place of the original."
|
||||||
|
(walk (partial postwalk f) f form))
|
||||||
|
|
||||||
|
(defn prewalk [f form]
|
||||||
|
"Performs depth-first, pre-order traversal of form. Calls f on each
|
||||||
|
sub-form, uses f's return value in place of the original."
|
||||||
|
(walk (partial prewalk f) identity (f form)))
|
@ -17,3 +17,4 @@ from .native_tests.with_test import * # noqa
|
|||||||
from .native_tests.contrib.anaphoric import * # noqa
|
from .native_tests.contrib.anaphoric import * # noqa
|
||||||
from .native_tests.contrib.loop import * # noqa
|
from .native_tests.contrib.loop import * # noqa
|
||||||
from .native_tests.contrib.meth import * # noqa
|
from .native_tests.contrib.meth import * # noqa
|
||||||
|
from .native_tests.contrib.walk import * # noqa
|
||||||
|
24
tests/native_tests/contrib/walk.hy
Normal file
24
tests/native_tests/contrib/walk.hy
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
(import [hy.contrib.walk [*]])
|
||||||
|
|
||||||
|
(def walk-form '(print {"foo" "bar"
|
||||||
|
"array" [1 2 3 [4]]
|
||||||
|
"something" (+ 1 2 3 4)
|
||||||
|
"quoted?" '(foo)}))
|
||||||
|
|
||||||
|
(defn collector [acc x]
|
||||||
|
(.append acc x)
|
||||||
|
nil)
|
||||||
|
|
||||||
|
(defn test-walk-identity []
|
||||||
|
(assert (= (walk identity identity walk-form)
|
||||||
|
walk-form)))
|
||||||
|
|
||||||
|
(defn test-walk []
|
||||||
|
(let [[acc '()]]
|
||||||
|
(assert (= (walk (partial collector acc) identity walk-form)
|
||||||
|
[nil nil]))
|
||||||
|
(assert (= acc walk-form)))
|
||||||
|
(let [[acc []]]
|
||||||
|
(assert (= (walk identity (partial collector acc) walk-form)
|
||||||
|
nil))
|
||||||
|
(assert (= acc [walk-form]))))
|
Loading…
Reference in New Issue
Block a user