[gambit-list] Transforming top-level program code

Jason Felice jason.m.felice at gmail.com
Thu Feb 21 10:50:25 EST 2013


Awesome!  Took a while to digest (specially because the docs are offline :(
).

What's the best way of making a check macro do nothing normally, but
redefining it when the code is loaded in a particular environment?

I'm thinking my checker tool will read the code, set a flag at the top,
then eval it (essentially).  The problem is that I can't check a name which
might or might not exist. I was looking for whether there was a way to
stick a feature into cond-expand, but that doesn't seem to be the case.
 Though I can redefine cond-expand (or something else), that seems a bit
much.

Thoughts?
-Jason



On Wed, Feb 20, 2013 at 1:37 PM, Marc Feeley <feeley at iro.umontreal.ca>wrote:

>
> On 2013-02-20, at 10:58 AM, Jason Felice <jason.m.felice at gmail.com> wrote:
>
> >
> > I've had a couple ideas for modifications to the Scheme reader that I
> imagine would be front-ends to the compiler.  Examples:
> >
> > 1. A front end which reads Scheme source but specially handles square
> braces, transforming them into Objective-C method calls via my library, so
> that I can put the following in a program:
> >
> >    (let ((s [[NSString alloc] initWithCapacity:42]))
> >       ...)
> >
> > And have it dispatch non-dynamically (my current project is completely
> dynamic).
>
> Extending the reader to handle square brackets is easy because the reader
> already has hooks to customize the reading of [...], {...}, <...>, and
> (...).  Here's an example:
>
>  Gambit v4.6.7
>
>  > (include "~~lib/_gambit#.scm")
>  > '[NSString alloc]
>  (NSString alloc)
>  > (macro-readtable-bracket-keyword-set! ##main-readtable 'ObjC-send)
>  > '[NSString alloc]
>  [NSString alloc]
>  > (length '[NSString alloc])
>  3
>  > (car '[NSString alloc])
>  ObjC-send
>  > (cadr '[NSString alloc])
>  NSString
>  > (caddr '[NSString alloc])
>  alloc
>  > (list->vector '[NSString alloc])
>  #(ObjC-send NSString alloc)
>  > (define-macro (ObjC-send receiver . args) `(pp 'objective-c-send...))
>  > [NSString alloc]
>  objective-c-send...
>
> Another example, which treats [...] as a vector constructor is:
>
>  > (include "~~lib/_gambit#.scm")
>  > (macro-readtable-bracket-keyword-set! ##main-readtable 'vector)
>  > [1 2 3 4]
>  #(1 2 3 4)
>
> > 2. A testing library where "check" forms appear under each function in
> the same file as documentation.  The check forms normally expand to
> nothing, but a command can be run from the command line scans the current
> directory and sub-directories for .scm files which (check ...) forms in
> them and runs them.
>
> This should be easy to do with macros.
>
> > 3. A complete environment with support for a lot of SRFI's and utility
> functions built in - a new REPL/compiler which is specialized for some
> domain.
> >
> > Black hole appears to do something like this.
> >
> > My question is, how do I hook into Gambit to compile or interpret after
> I've transformed the code, preserving line numbers?
>
> When you transform the code you must preserve the location information
> that was generated by the reader.
>
> The interpreter and compiler invoke the reader in a special mode where
> each datum (and subdatum) that is read is wrapped in a structure which
> gives the location information.  These structures are called "source"
> objects, and the ##make-source function is the constructor.
>
> Here is an example.  Say you have a file "foo.scm" with the content:
>
>  (define n 1)
>  (pp n)
>
> The interpreter and compiler will read that source code using the
> ##read-all-as-a-begin-expr-from-path function, which calls Gambit's
> extended read function to read each expression and construct a begin
> expression:
>
>  > (vector-ref (##read-all-as-a-begin-expr-from-path
>                 "foo.scm"
>                 (##current-readtable)
>                 (lambda (re x) x)
>                 (lambda (re x) x))
>                1)
>  (##begin (define n 1) (pp n))
>
> The last two parameters of ##read-all-as-a-begin-expr-from-path are the
> wrap and unwrap functions (whose first argument is the read-environment,
> which contains the reader's state including the port being read from and
> the current line/column location).  By supplying the predefined
> ##wrap-datum and ##unwrap-datum functions, each datum (and subdatum) will
> be wrapped in a source object:
>
>  > (vector-ref (##read-all-as-a-begin-expr-from-path
>                 "foo.scm"
>                 (##current-readtable)
>                 ##wrap-datum
>                 ##unwrap-datum)
>                1)
>  #(#(source1)
>    (#(#(source1) ##begin "/Users/feeley/gambit/work/foo.scm" 0)
>     #(#(source1)
>       (#(#(source1) define "/Users/feeley/gambit/work/foo.scm" 65536)
>        #(#(source1) n "/Users/feeley/gambit/work/foo.scm" 524288)
>        #(#(source1) 1 "/Users/feeley/gambit/work/foo.scm" 655360))
>       "/Users/feeley/gambit/work/foo.scm"
>       0)
>     #(#(source1)
>       (#(#(source1) pp "/Users/feeley/gambit/work/foo.scm" 65537)
>        #(#(source1) n "/Users/feeley/gambit/work/foo.scm" 262145))
>       "/Users/feeley/gambit/work/foo.scm"
>       1))
>    "/Users/feeley/gambit/work/foo.scm"
>    0)
>
> The source objects are vectors with the special tag #(source1) as their
> first element, i.e. #(#(source1) <datum> <filename> <column*65536+line>) .
>  Note that when <datum> is a list or vector, each of the elements is
> wrapped in a source object, and so on recursively.  The datum can be
> extracted with ##source-code, and the location information with
> ##source-locat.
>
> The interpreter and compiler can maintain this source location information
> when macros are defined with the ##define-syntax special form.  The macro
> transformer function receives a source object with location information,
> and can return a source object with location information (the transformer
> can also return a non source object, which will get automatically wrapped
> with a source location object with the location of the macro call).  Here's
> an example:
>
>  > (define (where source)
>     (##display-locat (##source-locat source) #f (repl-output-port))
>     (newline))
>  > (##define-syntax foo (lambda (source) (pp source) (where source) #f))
>  > (foo 1 2)
>  #(#(source1)
>    (#(#(source1) foo (console) 65540)
>     #(#(source1) 1 (console) 327684)
>     #(#(source1) 2 (console) 458756))
>    (console)
>    4)
>  (console)@5:1
>  #f
>
> Marc
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.iro.umontreal.ca/pipermail/gambit-list/attachments/20130221/777717c7/attachment.htm>


More information about the Gambit-list mailing list