[plt-scheme] Using the struct type identifier as a macro [PATCH]

From: Dimitris Vyzovitis (vyzo at media.mit.edu)
Date: Mon Nov 17 13:28:57 EST 2008

On Mon, 17 Nov 2008, Sam TH wrote:

> as well as add some tests for your new feature?  Probably it would be
> easiest to add them to collects/tests/match/examples.ss .

Added tests in collects/tests/match/example.ss and 
collects/tests/mzscheme/struct.ss

-- vyzo
-------------- next part --------------
Index: collects/scheme/match/parse.ss
===================================================================
--- collects/scheme/match/parse.ss	(revision 12479)
+++ collects/scheme/match/parse.ss	(working copy)
@@ -152,6 +152,10 @@
     [(mcons e1 e2) (make-MPair (parse #'e1) (parse #'e2))]
     [(struct s pats)
      (parse-struct stx cert parse #'s #'pats)]
+    [(type pat ...)
+     (and (identifier? #'type) 
+          (struct-info? (syntax-local-value (cert #'type) (lambda () #f))))
+     (parse-struct stx cert parse #'type #'(pat ...))]
     [(? p q1 qs ...)
      (make-And (cons (make-Pred (cert #'p))
                      (map parse (syntax->list #'(q1 qs ...)))))]
Index: collects/scheme/private/define-struct.ss
===================================================================
--- collects/scheme/private/define-struct.ss	(revision 12479)
+++ collects/scheme/private/define-struct.ss	(working copy)
@@ -26,10 +26,20 @@
                       0 0 #f
                       null (current-inspector)
                       (lambda (v stx)
-                        (raise-syntax-error
-                         #f
-                         "identifier for static struct-type information cannot be used as an expression"
-                         stx))
+                        (let-values (((kons) (cadr (extract-struct-info v))))
+                          (if kons
+                            (if (list? (syntax-e stx))
+                              (datum->syntax stx (cons kons (cdr (syntax-e stx))) stx)
+                              (if (symbol? (syntax-e stx))
+                                kons 
+                                (raise-syntax-error
+                                    #f
+                                  "illegal use of struct-type identifier"
+                                  stx)))
+                            (raise-syntax-error
+                                #f
+                              "identifier for static struct-type information cannot be used as an expression"
+                              stx))))
                       null
                       (lambda (proc info)
                         (if (and (procedure? proc)
Index: collects/scheme/private/struct-info.ss
===================================================================
--- collects/scheme/private/struct-info.ss	(revision 12479)
+++ collects/scheme/private/struct-info.ss	(working copy)
@@ -16,10 +16,20 @@
                       1 0 #f
                       null (current-inspector)
                       (lambda (v stx)
-                        (raise-syntax-error
-                         #f
-                         "identifier for static struct-type information cannot be used as an expression"
-                         stx))
+                        (let-values (((kons) (cadr (extract-struct-info v))))
+                          (if kons
+                            (if (list? (syntax-e stx))
+                              (datum->syntax stx (cons kons (cdr (syntax-e stx))) stx)
+                              (if (symbol? (syntax-e stx))
+                                kons
+                                (raise-syntax-error
+                                    #f
+                                  "illegal use of struct-type identifier"
+                                  stx)))
+                            (raise-syntax-error
+                                #f
+                              "identifier for static struct-type information cannot be used as an expression"
+                              stx))))
                       null
                       (lambda (proc info)
                         (if (and (procedure? proc)
Index: collects/tests/match/examples.ss
===================================================================
--- collects/tests/match/examples.ss	(revision 12479)
+++ collects/tests/match/examples.ss	(working copy)
@@ -51,6 +51,8 @@
 
 (define-struct empt ())
 
+(define-struct T1 (x y))
+(define-struct (T2 T1) (z))
 
 (provide new-tests)
 
@@ -577,5 +579,30 @@
            [(vector a b) a]
            [else 'bad]))
 
+   
+   ;; direct struct expanders
+   (comp 3
+         (match (make-T1 1 2)
+           ((T1 x y) (+ x y))
+           (else #f)))
+   
+   (comp 3
+         (match (make-T2 1 2 3)
+           ((T1 x y) (+ x y))
+           (else #f)))
+   
+   (comp 6
+         (match (make-T2 1 2 3)
+           ((T2 x y z) (+ x y z))
+           (else #f)))
+   
+   (comp 'yes
+         (match 'foo
+           ((T1 x y) (+ x y))
+           (else 'yes)))
+   
+   (comp 'yes (with-handlers ((exn:fail:syntax? (lambda _ 'yes)))
+                (expand (quote-syntax (match 'foo ((T1 x) x))))))
+   
 
    ))
Index: collects/tests/mzscheme/struct.ss
===================================================================
--- collects/tests/mzscheme/struct.ss	(revision 12479)
+++ collects/tests/mzscheme/struct.ss	(working copy)
@@ -430,6 +430,8 @@
 (test #f struct? ai)
 (test 1 a-b ai)
 (test 2 a-c ai)
+(test #t procedure? a)
+(test #t a? (a 1 2))
 (define ai2 (make-a 1 2))
 (set-a-b! ai2 3)
 (set-a-c! ai2 4)

Posted on the users mailing list.