Let's start Scheme

2015-04-14

Comparison of er-macro-transformer 2

Previous article: Comparison of er-macro-transformer

I've heard er macro and syntax-case can do the same things (or they have almost the equal power). Now I'm wondering if this is really true or not. Once upon a time, there was an R6RS portable OOP library called nausicaa-oopp. For some reason its repository is removed from GitHub. The library used syntax-case to its limit (I think) and provided CL like multi method and other OOP things.

One of the remarkable thing of the library was it inserts identifiers which renamed by syntax-case or syntax and binds a macro to it, then inside of the macro it refers the original identifier. For example, it can do like this thing:
;; <beta> is a macro which represents a class of object o.
;; with-tags binds a macro which name is o, thus the o in its body
;; refers to the macro. however inside of the macro o, it refers
;; given o.
(define (beta-def-ref o)
  (with-tags ((o <beta>))
    (list (o d) (o e) (o f))))
If you just read the comment, it seems pretty much normal thing however the macro with-tags requires to have the same name as the o passed to beta-def-ref. Thus this would raise an error.
(define (beta-def-ref o)
  (with-tags ((oo <beta>))
    (list (oo d) (oo e) (oo f))))
Can this be done on er macro? The answer is yes. This is the piece of code: https://gist.github.com/ktakashi/63745cf1b7e0a018b64f

Then how portable is this? I know there is no concrete specification of er macro so I would expect this type of code may not be portable. So I've run it on Chicken, Chibi, Gauche and Sagittarius. And the following is the result:
Chicken:
dispatched!
dispatched!
dispatched!
(a a a)
dispatched!
dispatched!
dispatched!

Error: unbound variable: oo

 Call history:

 <eval>   (cdr2441 x2345)
 <eval>   (pair?2514 x2440)
 <eval>   (null?2515 (cdr2516 x2440))
 <eval>   (cdr2516 x2440)
 <eval>   (car2519 x2440)
 <eval>   (pair?2536 w2518)
 <eval>   (car2539 w2518)
 <eval>   (cdr2541 w2518)
 <eval>   (display (quote dispatched!))
 <eval>   (newline)
 <eval>   (r src)
 <syntax>   (beta-def-ref2 (quote a))
 <syntax>   (quote a)
 <syntax>   (##core#quote a)
 <eval>   (beta-def-ref2 (quote a))
 <eval>   [beta-def-ref2] (list2684 (oo2680 d2685) (oo2680 e2686) (oo2680 f2687)) <--

Chibi:
dispatched!
dispatched!
dispatched!
(a a a)
dispatched!
dispatched!
dispatched!
ERROR in beta-def-ref2: undefined variable: oo
  called from <anonymous> on line 1039 of file /home/takashi/sandbox/share/chibi/init-7.scm
  called from <anonymous> on line 542 of file /home/takashi/sandbox/share/chibi/init-7.scm
  called from <anonymous> on line 622 of file /home/takashi/sandbox/share/chibi/init-7.scm
Searching for modules exporting oo ...
... none found.

Gauche:
dispatched!
dispatched!
dispatched!
*** ERROR: unbound variable: o
    While loading "./er.scm" at line 154
Stack Trace:
_______________________________________
  0  o

  1  (beta-def-ref 'a)
        At line 154 of "./er.scm"

Sagittarius:
dispatched!
dispatched!
dispatched!
(a a a)
dispatched!
dispatched!
dispatched!
Unhandled exception
  Condition components:
  1. &undefined
  2. &who oo
  3. &message unbound variable oo in library user

stack trace:
  [1] beta-def-ref2
    src: (lambda (o) (with-tags ((oo <beta>)) (list (oo d) 
    "er.scm":157
  [2] load
Chicken, Chibi and Sagittarius worked as I expected. It seems Gauche can't resolve the original binding. I guess Chicken requires to put explicit phase when importing a library if I want to use it in procedural macro but I don't know how on R7RS extension. Updated on 11/05/2015: Using import-for-syntax resolves this. Thanks evhan!

During writing the code, I've notice a small thing. Chibi and Chicken accepts the following:
(define-syntax foo (er-macro-transformer (lambda (f r c) (r '(display "hoge")))))
(foo)
;;-> prints "hoge"
However Gauche and Sagittarius raise an error. As a user, it's convenient if I can rename a list with rename procedure but is this actually common in sense of er macro?

No comments:

Post a Comment