[gambit-list] Transforming top-level program code
Jason Felice
jason.m.felice at gmail.com
Tue Mar 12 23:52:42 EDT 2013
I'm playing with macro-readtable-bracket-keyword-set! and can't get it to
work when compiling files.
I tried inline with the code, but realized that won't evaluate at compile
time, then did the define-macro/eval begin trick and found that brackets
still don't expand.
It works fine in gsi.
Thoughts?
On Thu, Feb 21, 2013 at 10:50 AM, Jason Felice <jason.m.felice at gmail.com>wrote:
> 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/20130312/4490a93e/attachment.htm>
More information about the Gambit-list
mailing list