[racket] Ready for the next phase - or how to shift the phase of a namespace

From: Jens Axel Søgaard (jensaxel at soegaard.net)
Date: Mon Aug 4 16:16:53 EDT 2014

For the archives the functions

eval-for-meta           ; evaluate expression in given phase and return result
eval-for-syntax         ; evaluate expression in phase 1 and return result
eval-form-for-meta      ; evaluate form in given phase
eval-form-for-syntax    ; evaluate form in phase 1
syntax-value            ; return the value associated with a syntax
binding in a given phase

are available here:

https://github.com/soegaard/meta/blob/master/expander/transformer.rkt

/Jens Axel


2014-07-20 1:39 GMT+02:00 Jens Axel Søgaard <jensaxel at soegaard.net>:
> 2014-07-20 1:19 GMT+02:00 Matthias Felleisen <matthias at ccs.neu.edu>:
>>
>> Can't you just put forms2 into a constructed module that requires the desired module at the phase where you want it? -- Matthias
>
> That would be tricky. I am writing an interpreter that evaluates
> Racket bytecode represented as zo-structures.
>
> The main entry is:
>
> ; eval-zo : compilation-top [namespace] -> values(s)
> (define (eval-zo zo [ns (make-start-namespace)])
>   (unless (compilation-top? zo)
>       (error 'eval-zo "expected a compilation-top, got ~a" zo))
>   ; evaluation always occur within a top-level namespace
>   (parameterize ([current-namespace ns])
>     (eval-top zo)))
>
> The structure of the interpreter is a straight forward recursive descent.
> The "phase 0" forms and expressions are done and works fine.
> I have also managed to evaluate the stxs part of the prefix.
> The instruction I need shift-phase for is seq-for-syntax.
>
> From the docs on begin-for-syntax:
>   Evaluation of an expr within begin-for-syntax is parameterized to
>   set current-namespace as in let-syntax.
> From the docs on (let-syntax ([id trans-expr] ...) body ...+)
>   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.
>
>
> Here is what I'd like to write:
>
> (define (eval-form form globs stack closed stx-ht)
>   (match form
>    ...
>    [(struct seq-for-syntax (forms prefix max-let-depth dummy))
>      ; push the prefix
>      (define array (eval-prefix prefix stx-ht))
>      (define new-stack (mlist array stack))
>      ; shift phase and evalate each form
>      (parameterize ([current-namespace (shift-phase (current-namespace) +1)])
>         (for ([form (in-list forms)])
>            (let-syntaxes ([() (begin (eval-form (car forms) globs
> new-stack closed stx-ht)
>                                      (values))])
>                          (void))))]
>
> /Jens Axel
>
>> On Jul 19, 2014, at 3:52 PM, Jens Axel Søgaard wrote:
>>
>>> I am looking for a way to change the base phase of a namespace.
>>> Or perhaps to make a new namespace with the same mappings except a
>>> shift in phases.
>>> I hope I have missed a trick, but I couldn't find a
>>> namespace-shift-phase in the docs.
>>>
>>> Consider the following program which defines a variable x to 0, 1, 2, and, 3
>>> in phases 0, 1, 2, and, 3 respectively. It does so by evalunting the
>>> forms in forms.
>>>
>>> Then it displays the values of x in phases 1 and 2 with the results 1 and 2.
>>> It does so by evaluating the forms in forms2.
>>>
>>> I'd like to shift the base phase of the namespace (or make a copy with
>>> new base phase),
>>> so evaluating the forms in forms2 again will give results 2 and 3.
>>>
>>> #lang racket
>>> (define (eval* forms [ns (current-namespace)])
>>>  (for ([form forms])
>>>    (displayln (~a "> " form))
>>>    (eval form ns)))
>>>
>>> (define forms '((module m0 racket (provide x) (define x 0))
>>>                (module m1 racket (provide x) (define x 1))
>>>                (module m2 racket (provide x) (define x 2))
>>>                (module m3 racket (provide x) (define x 3))
>>>                (require (for-meta 0 'm0))
>>>                (require (for-meta 1 'm1))
>>>                (require (for-meta 2 'm2))
>>>                (require (for-meta 3 'm3))))
>>>
>>> (define forms2 '(; display the value of x in phase 1
>>>                 (define-syntaxes () (begin (displayln x) (values)))
>>>                 ; display the value of x in phase 2
>>>                 (define-syntaxes () (begin (let-syntaxes ([() (begin
>>> (displayln x) (values))])
>>>                                                          (void)) (values)))))
>>>
>>> (define ns (make-base-empty-namespace))
>>> (parameterize ([current-namespace ns])
>>>  ; setup the namespace
>>>  (namespace-require '(for-meta 0 racket/base))
>>>  (namespace-require '(for-meta 1 racket/base))
>>>  (namespace-require '(for-meta 2 racket/base))
>>>  (namespace-require '(for-meta 3 racket/base))
>>>  ; declare and require the modules
>>>  (eval* forms)
>>>  ; display the value of x in phase 1 and 2
>>>  (eval* forms2)       ; displays 1 and 2
>>>  ; (namespace-shift-phase ns +1)  ; on the wish list
>>>  ; (eval* forms2)                 ; would display 2 and 3
>>>  )
>>>
>>> The output is:
>>>
>>>> (module m0 racket (provide x) (define x 0))
>>>> (module m1 racket (provide x) (define x 1))
>>>> (module m2 racket (provide x) (define x 2))
>>>> (module m3 racket (provide x) (define x 3))
>>>> (require (for-meta 0 (quote m0)))
>>>> (require (for-meta 1 (quote m1)))
>>>> (require (for-meta 2 (quote m2)))
>>>> (require (for-meta 3 (quote m3)))
>>>> (define-syntaxes () (begin (displayln x) (values)))
>>> 1
>>>> (define-syntaxes () (begin (let-syntaxes ((() (begin (displayln x) (values)))) (void)) (values)))
>>> 2
>>>
>>> --
>>> Jens Axel Søgaard
>>>
>>> ____________________
>>>  Racket Users list:
>>>  http://lists.racket-lang.org/users
>>
>
>
>
> --
> --
> Jens Axel Søgaard



-- 
--
Jens Axel Søgaard


Posted on the users mailing list.