[plt-scheme] Dot-notation for structure field access

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Mon Mar 19 02:56:01 EDT 2007

At Sun, 11 Mar 2007 12:49:17 +0100, "jos koot" wrote:
> Inspired by the dot notation of Jens Axel Søgaard I tried to eliminate the 
> need for define-accessor. See enclosure. However, I can't get rid of the error 
> reported at the end of my trial, reading:
> "compile: bad syntax; reference to top-level identifier is not allowed, 
> because no #%top syntax transformer is bound in: acc85"

The problem starts here:

 (define-syntax (define-struct-type stx)
  (syntax-case stx ()
   ((define-struct-type (descr constr pred super) (field ...) inspector)
    (let-values (((acc mut) (apply values (generate-temporaries #'(acc mut)))))
     (register-transformer-builder #'constr #'(field ...) acc mut)
   #`(define-values (descr constr pred #,acc #,mut)

The call to `register-transformer-builder' is a side effect that
happens while the macro is expanded. After a `define-struct-type' form
is expanded --- say, when compiling a module --- the side-effect won't
happen anymore. In particular, the side effect won't happen if you
(next week, on a different machine) load the compiled form of module
whose source contains the `define-struct-type' declaration.

Well, the error you see is only indirectly related to the problem,
which is partly why it's difficult to track down. The problem is that
the registration uses `acc' and `mut' identifiers before any such
bindings exist, and that leads to the bad reference.

The solution to both problems is the same, and it's simple to write

 (define-syntax (define-struct-type stx)
  (syntax-case stx ()
   ((define-struct-type (descr constr pred super) (field ...) inspector)
    (let-values (((acc mut) (apply values (generate-temporaries #'(acc mut)))))
          (register-transformer-builder #'constr #'(field ...) #'#,acc #'#,mut))
         (define-values (descr constr pred #,acc #,mut)

All I've done is move the `register-transformer-builder' call into the
result of the macro, so that it's a side-effect wrapped by
`begin-for-syntax'. Since it's part of the result expansion, the side
effect happens each time the expanded (or compiled) expression is

Moreover, `acc' and `mut are now in the same binding context as the
`define-values' form, so they get bound in the way that you want.

The general rule is: Don't put any side-effects in a macro expansion.
If you must have side effects at compile time, they should be in

See also 
which may make more sense now that you've hit the problem that it
describes. :)

Unfortunately, there's a small catch, which I think is almost certainly
related to your later question about `syntax-recertify'. If you try

 (module m mzscheme
   (require dot)
   (define-struct-type d c p (x y z) (make-inspector))
   (provide d c p))

 (module n mzscheme
   (require dot m)
   (define-struct-var s (c 1 2 add1))
   (printf "~s\n" s.x))

then you get

 compile: access from an uncertified context to unexported variable
 from module: m at: acc1 in: acc1.1

Even though there's no `local-expand' in the macro implementation,
there is a kind of manual expansion that happens when looking up a
binding via `register-lookup'. That manual lookup must be accompanied
by manual management of certificates (though not through using

So, explicitly certify the referencing identifiers before you record

 (define-syntax (define-struct-type stx)
  (syntax-case stx ()
   ((define-struct-type (descr constr pred super) (field ...) inspector)
    (let-values (((acc mut) (apply values (generate-temporaries #'(acc mut)))))
          (let ([cert (syntax-local-certifier)])
            (register-transformer-builder #'constr #'(field ...) 
                                          (cert #'#,acc)
                                          (cert #'#,mut))))
         (define-values (descr constr pred #,acc #,mut)

Revised code and example enclosed.

-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: dot.scm
URL: <http://lists.racket-lang.org/users/archive/attachments/20070319/61197c27/attachment.ksh>

Posted on the users mailing list.