144 lines
6.9 KiB
Scheme
144 lines
6.9 KiB
Scheme
(module search scheme/base
|
|
(require "struct.ss"
|
|
"basic.ss"
|
|
setup/main-collects
|
|
syntax/modcode)
|
|
|
|
(provide find-scheme-tag
|
|
intern-taglet)
|
|
|
|
(define module-info-cache (make-hash-table))
|
|
|
|
(define (module-path-index-rejoin mpi rel-to)
|
|
(let-values ([(name base) (module-path-index-split mpi)])
|
|
(cond
|
|
[(not name) rel-to]
|
|
[(not base) mpi]
|
|
[else
|
|
(module-path-index-join name
|
|
(module-path-index-rejoin base rel-to))])))
|
|
|
|
(define interned (make-hash-table 'equal 'weak))
|
|
|
|
(define (intern-taglet v)
|
|
(let ([v (if (list? v)
|
|
(map intern-taglet v)
|
|
v)])
|
|
(if (or (string? v)
|
|
(bytes? v)
|
|
(list? v))
|
|
(let ([b (hash-table-get interned v #f)])
|
|
(if b
|
|
(weak-box-value b)
|
|
(begin
|
|
(hash-table-put! interned v (make-weak-box v))
|
|
v)))
|
|
v)))
|
|
|
|
|
|
;; mode is #f, 'for-label, or 'for-run
|
|
(define (find-scheme-tag part ri stx/binding mode)
|
|
(let ([b (cond
|
|
[(identifier? stx/binding)
|
|
((case mode
|
|
[(for-label) identifier-label-binding]
|
|
[(for-syntax) identifier-transformer-binding]
|
|
[else identifier-binding])
|
|
stx/binding)]
|
|
[(and (list? stx/binding)
|
|
(= 6 (length stx/binding)))
|
|
stx/binding]
|
|
[else
|
|
(and (not (symbol? (car stx/binding)))
|
|
(let ([p (module-path-index-join
|
|
(main-collects-relative->path (car stx/binding))
|
|
#f)])
|
|
(list #f
|
|
(cadr stx/binding)
|
|
p
|
|
(cadr stx/binding)
|
|
#f
|
|
(if (= 2 (length stx/binding))
|
|
mode
|
|
(caddr stx/binding)))))])])
|
|
(and
|
|
(pair? b)
|
|
(let ([seen (make-hash-table)]
|
|
[search-key #f])
|
|
(let loop ([queue (list (list (caddr b) (cadddr b) (eq? mode (list-ref b 5))))]
|
|
[rqueue null])
|
|
(cond
|
|
[(null? queue)
|
|
(if (null? rqueue)
|
|
;; Not documented
|
|
#f
|
|
(loop (reverse rqueue) null))]
|
|
[else
|
|
(let ([mod (caar queue)]
|
|
[id (cadar queue)]
|
|
[here? (caddar queue)]
|
|
[queue (cdr queue)])
|
|
(let* ([rmp (module-path-index-resolve mod)]
|
|
[eb (and here?
|
|
(list (let ([p (resolved-module-path-name rmp)])
|
|
(if (path? p)
|
|
(intern-taglet (path->main-collects-relative p))
|
|
p))
|
|
id))])
|
|
(when (and eb
|
|
(not search-key))
|
|
(set! search-key eb))
|
|
(let ([v (and eb (resolve-search search-key part ri `(dep ,eb)))])
|
|
(or (and v
|
|
(let ([v (resolve-get/tentative part ri `(form ,eb))])
|
|
(or (and v `(form ,eb))
|
|
`(def ,eb))))
|
|
;; Maybe it's re-exported from this module...
|
|
;; Try a shortcut:
|
|
(if (eq? rmp (and (car b) (module-path-index-resolve (car b))))
|
|
;; Not defined through this path, so keep looking
|
|
(loop queue rqueue)
|
|
;; Check parents, if we can get the source:
|
|
(if (and (path? (resolved-module-path-name rmp))
|
|
(not (hash-table-get seen rmp #f)))
|
|
(let ([exports
|
|
(hash-table-get
|
|
module-info-cache
|
|
rmp
|
|
(lambda ()
|
|
(let-values ([(run-vals run-stxes
|
|
syntax-vals syntax-stxes
|
|
label-vals label-stxes)
|
|
(module-compiled-exports
|
|
(get-module-code (resolved-module-path-name rmp)))])
|
|
(let ([t (list (append run-vals run-stxes)
|
|
(append syntax-vals syntax-stxes)
|
|
(append label-vals label-stxes))])
|
|
(hash-table-put! module-info-cache rmp t)
|
|
t))))])
|
|
(hash-table-put! seen rmp #t)
|
|
(let ([a (assq id (list-ref exports
|
|
(if here?
|
|
0
|
|
(case mode
|
|
[(for-syntax) 1]
|
|
[(for-label) 2]
|
|
[else 0]))))])
|
|
(if a
|
|
(loop queue
|
|
(append (map (lambda (m)
|
|
(if (pair? m)
|
|
(list (module-path-index-rejoin (car m) mod)
|
|
(caddr m)
|
|
(or here?
|
|
(eq? mode (cadr m))))
|
|
(list (module-path-index-rejoin m mod)
|
|
id
|
|
here?)))
|
|
(cadr a))
|
|
rqueue))
|
|
(error 'find-scheme-tag
|
|
"dead end when looking for binding source: ~e"
|
|
id))))
|
|
;; Can't get the module source, so continue with queue:
|
|
(loop queue rqueue)))))))]))))))) |