;; traverse.stk -- traversal methods for object graphs & visitors (require "visitor") (require "path") (define-method traverse ((path ) obj . visitors) (set! visitors (map (lambda (v) (set-path! v path)) visitors)) (traverse-obj path obj visitors)) ;; object traversal (define-method traverse-obj ((path ) obj (visitors )) ;; Since only visitors can add new visitors, there's no point in ;; continuing if there are no visitors. (unless (null? visitors) (set! visitors (before visitors obj)) ; might add visitors (unless (stop-at? path obj) (let ((visitors (continuing visitors path obj))) ; might subtract visitors (unless (null? visitors) (for-each (lambda (edge) (let ((visitors ; might subtract visitors (continuing visitors path edge))) (unless (or (null? visitors) (bypass? path edge)) (traverse-edge path obj edge [target edge] visitors)))) [edges obj])))) (after visitors obj))) ;; Return a new list of visitors that want to continue along path from ;; obj or along edge. (define-method continuing ((visitors ) (path ) obj-or-edge) '()) (define-method continuing ((visitors ) (path ) obj-or-edge) (let* ((v (car visitors)) (p [path-dir v])) (if (continue? p obj-or-edge) (cons v (continuing (cdr visitors) path obj-or-edge)) (continuing (cdr visitors) path obj-or-edge)))) ;; edge traversal (define-method traverse-edge ((p ) source (e ) target (visitors )) ;; Since only visitors can add new visitors, there's no point in ;; continuing if there are no visitors. (unless (null? visitors) (set! visitors (before visitors source e target)) (traverse-obj p target visitors) (after visitors source e target))) (provide "traverse")