raco decompile: improve argument checking and reporting
Relevant to PR 14525
This commit is contained in:
parent
9b42fca050
commit
e4189afb15
|
@ -3,25 +3,80 @@
|
|||
raco/command-name
|
||||
compiler/zo-parse
|
||||
compiler/decompile
|
||||
racket/pretty)
|
||||
racket/pretty
|
||||
racket/format)
|
||||
|
||||
(define (get-name)
|
||||
(string->symbol (short-program+command-name)))
|
||||
|
||||
(define force? #f)
|
||||
|
||||
(define source-files
|
||||
(command-line
|
||||
#:program (short-program+command-name)
|
||||
#:once-each
|
||||
[("--force") "Ignore timestamp mimatch on associated \".zo\""
|
||||
(set! force? #t)]
|
||||
[("--columns" "-n") n "Format for <n> columns"
|
||||
(let ([num (string->number n)])
|
||||
(unless (exact-positive-integer? num)
|
||||
(raise-user-error (string->symbol (short-program+command-name))
|
||||
(raise-user-error (get-name)
|
||||
"not a valid column count: ~a" n))
|
||||
(pretty-print-columns num))]
|
||||
#:args source-or-bytecode-file
|
||||
source-or-bytecode-file))
|
||||
|
||||
(define (check-files orig-file alt-file)
|
||||
(cond
|
||||
[(not (file-exists? alt-file))
|
||||
(cond
|
||||
[(file-exists? orig-file)
|
||||
(unless (is-bytecode-file? orig-file)
|
||||
(raise-user-error (get-name)
|
||||
(~a "not a bytecode file, and no associated \".zo\" file\n"
|
||||
" path: ~a\n"
|
||||
" tried associated path: ~a")
|
||||
orig-file
|
||||
alt-file))]
|
||||
[else
|
||||
(raise-user-error (get-name)
|
||||
(~a "no such file, and no associated \".zo\" file\n"
|
||||
" path: ~a\n"
|
||||
" tried associated path: ~a")
|
||||
orig-file
|
||||
alt-file)])]
|
||||
[(not (is-bytecode-file? alt-file))
|
||||
(raise-user-error (get-name)
|
||||
(~a "associated \".zo\" file is not a bytecode file\n"
|
||||
" original path: ~a\n"
|
||||
" associated path: ~a")
|
||||
orig-file
|
||||
alt-file)]
|
||||
[(and (not force?)
|
||||
((file-or-directory-modify-seconds orig-file)
|
||||
. > .
|
||||
(file-or-directory-modify-seconds alt-file)))
|
||||
;; return a warning:
|
||||
(raise-user-error (get-name)
|
||||
(~a "associated \".zo\" file's date is older than given file's date;\n"
|
||||
" consider using `raco make` to rebuild the source file, or use `--force`\n"
|
||||
" to skip the date check\n"
|
||||
" original path: ~a\n"
|
||||
" associated path: ~a")
|
||||
orig-file
|
||||
alt-file)]))
|
||||
|
||||
(define (is-bytecode-file? orig-file)
|
||||
(call-with-input-file*
|
||||
orig-file
|
||||
(lambda (i)
|
||||
(equal? #"#~" (read-bytes 2 i)))))
|
||||
|
||||
(for ([zo-file source-files])
|
||||
(let ([zo-file (path->complete-path zo-file)])
|
||||
(let-values ([(base name dir?) (split-path zo-file)])
|
||||
(let ([alt-file (build-path base "compiled" (path-add-suffix name #".zo"))])
|
||||
(check-files zo-file alt-file)
|
||||
(parameterize ([current-load-relative-directory base]
|
||||
[print-graph #t])
|
||||
(pretty-write
|
||||
|
|
|
@ -9,13 +9,22 @@
|
|||
|
||||
@title[#:tag "decompile"]{@exec{raco decompile}: Decompiling Bytecode}
|
||||
|
||||
The @exec{raco decompile} command takes a bytecode file (which usually
|
||||
The @exec{raco decompile} command takes the path of a bytecode file (which usually
|
||||
has the file extension @filepath{.zo}) or a source file with an
|
||||
associated bytecode file (usually created with @exec{raco make}) and
|
||||
converts it back to an approximation of Racket code. Decompiled
|
||||
converts the bytecode file's content back to an approximation of Racket code. Decompiled
|
||||
bytecode is mostly useful for checking the compiler's transformation
|
||||
and optimization of the source program.
|
||||
|
||||
The @exec{raco decompile} command accepts the following command-line flags:
|
||||
|
||||
@itemlist[
|
||||
@item{@DFlag{force} --- skip modification-date comparison on the
|
||||
given file's path and an associated @filepath{.zo} file (if any)}
|
||||
@item{@Flag{n} @nonterm{n} or @DFlag{columns} @nonterm{n} --- format
|
||||
output for a display with @nonterm{n} columns}
|
||||
]
|
||||
|
||||
Many forms in the decompiled code, such as @racket[module],
|
||||
@racket[define], and @racket[lambda], have the same meanings as
|
||||
always. Other forms and transformations are specific to the rendering
|
||||
|
@ -104,14 +113,6 @@ Many forms in the decompiled code, such as @racket[module],
|
|||
of functions without an @racket['%%inline-variant%%] are never
|
||||
inlined across modules.}
|
||||
|
||||
@item{Some applications of core primitives are annotated with
|
||||
@racketidfont{#%in}, which indicates that the JIT compiler will
|
||||
inline the operation. (Inlining information is not part of the
|
||||
bytecode, but is instead based on an enumeration of primitives that
|
||||
the JIT is known to handle specially.) Operations from
|
||||
@racketmodname[racket/flonum] and @racketmodname[racket/unsafe/ops]
|
||||
are always inlined, so @racketidfont{#%in} is not shown for them.}
|
||||
|
||||
@item{Function arguments and local bindings that are known to have a
|
||||
particular type have names that embed the known type. For example, an
|
||||
argument might have a name that starts @racketidfont{argflonum} or a
|
||||
|
@ -123,14 +124,6 @@ Many forms in the decompiled code, such as @racket[module],
|
|||
|
||||
]
|
||||
|
||||
Command-line flags:
|
||||
|
||||
@itemlist[
|
||||
@item{@Flag{n} @nonterm{n} or @DFlag{columns} @nonterm{n} --- format output for a display with @nonterm{n} columns}
|
||||
@item{@Flag{h} or @DFlag{help} --- show help information for this command}
|
||||
@item{@DFlag{} --- do not treat remaining arguments as switches}
|
||||
]
|
||||
|
||||
@; ------------------------------------------------------------
|
||||
|
||||
@section{API for Decompiling}
|
||||
|
|
Loading…
Reference in New Issue
Block a user