racket/collects/drracket/private/eval-helpers.rkt
Matthew Flatt 6fe2861877 DrRacket: if any file in package X is open, treat X as "in development"
... for the purpose of "populate 'compiled' directories" --- but only if
the user has write permission for the package directory.

This change may or may not be a good idea. The idea is that installed
packages generally should be treated in the same way as the main
"collects" tree (e.g., avoiding debugging instrumentation), but if you
happen to be developing a package, then you want it treated like things
that are not in the main "collects" tree. So, how do you pick? Maybe
opening a file in the package is a good way to pick.
2013-04-16 12:51:54 -06:00

145 lines
5.8 KiB
Racket

#lang racket/base
(require racket/class
racket/draw
racket/list
racket/set
compiler/cm
setup/dirs
planet/config
pkg/lib
(prefix-in *** '#%foreign) ;; just to make sure it is here
)
(provide set-basic-parameters/no-gui
set-module-language-parameters
(struct-out prefab-module-settings)
transform-module
get-init-dir)
;; get-init-dir : (or/c path? #f) -> path?
;; returns the initial directory for a program
;; that is saved in 'path/f' (with #f indicating
;; an unsaved file)
(define (get-init-dir path/f)
(cond
[path/f
(let-values ([(base name dir?) (split-path path/f)])
base)]
[else
(find-system-path 'home-dir)]))
(struct prefab-module-settings
(command-line-args
collection-paths
compilation-on?
full-trace?
annotations)
#:prefab)
(define orig-namespace (current-namespace))
(define (set-basic-parameters/no-gui)
(let ([cust (current-custodian)])
(define (drracket-plain-exit-handler arg)
(custodian-shutdown-all cust))
(exit-handler drracket-plain-exit-handler))
(current-thread-group (make-thread-group))
(current-command-line-arguments #())
(current-pseudo-random-generator (make-pseudo-random-generator))
(current-evt-pseudo-random-generator (make-pseudo-random-generator))
(read-curly-brace-as-paren #t)
(read-square-bracket-as-paren #t)
(error-print-width 250)
(current-ps-setup (make-object ps-setup%))
(current-namespace (make-base-empty-namespace))
;; is this wise?
#;(namespace-attach-module orig-namespace ''#%foreign))
(define (set-module-language-parameters settings
module-language-parallel-lock-client
currently-open-files
#:use-use-current-security-guard? [use-current-security-guard? #f])
(current-command-line-arguments (prefab-module-settings-command-line-args settings))
(let* ([default (current-library-collection-paths)]
[cpaths (append-map (λ (x) (if (symbol? x) default (list x)))
(prefab-module-settings-collection-paths settings))])
(when (null? cpaths)
(eprintf "WARNING: your collection paths are empty!\n"))
(current-library-collection-paths cpaths))
(compile-context-preservation-enabled (prefab-module-settings-full-trace? settings))
(when (prefab-module-settings-compilation-on? settings)
(define open-pkgs
(for/fold ([s (set)]) ([path (in-list currently-open-files)])
(define pkg (path->pkg path))
(if (and pkg
(memq 'write
(file-or-directory-permissions (pkg-directory pkg))))
(set-add s pkg)
s)))
(for ([pkg (in-set open-pkgs)])
(log-info "DrRacket: enabling bytecode-file compilation for package ~s" pkg))
(define skip-path?
(let* ([cd (find-collects-dir)]
[no-dirs (if cd
(list (CACHE-DIR) cd)
(list (CACHE-DIR)))])
(λ (p) (or (file-stamp-in-paths p no-dirs)
(let ([pkg (path->pkg p)])
(and pkg
(not (set-member? open-pkgs pkg))
(file-stamp-in-paths p (list (pkg-directory pkg)))))))))
(define extra-compiled-file-path
(case (prefab-module-settings-annotations settings)
[(none) (build-path "compiled" "drracket")]
[(debug) (build-path "compiled" "drracket" "errortrace")]
[else #f]))
(when extra-compiled-file-path
;; Add extra compiled-file path:
(use-compiled-file-paths
(cons extra-compiled-file-path
(use-compiled-file-paths)))
;; If we ever skip a file, then don't use the extra compiled-file
;; path for the skipped file's dependencies (because modules
;; compiled against the non-DrRacket-generated bytecode might not
;; work with any DrRacket-generated bytecode that is sitting around):
(current-load/use-compiled
(let ([orig (current-load/use-compiled)])
(lambda (path mod-name)
(if (and (member extra-compiled-file-path (use-compiled-file-paths))
(skip-path? path))
(parameterize ([use-compiled-file-paths
(remove extra-compiled-file-path
(use-compiled-file-paths))])
(orig path mod-name))
(orig path mod-name))))))
;; Install the compilation manager:
(parallel-lock-client module-language-parallel-lock-client)
(current-load/use-compiled (make-compilation-manager-load/use-compiled-handler
#t
#:security-guard (and use-current-security-guard?
(current-security-guard))))
(manager-skip-file-handler skip-path?)))
(define (transform-module filename stx raise-hopeless-syntax-error)
(define-values (mod name lang body)
(syntax-case stx ()
[(module name lang . body)
(eq? 'module (syntax-e #'module))
(values #'module #'name #'lang #'body)]
[_ (raise-hopeless-syntax-error
(string-append "only a module expression is allowed, either\n"
" #lang <language-name>\n or\n"
" (module <name> <language> ...)\n")
stx)]))
(define name* (syntax-e name))
(unless (symbol? name*)
(raise-hopeless-syntax-error "bad syntax in name position of module"
stx name))
(let* (;; rewrite the module to use the racket/base version of `module'
[mod (datum->syntax #'here 'module mod)]
[expr (datum->syntax stx `(,mod ,name ,lang . ,body) stx stx)])
(values name lang expr)))