Marc,

Can we get an implementation of equal? that works for recursive structures per r7rs?
It doesn't need to be called equal?, it can be called equal-shared? for instance.

I have an initial implementation that works with shared structures, but there is an edge case:
If there is a shared object in the structure (without recursion) it needs to be eq? to its counterpart.

(def (r7rs-equal? obj1 obj2)
  (def ht (make-hash-table-eq))

  (def (equal obj1 obj2)
    (cond
     ((##eq? obj1 obj2))
     ((immediate? obj1) #f)             ; should be eq?
     ((number? obj1)
      (##eqv? obj1 obj2))
     ((##table-ref ht obj1 #f)
      => (cut ##eq? <> obj2))         ; edge case mentioned above
     ((##pair? obj1)
      (and (##pair? obj2)
           (begin
             (##table-set! ht obj1 obj2)
             (and (equal (##car obj1) (##car obj2))
                  (equal (##cdr obj1) (##cdr obj2))))))
     ((##vector? obj1)
      (and (##vector? obj2)
           (let (len (##vector-length obj1))
             (and (##fx= len (##vector-length obj2))
                  (begin (##table-set! ht obj1 obj2)
                         (vector-equal obj1 obj2 0 len))))))
     ((##string? obj2)
      (and (##string? obj2)
           (##string-equal? obj1 obj2)))
     ((##u8vector? obj1)
      (and (##u8vector? obj2)
           (##u8vector-equal? obj1 obj2)))
     ((##s8vector? obj1)
      (and (##s8vector? obj2)
           (##s8vector-equal? obj1 obj2)))
     ((##u16vector? obj1)
      (and (##u16vector? obj2)
           (##u16vector-equal? obj1 obj2)))
     ((##s16vector? obj1)
      (and (##s16vector? obj2)
           (##s16vector-equal? obj1 obj2)))
     ((##u32vector? obj1)
      (and (##u32vector? obj2)
           (##u32vector-equal? obj1 obj2)))
     ((##s32vector? obj1)
      (and (##s32vector? obj2)
           (##s32vector-equal? obj1 obj2)))
     ((##u64vector? obj1)
      (and (##u64vector? obj2)
           (##u64vector-equal? obj1 obj2)))
     ((##s64vector? obj1)
      (and (##s64vector? obj2)
           (##s64vector-equal? obj1 obj2)))
     ((##f32vector? obj1)
      (and (##f32vector? obj2)
           (##f32vector-equal? obj1 obj2)))
     ((##f64vector? obj1)
      (and (##f64vector? obj2)
           (##f64vector-equal? obj1 obj2)))
     ((table? obj1)
      (and (table? obj2)
           (begin
             (##table-set! ht obj1 obj2)
             (table-equal obj1 obj2))))
     ((##structure? obj1)
      (and (##structure? obj2)
           (let* ((t1 (##structure-type obj1))
                  (t2 (##structure-type obj2))
                  (tid1 (##type-id t1))
                  (tid2 (##type-id t2)))
             (and (##eq? tid1 tid2)
                  (let (len (##vector-length obj1))
                    (and (##fx= len (##vector-length obj2))
                         (##fx= (##fxand (##type-flags t1) 1) 0) ; not opaque
                         (begin
                           (##table-set! ht obj1 obj2)
                           (vector-equal obj1 obj2 1 len))))))))
     ((##box? obj1)
      (and (##box? obj2)
           (begin
             (##table-set! ht obj1 obj2)
             (equal (##unbox obj1) (##unbox obj2)))))
     (else #f)))

  (def (vector-equal obj1 obj2 i len)
    (let lp ((i i))
      (if (##fx< i len)
        (and (equal (##vector-ref obj1 i) (##vector-ref obj2 i))
             (lp (##fx+ i 1)))
        #t)))

  (def (table-equal obj1 obj2)
    (and (##fx= (##vector-ref obj1 1) ; flags
                (##vector-ref obj2 1))
         (##eq? (##vector-ref obj1 2) ; test
                (##vector-ref obj2 2))
         (##eq? (##vector-ref obj1 3) ; hash
                (##vector-ref obj2 3))
         (##fx= (##table-length obj1)
                (##table-length obj2))
         (not (##table-search
               (lambda (k1 v1)
                 (let (v2 (##table-ref obj2 k1 nil))
                   (not (equal v1 v2))))
               obj1))))

  (equal obj1 obj2))

-- vyzo