On Tuesday, June 23, 2015 at 8:30:32 AM UTC-4, Matthew Flatt wrote:
> Providing #f as the third argument to `local-expand` means that
> 
>  (+ i j)
> 
> is expanded only as far as exposing the primitive function-call form, also 
> known as `#%plain-app`:
> 
>  (#%plain-app + i j)
> 
> When `i` is encountered later, there's no binding in the compile-time
> environment, because the internal-definition context has been
> discarded as the `my-def-stx` macro returned.
> 
> Probably you want to replace the `#f` with `null` (which means "expand
> without stopping").
Got it - this makes sense, thanks.

> Another possibility is to expand to a
> `letrec-syntaxes+values` form to bind `i` and `j`.

This is actually what I'm trying to avoid - see the earlier note on why I need 
a solution that won't leave behind empty (let-values () ...) forms (or any 
other Racket-specific forms) in the output syntax.
 
> At Tue, 23 Jun 2015 02:13:19 -0400, Thomas Dickerson wrote:
> > I seem to be missing some key ingredient here. The following really simply
> > test-case, using let-syntaxes, works as expected:
> > 
> > > (define-syntax my-def-stx
> > >   (lambda (stx)
> > >     (syntax-case stx (my-def-stx)
> > >       [(my-def-stx (id ...) rhs expr)
> > >        #'(let-syntaxes ([(id ...) rhs]) expr)])))
> > >
> > > (my-def-stx
> > >  (i j) (values (lambda (stx) #'3) (lambda (stx) #'4))
> > >  (+ i j))
> > >
> > Trying the same thing, but with this:
> > 
> > > (require (for-syntax syntax/context))
> > > (define-syntax my-def-stx
> > >   (lambda (stx)
> > >     (syntax-case stx (my-def-stx)
> > >       [(my-def-stx (id ...) rhs expr)
> > >        (let* ([intdef (syntax-local-make-definition-context)]
> > >              [ctx (generate-expand-context)])
> > >            (syntax-local-bind-syntaxes (syntax->list #'(id ...))
> > > (local-transformer-expand #'rhs 'expression null) intdef)
> > >            (internal-definition-context-seal intdef)
> > >            (local-expand #'expr ctx #f intdef))])))
> > >
> > > (my-def-stx
> > >  (i j) (values (lambda (stx) #'3) (lambda (stx) #'4))
> > >  (+ i j))
> > >
> > instead, gives me "i: undefined; cannot reference an identifier before its
> > definition".
> > 
> > Thomas Dickerson
> > 
> > Brown University
> > Department of Computer Science
> > 115 Waterman St, 4th Floor
> > Providence, RI 02912
> > 
> > 802-458-0637
> > 
> > On Mon, Jun 22, 2015 at 11:39 PM, Matthew Flatt <mfl...@cs.utah.edu> wrote:
> > 
> > > Probably you don't want to work with namespaces, which are intended more
> > > for run-time reflection.
> > >
> > > For an example of turning internal definitions into
> > > 'letrec-syntaxes+values', try the implementation of 'racket/block'.
> > >
> > > > On Jun 23, 2015, at 10:06 AM, Thomas Dickerson <
> > > thomas_dicker...@brown.edu> wrote:
> > > >
> > > > Update / addendum: I was also able to fairly trivially extend Alex's
> > > code using let-syntax to have the more hygienic behavior for where Accum
> > > is/is-not visible, but let-syntax ends up leaving an additional layer of
> > > empty (let-values() ...) behind.
> > > >
> > > > The documentation for let-syntax makes the following claim - "The
> > > evaluation of each trans-expr is parameterized to set current-namespace to
> > > a namespace that shares bindings and variables with the namespace being
> > > used to expand the let-syntax form, except that its base phase is one
> > > greater." which seems very much related to what I'd like to accomplish 
> > > (and
> > > Shriram's suggestion that I mentioned in the original post); however, I 
> > > see
> > > no evidence of this actually taking place in the Racket source-code, it
> > > just appears to desugar, with very few bells and whistles, to
> > > letrec-syntaxes+values which evidently is implemented in the C code.
> > > Digging into syntax-parameterize shows that, unsurprisingly, this is also
> > > how syntax-parameterize gets desugared, with a few more bells and 
> > > whistles.
> > > >
> > > > So I guess at this point the remainder of my question boils down to
> > > this: can someone offer any insight into the process of turning macros
> > > which are introduced by let-syntax or equivalent into macros which are
> > > introduced implicitly by an internal-definition-context argument to
> > > local-expand, or by explicit namespace manipulation as hinted at in the
> > > let-syntax documentation (but which I can't turn up anywhere).
> > > >
> > > >> On Monday, June 22, 2015 at 5:35:50 PM UTC-4, Thomas Dickerson wrote:
> > > >> Thanks for the effort that went into figuring that out! A couple first
> > > thoughts on the implementation:
> > > >> To first order, this is exactly what I want to be able to do (and it
> > > elegantly avoids local-expand by reasoning about expansion order); 
> > > however,
> > > as a general pattern, it's a bit unhygienic in that Accum is now in the
> > > global namespace, which precludes using it as a child macro for other
> > > constructs, and prevents specific instantiations of Loop from requesting a
> > > different name for Accum to cooperate in nested loops.
> > > >>
> > > >> I also noticed that (syntax-parameterize) isn't totally transparent in
> > > the expanded syntax - it leaves a bunch of empty (let-values () ...)
> > > behind, which is fine for Racket, but problematic in my target use-case of
> > > emitting something which ultimately needs to be an entirely different
> > > language. This is why my experiments have all involved local-expand - I
> > > want to introduce expand-time names without introducing wrapping
> > > let-syntaxes (or similar) forms around my body code.
> > > >>
> > > >>
> > > >>> On Saturday, June 20, 2015 at 2:24:40 PM UTC-4, Alex Knauth wrote:
> > > >>>> 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.
> > > >
> > > > --
> > > > 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.
> > >
> > 
> > -- 
> > 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.

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