On Jun 19, 2015, at 7:44 PM, Thomas Dickerson <thomas_dicker...@brown.edu> 
wrote:

> I was intending for that example to have the variables be defined outside the 
> macro, but being able to create the (set! ...) forms outside should mean I 
> could also hypothetically create let/define-values forms. This is why I 
> originally specified being able to effect generation of both prologue + 
> epilogue code.

I figured this out for code that will be expanded after the body:

#lang racket/base

(require racket/stxparam
         (for-syntax racket/base
                     syntax/parse
                     racket/set
                     ))

;; (syntax-parameter-value vars) : (U #f (MutableSetof Identifier))
(define-syntax-parameter vars #f)

(define-syntax Accum
  (lambda (stx)
    (syntax-parse stx
      [(Accum x:id dx:expr)
       (define vs (syntax-parameter-value #'vars))
       (unless (set-mutable? vs)
         (raise-syntax-error #f "cannot be used outside Loop" stx))
       (set-add! vs (syntax-local-introduce #'x))
       #'(set! x (+ x dx))])))

(define-syntax set-accums-zero!
  (syntax-parser
    [(set-accums-zero!)
     #:with [x ...]
     (map syntax-local-introduce (set->list (syntax-parameter-value #'vars)))
     #'(begin (set! x 0) ...)]))

(define-syntax Loop
  (syntax-parser
    [(Loop up-to-expr:expr body:expr ...+)
     #'(syntax-parameterize ([vars (mutable-set)])
         (let ([up-to up-to-expr])
           (letrec
               ([loop
                 (lambda (n)
                   body
                   ...
                   (if (< n up-to)
                       (loop (add1 n))
                       (void)))])
             (set-accums-zero!)
             (loop 0))))]))

(let ([x "x"] [y "y"] [z "z"])
  (Loop 10
        (begin
          (define-values 
            [dx dy dz] 
            (values 1 2 3))
          (printf "x = ~v, y = ~v, z = ~v\n" x y z)
          (Accum x dx)
          (Accum y dy)
          (Accum z dz))))

To generate a let outside of that you’d probably need to do some kind of 
local-expand, but I’m not sure.


> On Friday, June 19, 2015 at 6:47:15 PM UTC-4, Alex Knauth wrote:
>> Are the x, y, and z variables meant to be defined outside the macro by the 
>> user as in:
>> (let ([x “something”] [y “something else”] [z “and something else”])
>>   (Loop ….))
>> ?
>> 
>> 
>> Or should the Loop macro create a (let ([x 0] [y 0] [z 0]) ….) for you 
>> instead?
>> 
>> 
>> On Jun 19, 2015, at 5:58 PM, Thomas Dickerson <thomas_d...@brown.edu> wrote:
>> 
>> 
>> Sure, here's a toy example.
>> 
>> This code:
>> 
>> 
>> (Loop 10
>>       (begin
>>         (define-values 
>>           [dx dy dz] 
>>           (values 0 0 0))
>>         ; Some calculation here
>>         (Accum x dx)
>>         (Accum y dy)
>>         (Accum z dz)))
>> 
>> Should desugar into this code:
>> (letrec 
>>     ([loop 
>>       (lambda (n) 
>>         (begin
>>           (define-values 
>>             [dx dy dz] 
>>             (values 0 0 0))
>>           ; Some calculation here
>>           (set! x (+ x dx))
>>           (set! y (+ y dy))
>>           (set! z (+ z dz)))
>>         (if (< n 10)
>>             (loop (+ 1 n))
>>             (void)))])
>>   (set! x 0)
>>   (set! y 0)
>>   (set! z 0)
>>   (loop 0))
>> 
>> 
>> And in general, every unique id occuring in an (Accum id delta) in the loop 
>> body should result in (set! id 0) in the prologue.
>> 
>> 
>> Also, some context to avoid unproductive side-conversation: I'm using 
>> Racket's macro facility to do pre-compilation of a totally different 
>> language. The fully-expanded program in this case is going to be a call to a 
>> function that rewrites Racket syntax objects into strings in the syntax of 
>> something which isn't Racket. This means that I really want my original 
>> question answered, rather than suggestions to solve a different problem that 
>> happens to accomplish the same thing for this toy example. The critical 
>> pieces here are that Accum only be defined within the body of a Loop, and 
>> that it be able to communicate outwards to effect the code generation of the 
>> specific instantiation of Loop in which it appears.
>> 
>> 
>> 
>> 
>> 
>> 
>> 
>> 
>> 
>> 
>> Thomas Dickerson
>> 
>> Brown University
>> Department of Computer Science
>> 
>> 115 Waterman St, 4th Floor
>> 
>> Providence, RI 02912
>> 
>> 802-458-0637
>> 
>> 
>> 
>> On Fri, Jun 19, 2015 at 3:22 PM, Ryan Culpepper <ry...@ccs.neu.edu> wrote:
>> On 06/19/2015 03:07 PM, Thomas Dickerson wrote:
>> 
>> 
>> Hi All,
>> 
>> 
>> 
>> I'm trying to figure out how best to implement the following pattern of 
>> macro behavior:
>> 
>> 
>> 
>> Let's say we are writing Loop macro that implements a looped computation 
>> over a specified body. I would like to then be able to
>> 
>> (a) introduce additional Loop-specific macros that are defined only within 
>> the scope of the body
>> 
>> (b) are able to coordinate with the outer macro so as to alter its 
>> generation of prologue and epilogue code.
>> 
>> 
>> 
>> My best guess here is some use of local-expand with 
>> syntax-local-bind-syntaxes, or perhaps syntax-parameterize, but I can't 
>> quite work out the appropriate constructions.
>> 
>> 
>> 
>> I've been able to implement something similar using syntax-case functions on 
>> syntax objects at phase-0, by essentially implementing my own namespace for 
>> macros and passing it as an explicit argument, but this loses the hygiene 
>> benefits of coordinating with expand.  I had an offline discussion with 
>> Shriram yesterday in which he suggested looking into ways to reify the 
>> expansion-time namespace, but obviously current-namespace does the wrong 
>> thing here.
>> 
>> 
>> 
>> 
>> Can you provide a small example program and describe how you want it to 
>> behave?
>> 
>> 
>> 
>> Ryan
>> 
>> 

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to