[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: Sat Jul 19 19:39:17 EDT 2014

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


Posted on the users mailing list.