Let's start Scheme

2012-12-05

expanded internal define

It's aboud the macro expander of Sagittarius Scheme. I'm re-writing it to get better conformity with R6RS. Now I've got a (well not only one) problem and found a bug of current version.

Short description of the bug;
;; Doesn't matter what equal? return.

;; Bug 1
(let ()
  (define-record-type (pare kons pare?)
    (fields (mutable x kar set-kar!)
     (immutable y kdr)))
  (define a (kons (vector 1 2 3) '(a b c)))
  (define b (kons (vector 1 2 3) '(a b c)))
  (equal? a b))
kons ;; -> #<closure kons>
;; this should be &assertion of unbound variable

;; Bug 2
(let ((c #t))
  (define-record-type (pare kons pare?)
    (fields (mutable x kar set-kar!)
     (immutable y kdr)))
  (define a (kons (vector 1 2 3) '(a b c)))
  (define b (kons (vector 1 2 3) '(a b c)))
  (equal? a b))
;; -> &assertion
The first one is obviously wrong, it broke the definition of internal define. The second one is releated to comple time environment lookup. The kons is defined by define-record-type and it must be the same identifier as the one in internal define. But it's not. That's because macro expander re-name it to different identifer.

The simplest solution I have tried was to wrap all given expression first then expand macros. It's simple it worked (mostly) but broke constant literals such as quoted lists or vectors. The problem was not only it but also broke some other codes (mostly related with er-macro-transformer used for generating bootstap code and R7RS). So I've decided not to do this (even though I feel like it's the easier way to do it).

The second solution is modifying the environment lookup process. An identifier can hold some environment without any restriction on current branch and if I can find a better way to look up proper variable from compile time environment, it can be resolved. The problem is I don't know how...

Consider the case of Bug 1. The kons and environment have following frames;
;; kons identifier's frame
((0))
;; when 'a' is being compiled
((0 (kons#user . #(lvar ...)) ...) ;; kons#user is an identifier
 (0)) ;; &lt-- the same environment as the kons identifier
So when a is being compiled, compiler can see the same environment at the very top of the frame chain. But how can we assume kons#user and kons in internal define are the same variables? If the root of the frame are the same, would we be able to assume? Or when it's expanded to internal define, should it be stripped to mere symbol?

Hmm..., I need to think ...

No comments:

Post a Comment