Andrew Wright の match を移植する その2 - Scheme VMを書く
昨日の続き。
- (cond (3)) => 3 は Scheme の仕様上正しいものだった。ごめんなさい。
- quasiquote の展開に仕様の違いが見られると思ったが勘違いで、僕のコンパイラが特定の場合に quasiquote の展開し忘れたいただけだった。
というわけでほぼ完全に動くようになりました。 match-lambda とか match-let1 (Gauche 由来のもの)が動くようになって幸せです。
このライブラリのコンパイルに時間がかかるようになったのでいずれはプリコンパイルしよう。
コンパイラをプリコンパイルしてCの配列にして内蔵することはやっていたのだけど、ライブラリをプリコンパイルして内蔵する発想は無かった。Gauche.Nightの2次会で shiroさんに教えてもらい気づかされた><。
以下 本家との diff です。
--- match-slib.scm.orig 1995-07-18 00:51:14.000000000 +0900 +++ match-slib.scm 2008-03-10 13:11:18.000000000 +0900 @@ -1,3 +1,18 @@ +;; +;; match - Andrew Wright's pattern matching macro. +;; +;; Ported to Mona Scheme by higepon@users.sourceforge.jp. + +(define-macro (gentemp) + `(gensym)) + +(define-macro (defmacro . args) + `(define-macro (,(first args) . ,(second args)) + ,@(cddr args))) + +(define-macro (match-let1 pat exp . body) ;; Extension from Gauche by shiro kawai. + `(match ,exp (,pat ,@body))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Pattern Matching Syntactic Extensions for Scheme ;; @@ -142,18 +157,17 @@ ;; End of user visible/modifiable stuff. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(require 'pretty-print) (define match:error (lambda (val . args) (for-each pretty-print args) - (slib:error "no matching clause for " val))) + (error "no matching clause for " val))) (define match:andmap (lambda (f l) (if (null? l) (and) (and (f (car l)) (match:andmap f (cdr l)))))) (define match:syntax-err - (lambda (obj msg) (slib:error msg obj))) + (lambda (obj msg) (error msg obj))) (define match:disjoint-structure-tags '()) (define match:make-structure-tag (lambda (name) @@ -2446,44 +2460,53 @@ (g242)))) (g242))) (g242)))) + +(define-macro (field? id) + `(if (symbol? ,id) + ((lambda () #t)) + (if (and (pair? ,id) + (equal? (car ,id) '!) + (pair? (cdr ,id)) + (symbol? (cadr ,id)) + (null? (cddr ,id))) + ((lambda () #t)) + ((lambda () #f))))) + +(define-macro (field-name x) + `(if (symbol? ,x) ,x (cadr ,x))) + + +(define-macro (has-mutator? x) + `(not (symbol? ,x))) + +(define-macro (filter-map-with-index f l) + `(letrec ((mapi (lambda (l i) + (cond + ((null? l) '()) + ((,f (car l) i) => + (lambda (x) + (cons x + (mapi (cdr l) + (+ 1 + i))))) + (else (mapi (cdr l) + (+ 1 i))))))) + (mapi ,l 1))) + +(define-macro (symbol-append . l) + `(string->symbol + (apply + string-append + (map (lambda (x) + (cond + ((symbol? x) (symbol->string x)) + ((number? x) (number->string x)) + (else x))) + ,l)))) + (defmacro define-const-structure args - (let ((field? (lambda (id) - (if (symbol? id) - ((lambda () #t)) - (if (and (pair? id) - (equal? (car id) '!) - (pair? (cdr id)) - (symbol? (cadr id)) - (null? (cddr id))) - ((lambda () #t)) - ((lambda () #f)))))) - (field-name (lambda (x) (if (symbol? x) x (cadr x)))) - (has-mutator? (lambda (x) (not (symbol? x)))) - (filter-map-with-index (lambda (f l) - (letrec ((mapi (lambda (l i) - (cond - ((null? l) '()) - ((f (car l) i) => - (lambda (x) - (cons x - (mapi (cdr l) - (+ 1 - i))))) - (else (mapi (cdr l) - (+ 1 i))))))) - (mapi l 1)))) - (symbol-append (lambda l - (string->symbol - (apply - string-append - (map (lambda (x) - (cond - ((symbol? x) (symbol->string x)) - ((number? x) (number->string x)) - (else x))) - l)))))) (let ((g266 (lambda () (match:syntax-err `(define-const-structure ,@args) @@ -2614,4 +2637,4 @@ (g259 (cdr g260) (cons (car g260) g258)) (g266)))) (g266))) - (g266))))) + (g266))))