<div dir="ltr">Awesome!  Took a while to digest (specially because the docs are offline :( ).<div><br></div><div style>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?</div>
<div style> </div><div style>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.</div>
<div style><br></div><div style>Thoughts?</div><div style>-Jason</div><div style><br></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Wed, Feb 20, 2013 at 1:37 PM, Marc Feeley <span dir="ltr"><<a href="mailto:feeley@iro.umontreal.ca" target="_blank">feeley@iro.umontreal.ca</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="im"><br>
On 2013-02-20, at 10:58 AM, Jason Felice <<a href="mailto:jason.m.felice@gmail.com">jason.m.felice@gmail.com</a>> wrote:<br>
<br>
><br>
> I've had a couple ideas for modifications to the Scheme reader that I imagine would be front-ends to the compiler.  Examples:<br>
><br>
> 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:<br>
><br>
>    (let ((s [[NSString alloc] initWithCapacity:42]))<br>
>       ...)<br>
><br>
> And have it dispatch non-dynamically (my current project is completely dynamic).<br>
<br>
</div>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:<br>
<br>
 Gambit v4.6.7<br>
<br>
 > (include "~~lib/_gambit#.scm")<br>
 > '[NSString alloc]<br>
 (NSString alloc)<br>
 > (macro-readtable-bracket-keyword-set! ##main-readtable 'ObjC-send)<br>
 > '[NSString alloc]<br>
 [NSString alloc]<br>
 > (length '[NSString alloc])<br>
 3<br>
 > (car '[NSString alloc])<br>
 ObjC-send<br>
 > (cadr '[NSString alloc])<br>
 NSString<br>
 > (caddr '[NSString alloc])<br>
 alloc<br>
 > (list->vector '[NSString alloc])<br>
 #(ObjC-send NSString alloc)<br>
 > (define-macro (ObjC-send receiver . args) `(pp 'objective-c-send...))<br>
 > [NSString alloc]<br>
 objective-c-send...<br>
<br>
Another example, which treats [...] as a vector constructor is:<br>
<br>
 > (include "~~lib/_gambit#.scm")<br>
 > (macro-readtable-bracket-keyword-set! ##main-readtable 'vector)<br>
 > [1 2 3 4]<br>
 #(1 2 3 4)<br>
<div class="im"><br>
> 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.<br>

<br>
</div>This should be easy to do with macros.<br>
<div class="im"><br>
> 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.<br>
><br>
> Black hole appears to do something like this.<br>
><br>
> My question is, how do I hook into Gambit to compile or interpret after I've transformed the code, preserving line numbers?<br>
<br>
</div>When you transform the code you must preserve the location information that was generated by the reader.<br>
<br>
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.<br>

<br>
Here is an example.  Say you have a file "foo.scm" with the content:<br>
<br>
 (define n 1)<br>
 (pp n)<br>
<br>
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:<br>

<br>
 > (vector-ref (##read-all-as-a-begin-expr-from-path<br>
                "foo.scm"<br>
                (##current-readtable)<br>
                (lambda (re x) x)<br>
                (lambda (re x) x))<br>
               1)<br>
 (##begin (define n 1) (pp n))<br>
<br>
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:<br>

<br>
 > (vector-ref (##read-all-as-a-begin-expr-from-path<br>
                "foo.scm"<br>
                (##current-readtable)<br>
                ##wrap-datum<br>
                ##unwrap-datum)<br>
               1)<br>
 #(#(source1)<br>
   (#(#(source1) ##begin "/Users/feeley/gambit/work/foo.scm" 0)<br>
    #(#(source1)<br>
      (#(#(source1) define "/Users/feeley/gambit/work/foo.scm" 65536)<br>
       #(#(source1) n "/Users/feeley/gambit/work/foo.scm" 524288)<br>
       #(#(source1) 1 "/Users/feeley/gambit/work/foo.scm" 655360))<br>
      "/Users/feeley/gambit/work/foo.scm"<br>
      0)<br>
    #(#(source1)<br>
      (#(#(source1) pp "/Users/feeley/gambit/work/foo.scm" 65537)<br>
       #(#(source1) n "/Users/feeley/gambit/work/foo.scm" 262145))<br>
      "/Users/feeley/gambit/work/foo.scm"<br>
      1))<br>
   "/Users/feeley/gambit/work/foo.scm"<br>
   0)<br>
<br>
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.<br>

<br>
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:<br>

<br>
 > (define (where source)<br>
    (##display-locat (##source-locat source) #f (repl-output-port))<br>
    (newline))<br>
 > (##define-syntax foo (lambda (source) (pp source) (where source) #f))<br>
 > (foo 1 2)<br>
 #(#(source1)<br>
   (#(#(source1) foo (console) 65540)<br>
    #(#(source1) 1 (console) 327684)<br>
    #(#(source1) 2 (console) 458756))<br>
   (console)<br>
   4)<br>
 (console)@5:1<br>
 #f<br>
<span class="HOEnZb"><font color="#888888"><br>
Marc<br>
<br>
</font></span></blockquote></div><br></div>