[plt-scheme] Some more syntax-handling fun --- trying to extract all the definitions in an arbitrary file

From: Paulo J. Matos (pocmatos at gmail.com)
Date: Wed Mar 22 16:56:25 EST 2006

On 21/03/06, Danny Yoo <dyoo at hkn.eecs.berkeley.edu> wrote:
> 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)))
>

As a side note, there is already an append-map in srfi1. :)

>
>   ;; 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!
>
> _________________________________________________
>   For list-related administrative tasks:
>   http://list.cs.brown.edu/mailman/listinfo/plt-scheme
>


--
Paulo Jorge Matos - pocm at sat inesc-id pt
Web: http://sat.inesc-id.pt/~pocm
Computer and Software Engineering
INESC-ID - SAT Group


Posted on the users mailing list.