Skip to content

Latest commit

 

History

History
89 lines (74 loc) · 2.75 KB

0044-hu.dwim.walker.org

File metadata and controls

89 lines (74 loc) · 2.75 KB

hu.dwim.walker

Today I want to review an utility library, useful for writing macroses: hu.dwim.walker. This library provides a code walker which returns an AST representation of the walked form.

Resulted AST contains important semantic information which will be hard to extract. For example, it is possible to distinguish lexical variables and free variables:

POFTHEDAY> (hu.dwim.walker:walk-form
            '(let (a
                   (b 1))
              (list a b c)))
WARNING: Reference to unknown variable C in C.
#<HU.DWIM.WALKER:LET-FORM
(#<FREE-APPLICATION-FORM
 !(LIST #<WALKED-LEXICAL-VARIABLE-REFERENCE-FORM
        !A {1002754213}>
        #<WALKED-LEXICAL-VARIABLE-REFERENCE-FORM
        !B {10027543D3}>
        #<FREE-VARIABLE-REFERENCE-FORM !C {1002755023}>)
 {1002754063}>)
{1002753373}>

POFTHEDAY> (hu.dwim.walker:collect-variable-references
            *
            :type 'hu.dwim.walker:free-variable-reference-form)
(#<HU.DWIM.WALKER:FREE-VARIABLE-REFERENCE-FORM !C {1002755023}>)

POFTHEDAY> (hu.dwim.walker:unwalk-form ***)
(LET ((A NIL) (B 1))
  (LIST A B C))
  

hu.dwim.walker also provides functions to rewrite AST and to serialize it back into the s-exp form:

POFTHEDAY> (defparameter *ast*
             (hu.dwim.walker:walk-form
              '(let (a
                     (b 1))
                (list a b c))))

POFTHEDAY> (hu.dwim.walker:rewrite-ast
            *ast*
            ;; This is a visitor function which can
            ;; replace some parts of the AST:
            (lambda (parent field form)
              (typecase form
                (hu.dwim.walker:free-variable-reference-form
                 ;; In real code, we'll need to create
                 ;; a new piece of AST here:
                 (hu.dwim.walker:walk-form
                  '(some-replacement)))
                (t form))))
#<HU.DWIM.WALKER:LET-FORM
  (#<FREE-APPLICATION-FORM
   !(LIST #<WALKED-LEXICAL-VARIABLE-REFERENCE-FORM !A {100158A5B3}>
          #<WALKED-LEXICAL-VARIABLE-REFERENCE-FORM !B {100158A773}>
          #<FREE-APPLICATION-FORM !(SOME-REPLACEMENT ) {1001B94063}>)
   {100158A403}>)
{1001589973}>

POFTHEDAY> (hu.dwim.walker:unwalk-form *)
(LET ((A NIL) (B 1))
  (LIST A B (SOME-REPLACEMENT)))

I’ve found only one real usage of this library not in hu.dwim.* ecosystem - in arrow-macros library.

Probably, there are more interesting things in this system, but a complete absence of documentation and examples makes it hard to understand how to use it :(