
Really, `raco demod` is adapted here to work with any linklet-based VM by compiling modules to machine-independent form, which is essentially a wrapper around linklet S-expressions. The BC-specific implementation remains in place, and it has the advantage of being able to work with existing module compilations, while the implementation based on machine-independent form must recompile all modules before attempting to combine them (but that recompilation is easily cached). Use `--work <dir>` to use `<dir>` as a cache for multiple demodularizations. Getting `raco demod` to work involved several incidental improvements: * make `racket/linklet` work with machine-independent forms; * add `linklet-body-reserved-symbol?`; * fix schemify for linklets that have unexported definitions (which the expander never generates, but the demodularizer does); * add `current-multi-compile-any` to expose CM's multi-target compilation mode programmatically; and * repair a bug in CS JIT mode. The demodularizer could be a lot smarter to prune demodularized code before sending it off to the compiler. Of course, the compiler should be able to figure out improvements itself, but sending a smaller chunk of code to the compiler can avoid the hybrid interpreter--compiler mode that is used for large linklets and that prevents optimizers like cp0 from doing much to prune definitions. The demodularizer has a lot in common with the expander's flattener that is used for bootstrapping, and a smarter demodularizer would have even more in common. It would be nice to have one implementation instead of two.
32 lines
1.5 KiB
Racket
32 lines
1.5 KiB
Racket
#lang racket/base
|
|
(require racket/cmdline
|
|
racket/set
|
|
raco/command-name
|
|
"main.rkt")
|
|
|
|
(let ([output-file (make-parameter #f)])
|
|
(command-line #:program (short-program+command-name)
|
|
#:once-each
|
|
[("-o") dest-filename "Write output as <dest-filename>"
|
|
(output-file (string->path dest-filename))]
|
|
#:multi
|
|
[("-e" "--exclude-modules") path "Exclude <path> from flattening"
|
|
(current-excluded-modules (set-add (current-excluded-modules) path))]
|
|
#:once-each
|
|
[("-M" "--compile-any") "Keep in machine-independent form instead of recompiling"
|
|
(recompile-enabled #f)]
|
|
[("-r" "--recompile") "Recompile final module to re-run optimizations"
|
|
(recompile-enabled #t)]
|
|
[("--work") dir "Cache intermediate compilations in <dir>"
|
|
(unless (path-string? dir)
|
|
(raise-user-error (format "~a: invalid work directory: ~a"
|
|
(short-program+command-name)
|
|
dir)))
|
|
(current-work-directory dir)]
|
|
[("-g" "--garbage-collect") "Garbage-collect final module (unsound)"
|
|
(garbage-collect-toplevels-enabled #t)]
|
|
#:args (filename)
|
|
(demodularize filename (output-file))))
|
|
|
|
(module test racket/base)
|