dyoo / whalesong

Whalesong: Racket to JavaScript compiler
http://hashcollision.org/whalesong
250 stars 30 forks source link

require tracking isn't working properly with regards to (for-template ...) #55

Open dyoo opened 13 years ago

dyoo commented 13 years ago

I ran across a strange problem while getting the cs019 support code running under Whalesong. One of the syntax transformers produces the form check-not-undefined, which is defined in teach-runtime.rkt, and require-for-templated by teach.rkt. However, when I compile the program, the require dependency graph I'm generating doesn't include teach-runtime, even though it's required to run the code at runtime!

I'm working around this by having cs019-pre-base require the "teach-runtime.rkt" library explicitly, but this is wrong. I don't know yet what's wrong.

dyoo commented 12 years ago

Issue identified. I need to really use phase information to do the proper requires. I'm currently ignoring all modules at phase level <> 0. What I really need to do is maintain a record of a module and all its requires, and instantiate when the combined phase is 0. So modules that aren't used at runtime still need a record in the compilation output so that I can implement this behavior.

I can use the following code to determine runtime dependencies.

#lang racket/base
(require compiler/demodularizer/mpi
         syntax/modcode
         racket/path
         racket/pretty)

(read-accept-reader #t)
(current-namespace (make-base-namespace))

;; Produce a list of the phase-0 dependencies of a module.
(define (phase-0-dependencies a-mod-path)
  (define ht (make-hash))

  (define marked-for-visit? (make-hash))
  (parameterize ([MODULE-PATHS (make-hash)])

    (let recur ([a-mod-path a-mod-path]
                [current-phase 0])
      (define modcode (get-module-code a-mod-path))
      (define imports (module-compiled-imports modcode))
      (for ([phase+mpis (in-list imports)]
            #:when (number? (car phase+mpis)))
           (define phase (+ (car phase+mpis) current-phase))
           (define paths
             (parameterize ([current-module-path a-mod-path])
               (for/list ([mpi (in-list (cdr phase+mpis))])
                         (mpi->path! mpi))))
           (when (= phase 0)
             (for ([p paths]) (hash-set! ht p #t)))
           (for ([p (in-list paths)])
                (when (and (path? p) (not (hash-has-key? marked-for-visit? (list p phase))))
                  (hash-set! marked-for-visit? (list p phase) #t)
                  (recur p phase))))))

  ;; Return all the paths we've seen.
  (for/list ([p (in-hash-keys ht)])
     p))

(pretty-print
 (phase-0-dependencies (normalize-path (build-path "temp.rkt"))))