#lang typed/racket/base
(require "../compiler/compiler.rkt"
"../compiler/il-structs.rkt"
"../compiler/lexical-structs.rkt"
"../compiler/compiler-structs.rkt"
"../compiler/expression-structs.rkt"
"../compiler/kernel-primitives.rkt"
"../parameters.rkt"
"../sets.rkt"
"get-dependencies.rkt"
"make-structs.rkt"
racket/list
racket/match
"../promise.rkt")
(require/typed "../logger.rkt"
[log-debug (String -> Void)])
(require/typed "../parser/parse-bytecode.rkt"
[parse-bytecode ((U Path Input-Port) -> Expression)])
(require/typed "../get-module-bytecode.rkt"
[get-module-bytecode ((U String Path Input-Port) -> Bytes)])
(provide make)
(: current-module-source-compiling-hook
(Parameterof (Source -> Source)))
(define current-module-source-compiling-hook
(make-parameter (lambda: ([s : Source]) s)))
(: get-ast-and-statements (Source -> (values (U False Expression)
(MyPromise (Listof Statement)))))
(define (get-ast-and-statements a-source)
(cond
[(StatementsSource? a-source)
(values #f (my-delay (StatementsSource-stmts a-source)))]
[(UninterpretedSource? a-source)
(values #f (my-delay '()))]
[(MainModuleSource? a-source)
(let-values ([(ast stmts)
(get-ast-and-statements (make-ModuleSource (MainModuleSource-path a-source)))])
(values ast
(my-delay
(let ([maybe-module-locator (find-module-locator ast)])
(cond
[(ModuleLocator? maybe-module-locator)
(append (my-force stmts)
(list (make-Perform
(make-AliasModuleAsMain!
maybe-module-locator))))]
[else
(my-force stmts)])))))]
[else
(let ([ast (get-ast a-source)])
(values ast
(my-delay
(define start-time (current-inexact-milliseconds))
(define compiled-code (compile ast 'val next-linkage/drop-multiple))
(define stop-time (current-inexact-milliseconds))
(fprintf (current-timing-port)
" compile ast: ~a milliseconds\n"
(- stop-time start-time))
compiled-code)))]))
(: get-ast ((U ModuleSource SexpSource) -> Expression))
(define (get-ast a-source)
(define start-time (current-inexact-milliseconds))
(: ast Expression)
(define ast (cond
[(ModuleSource? a-source)
(parse-bytecode (ModuleSource-path a-source))]
[(SexpSource? a-source)
(let ([source-code-op (open-output-bytes)])
(write (SexpSource-sexp a-source) source-code-op)
(parse-bytecode
(open-input-bytes
(get-module-bytecode
(open-input-bytes
(get-output-bytes source-code-op))))))]))
(define stop-time (current-inexact-milliseconds))
(fprintf (current-timing-port) " get-ast: ~a milliseconds\n" (- stop-time start-time))
ast)
(: find-module-locator ((U Expression False) -> (U False ModuleLocator)))
(define (find-module-locator exp)
(match exp
[(struct Top ((? Prefix?)
(struct Module (name
(and path (? ModuleLocator?))
prefix
requires
provides
code))))
path]
[else
#f]))
(: make ((Listof Source) Configuration -> Void))
(define (make sources config)
(parameterize ([current-seen-unimplemented-kernel-primitives
((inst new-seteq Symbol))])
(match config
[(struct Configuration (wrap-source
should-follow-children?
on-source
after-module-statements
after-last))
(: follow-dependencies ((Listof Source) -> Void))
(define (follow-dependencies sources)
(define visited ((inst make-hash Source Boolean)))
(: collect-new-dependencies
(Source (U False Expression) -> (Listof Source)))
(define (collect-new-dependencies this-source ast)
(cond
[(UninterpretedSource? this-source)
(UninterpretedSource-neighbors this-source)]
[else
(cond
[(eq? ast #f)
empty]
[(not (should-follow-children? this-source))
empty]
[else
(let* ([dependent-module-names (get-dependencies ast)]
[paths
(foldl (lambda: ([mp : ModuleLocator]
[acc : (Listof Source)])
(let ([rp [ModuleLocator-real-path mp]])
(cond
[(kernel-module-name? mp)
acc]
[(path? rp)
(cons (make-ModuleSource rp) acc)]
[else
acc])))
'()
dependent-module-names)])
paths)])]))
(let: loop : Void ([sources : (Listof Source) sources])
(cond
[(empty? sources)
(after-last)]
[(hash-has-key? visited (first sources))
(loop (rest sources))]
[else
(fprintf (current-timing-port) "compiling a module ~a\n" (source-name (first sources)))
(hash-set! visited (first sources) #t)
(let*-values ([(this-source)
((current-module-source-compiling-hook)
(first sources))]
[(ast stmts)
(get-ast-and-statements this-source)])
(log-debug (format "visiting ~a\n" (source-name this-source)))
((Configuration-on-source config) this-source ast stmts)
(define start-time (current-inexact-milliseconds))
(define new-dependencies (map wrap-source (collect-new-dependencies this-source ast)))
(define end-time (current-inexact-milliseconds))
(fprintf (current-timing-port) " computing dependencies: ~a milliseconds\n" (- end-time start-time))
(loop (append new-dependencies (rest sources)))
(after-module-statements this-source))])))
(follow-dependencies (map wrap-source sources))])))