next: vectorize, repeat

main
Matthew Butterick 4 years ago
parent cbb5dbbb47
commit ad20e50294

@ -1,11 +1,6 @@
#lang debug racket
(provide (all-defined-out))
(define current-doc (make-parameter #false))
(define current-section (make-parameter #false))
(define current-page (make-parameter #false))
(define current-column (make-parameter #false))
(define current-block (make-parameter #false))
(define current-line (make-parameter #false))
(define current-pdf (make-parameter #false))
(define current-line-wrap (make-parameter #f)) ; because kp is slow and maybe we want to disable for "draft" mode

@ -2,10 +2,16 @@
(require quad/base "struct.rkt" "param.rkt")
(provide (all-defined-out))
(define (make-linear-index q)
;; we want to construct a query index once with reversed variant
;; so we don't have to keep generating it
(struct query-index (forward reverse) #:transparent)
(define (make-query-index q)
(define qs (let loop ([q q])
(cons q (append* (for/list ([elem (in-list (quad-elems q))]
#:when (quad? elem))
(make-linear-index elem)))))
(loop elem))))))
(query-index qs (reverse qs)))
(define (string->key str #:this [this? #false])
(match str
@ -23,36 +29,34 @@
'block block-quad?
'line line-quad?))
(define quad-params (hasheq 'doc current-doc
'section current-section
'page current-page
'column current-column
'block current-block
'line current-line))
(define (parse-query str)
(for/list ([piece (in-list (string-split str ":"))])
(match (regexp-match #px"^(.*)\\[(.*?)\\]$" piece)
[#false (cons (string->key piece) #false)]
[(list _ name "this") (cons (let ([quad-param-val ((hash-ref quad-params (string->key name)))])
(λ (q) (eq? q quad-param-val))) 1)]
[(list _ name arg) (cons (hash-ref preds (string->key name)) (or (string->number arg)
(string->symbol arg)))])))
(define (query quad-or-index query-str)
(for/fold ([qs (match quad-or-index
[(? quad? q) (make-linear-index q)]
[idx idx])]
(define (query quad-or-index query-str [querying-q #false])
(define qi (match quad-or-index
[(? quad? q) (make-query-index q)]
[idx idx]))
(for/fold ([qs (query-index-forward qi)]
#:result (and qs (car qs)))
([query-piece (in-list (parse-query query-str))])
(match-define (cons pred count) query-piece)
(match query-piece
[(cons pred 'this)
;; resolve `this` by finding the querying quad, and searching backward
(define this-thing (findf pred (memq querying-q (query-index-reverse qi))))
;; once we have this-thing, locate it in the forward index and keep going
(memq this-thing (query-index-forward qi))]
[(cons pred count)
(let loop ([qs qs][seen 0])
(define maybe-tail (memf pred qs))
(and maybe-tail
(let ([seen (add1 seen)])
(cond
[(= seen count) maybe-tail]
[else (loop (cdr maybe-tail) seen)]))))))
[else (loop (cdr maybe-tail) seen)]))))])))
(module+ test
(require rackunit)

@ -401,8 +401,12 @@
(cons new-section sections-acc)])
(section-pages-used (+ (section-pages-used) (length section-pages))))))
(define (wants-parent? x) (and (quad? x) (quad-ref x :anchor-parent)))
(define (resolve-parents doc)
(define (wants-parent? x) (and (quad? x) (quad-ref x :anchor-parent)))
;; we make our index now so that it includes the quads that want parents
;; so if we come across `this` as a subscript, we can resolve it
;; by reference to the parent-wanting quad
(define qi (make-query-index doc))
;; extract the quads that want parents
(define parent-wanter-acc null)
(let loop ([x doc])
@ -415,11 +419,12 @@
(map loop others)]
[_ x]))
;; then put them where they want to go
(define linearized-qs (make-linear-index doc))
;; if the query has no result, then the quad doesn't get replaced (ie. disappears)
;; which seems like the right outcome.
(for* ([wp (in-list parent-wanter-acc)]
[query-str (in-value (quad-ref wp :anchor-parent))]
#:when query-str
[parent (in-value (query linearized-qs query-str))]
[parent (in-value (query qi query-str wp))]
#:when parent)
(quad-update! parent [elems (append (quad-elems parent) (list wp))]))
doc)

Loading…
Cancel
Save