define-macroなしで頑張ってsimple-structを作る

今までdefine-macroで書いていたsimple-structをR6RSのsyntax-caseを使って書き直した。

(define-syntax syntax-with:
  (lambda (x)
    (define (add: sym)
      (string->symbol (string-append (symbol->string sym) ":")))
    (syntax-case x ()
      ((_ target body ...)
       (let ((newname (datum->syntax #'target (add: (syntax->datum #'target)))))
         #`(define-syntax #,newname body ...))))))

まず、後ろにsuffixを自動的につけるdefine-syntaxであるところのsyntax-with:を作る。これで、(syntax-with: hoge BODY)とやると、(define-syntax hoge: BODY)に展開されるようになる。
こればっかりはsyntax-caseのsyntax->datum等を使わないとどうにも書けない。。

(define-syntax addspec
  (lambda (x)
    (syntax-case x ()
      ((_ num name spec)
       #'(syntax-with: spec
                       (syntax-rules ()
                       ((_ obj) (vector-ref obj num))
                       ((_ obj dat) (vector-set! obj num dat))))))))

(define-syntax defmysclass-num
  (syntax-rules ()
  ((_ num name spec0)
   (addspec num name spec0))
  ((_ num name spec0 spec1 ...)
   (begin
     (addspec num name spec0)
     (defmysclass-num (+ 1 num) name spec1 ...)))))

(define-syntax defmysclass ; my-define-static-class
  (syntax-rules ()
     ((_ name spec0 ...)
      (defmysclass-num 0 name spec0 ...))))

あとはR5RS Schemeと同じようにsyntax-rulesで書ける。

(defmysclass myclass
   A
   B
   C)

このようにすると、(A: obj)とするとスロットAを参照でき、(A: obj DATUM)とすると、スロットAにDATUMを設定できる。