[plt-scheme] Some more syntax-handling fun --- trying to extract all the definitions in an arbitrary file
Hi everyone,
I know there's some code out there that does this already (DrScheme does
it of course!), but to better-understand macros and the subtleties of
module-or-top-identifier=?, I wrote a quick and dirty definition name
extractor. Here's the code:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(module get-definitions mzscheme
(provide get-definitions/path
get-definitions
extract-definition)
(require (lib "stx.ss" "syntax"))
(require (lib "file.ss"))
;; get-definitions/path: path -> (listof symbol)
;;
;; Given a filename, opens it up and tries to extract out all the
;; definitions.
(define (get-definitions/path path)
(call-with-input-file*
path
(lambda (ip)
(let ((stx (read-syntax path ip)))
(get-definitions stx)))))
;; get-definitions: syntax -> (listof symbol)
;;
;; Given a syntax, tries to return all the toplevel defined names in
;; that syntax.
(define (get-definitions stx)
(syntax-case* stx (module) module-or-top-identifier=?
((module m-name lang s-expr ...)
(mappend extract-definition (syntax->list (syntax (s-expr ...)))))
((s-expr ...)
(mappend extract-definition (syntax->list (syntax (s-expr ...)))))))
;; mappend: (X -> (listof Y)) (listof X) -> (listof Y)
;;
;; mapping append.
(define (mappend f l)
(apply append (map f l)))
;; extract-definition: syntax -> (listof symbol)
;;
;; If the form looks like a define, tries to extract the toplevel
;; name. Otherwise, returns the empty list.
(define (extract-definition stx)
(syntax-case* stx (define) module-or-top-identifier=?
((define (name args ...) body ...)
(list (syntax-e (syntax name))))
((define name value)
(list (syntax-e (syntax name))))
(else
(list)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Of course, I can't resist running this on itself. *grin*
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> (get-definitions/path "~/get-definitions.ss")
(get-definitions/path get-definitions mappend extract-definition)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
I'm really happy that this worked, but I know this is not quite robust
yet. If I use other forms that expand out to DEFINEs, then I'm sunk at
the moment. I need to understand how to use the expander functions.
I'm studying the reference manual about "Expanding Expressions to
Primitive Syntax", and was wondering: is EXPAND generally the right tool
to use to make sure the syntax is top-level-expr form before I start doing
the preprocessing stuff? In what contexts might one want to use the other
expand-* functions?
Thanks a lot!