(in-package :cl-table) (defstruct (iter-row (:include row)) "Iterator element" (id 0 :type fixnum) (children-vector #() :type (vector iter-row))) ;; We need vector of top rows and vector of all rows (to have integer -> row) ;; And we have to store it with the table or else we have independent vars ;; for a table (defstruct iter-table (all #() :type (vector iter-row)) (top #() :type (vector iter-row))) (defun make-iterator (table) "Returns array of iter-row" (let (res visited (res-len -1)) (declare (special visited)) (labels ((to-vector (l) (coerce (nreverse l) 'vector)) (visit-row (row) (declare (special visited)) (let* ((children (let (visited) (declare (special visited)) (map-table-row #'visit-row row) (to-vector visited))) (new-row (make-iter-row :parent (row-parent row) :table (row-table row) :children-vector children :children (row-children row) :id (incf res-len) :num (row-num row) :data (row-data row)))) (push new-row res) (push new-row visited)))) (map-table #'visit-row table) (make-iter-table :all (to-vector res) :top (to-vector visited))))) (defun aref* (array index) (when (< -1 index (array-dimension array 0)) (aref array index))) (defmethod path->row ((iter-table iter-table) path) (when path (path->row (aref* (iter-table-top iter-table) (car path)) (cdr path)))) (defmethod path->row ((iter-row iter-row) path) (if path (path->row (aref* (iter-row-children-vector iter-row) (car path)) (cdr path)) iter-row))