Implement pattern language to make spars more terse.
authorChris Hanson <org/chris-hanson/cph>
Wed, 21 Mar 2018 07:40:16 +0000 (00:40 -0700)
committerChris Hanson <org/chris-hanson/cph>
Wed, 21 Mar 2018 07:40:16 +0000 (00:40 -0700)
src/runtime/mit-macros.scm
src/runtime/runtime.pkg
src/runtime/syntax-parser.scm

index 0062502efcd941edf1ecb3b51987b900e3eb4233..bf900b940709214aa6801ac59963526a8ff84ece 100644 (file)
@@ -147,59 +147,65 @@ USA.
   (spar-transformer->runtime
    (delay
      (spar-call-with-values
-        (lambda (close identifiers expr . body-forms)
+        (lambda (close bvl expr . body-forms)
           (let ((r-cwv (close 'call-with-values))
                 (r-lambda (close 'lambda)))
             `(,r-cwv (,r-lambda () ,expr)
-                     (,r-lambda (,@identifiers) ,@body-forms))))
-       (spar-elt)
-       (spar-push spar-arg:close)
-       (spar-push-elt-if r4rs-lambda-list? spar-arg:form)
-       (spar-push-elt spar-arg:form)
-       (spar+ (spar-push-elt spar-arg:form))
-       (spar-match-null)))
+                     (,r-lambda ,bvl ,@body-forms))))
+       (pattern->spar '(ignore (push close) r4rs-bvl expr (+ form)))))
    system-global-environment))
 
-(define-syntax :define-record-type
-  (er-macro-transformer
-   (lambda (form rename compare)
-     compare                           ;ignore
-     (if (syntax-match? '((or identifier
-                             (identifier expression))
-                         (identifier * identifier)
-                         identifier
-                         * (identifier identifier ? identifier))
-                       (cdr form))
-        (let ((type-spec (cadr form))
-              (constructor (car (caddr form)))
-              (c-tags (cdr (caddr form)))
-              (predicate (cadddr form))
-              (fields (cddddr form))
-              (de (rename 'define)))
-          (let ((type (if (pair? type-spec) (car type-spec) type-spec)))
-            `(,(rename 'begin)
-              (,de ,type
-                   (,(rename 'new-make-record-type)
-                    ',type
-                    ',(map car fields)
-                    ,@(if (pair? type-spec)
-                          (list (cadr type-spec))
-                          '())))
-              (,de ,constructor (,(rename 'record-constructor) ,type ',c-tags))
-              (,de ,predicate (,(rename 'record-predicate) ,type))
-              ,@(append-map
-                 (lambda (field)
-                   (let ((name (car field)))
-                     (cons `(,de ,(cadr field)
-                                 (,(rename 'record-accessor) ,type ',name))
-                           (if (pair? (cddr field))
-                               `((,de ,(caddr field)
-                                      (,(rename 'record-modifier)
-                                       ,type ',name)))
-                               '()))))
-                 fields))))
-        (ill-formed-syntax form)))))
-
+(define :define-record-type
+  (spar-transformer->runtime
+   (delay
+     (spar-call-with-values
+        (lambda (close type-name parent maker-name maker-args pred-name
+                       field-specs)
+          (let ((beg (close 'begin))
+                (de (close 'define))
+                (mrt (close 'new-make-record-type))
+                (rc (close 'record-constructor))
+                (rp (close 'record-predicate))
+                (ra (close 'record-accessor))
+                (rm (close 'record-modifier)))
+            `(,beg
+              (,de ,type-name
+                   (,mrt ',type-name
+                         ',(map car field-specs)
+                         ,@(if parent
+                               (list parent)
+                               '())))
+              ,@(if maker-name
+                    `((,de ,maker-name
+                           (,rc ,type-name
+                                ,@(if maker-args
+                                      (list `',maker-args)
+                                      '()))))
+                    '())
+              ,@(if pred-name
+                    `((,de ,pred-name (,rp ,type-name)))
+                    '())
+              ,@(append-map (lambda (field)
+                              (let ((field-name (car field)))
+                                `((,de ,(cadr field)
+                                       (,ra ,type-name ',field-name))
+                                  ,@(if (caddr field)
+                                        `((,de ,(caddr field)
+                                               (,rm ,type-name ',field-name)))
+                                        '()))))
+                            field-specs))))
+       (pattern->spar
+       '(ignore (push close)
+                (or (seq id (push #f))
+                    (elt id expr))
+                (or (seq '#f (push #f #f))
+                    (seq id (push #f))
+                    (elt id (list (* symbol))))
+                (or (seq '#f (push #f))
+                    id)
+                (list (* (list (elt symbol id (or id (push #f))))))))))
+   system-global-environment))
+\f
 (define-syntax :define
   (er-macro-transformer
    (lambda (form rename compare)
@@ -236,21 +242,17 @@ USA.
                    (,scode-lambda-name:let ,@ids)
                    ,@body-forms)
                   ,@vals))))
-       (spar-elt)
-       (spar-push spar-arg:close)
-       (spar-or (spar-push-elt-if identifier? spar-arg:form)
-               (spar-push '#f))
-       (spar-elt
-        (spar-call-with-values list
-         (spar* (spar-elt
-                  (spar-call-with-values cons
-                    (spar-push-elt-if identifier? spar-arg:form)
-                    (spar-or (spar-push-elt spar-arg:form)
-                             (spar-push-value unassigned-expression)))
-                  (spar-match-null)))
-         (spar-match-null)))
-       (spar+ (spar-push-elt spar-arg:form))
-       (spar-match-null)))
+       (pattern->spar
+       `(ignore (push close)
+                (or id (push #f))
+                (elt
+                 (list
+                  (*
+                   (elt
+                    (cons id
+                          (or expr
+                              (push-value ,unassigned-expression)))))))
+                (+ form)))))
    system-global-environment))
 
 (define named-let-strategy 'internal-definition)
index 426f86d421f049d6b8631bd24e2cfe6b48d3574f..2856084f9e70c7298973e171c6c61501d0b6cd8e 100644 (file)
@@ -4547,6 +4547,8 @@ USA.
   (files "syntax-parser")
   (parent (runtime syntax))
   (export ()
+         pattern->spar
+         pattern->spar-expr
          spar*
          spar+
          spar-append-map-values
index ff5ef9ac7606e9642427d8246a81f34783312097..d0c0b03709be1a6bbfe895e498636b5498e406ce 100644 (file)
@@ -437,4 +437,129 @@ USA.
                            elts))))
       (spar+ (spar-elt spar-push-open-classified))
       (spar-match-null))
-    (spar-push spar-arg:senv)))
\ No newline at end of file
+    (spar-push spar-arg:senv)))
+\f
+;;;; Shorthand
+
+(define (make-pattern-compiler expr? caller)
+  (call-with-constructors expr?
+    (lambda (:* :+ :call :close :cons :elt :eqv? :form :hist :identifier? :list
+               :match-elt :match-null :mit-bvl? :opt :or :push :push-elt
+               :push-elt-if :push-value :r4rs-bvl? :senv :seq :symbol? :value)
+
+      (define (loop pattern)
+       (cond ((symbol? pattern)
+              (case pattern
+                ((symbol) (:push-elt-if (:symbol?) (:form)))
+                ((identifier id) (:push-elt-if (:identifier?) (:form)))
+                ((form expr) (:push-elt (:form)))
+                ((r4rs-bvl) (:push-elt-if (:r4rs-bvl?) (:form)))
+                ((mit-bvl) (:push-elt-if (:mit-bvl?) (:form)))
+                ((ignore) (:elt))
+                (else (bad-pattern pattern))))
+             ((procedure? pattern)
+              (:push-elt-if pattern (:form)))
+             ((and (pair? pattern)
+                   (list? (cdr pattern)))
+              (case (car pattern)
+                ((*) (apply :* (map loop (cdr pattern))))
+                ((+) (apply :+ (map loop (cdr pattern))))
+                ((?) (apply :opt (map loop (cdr pattern))))
+                ((or) (apply :or (map loop (cdr pattern))))
+                ((seq) (apply :seq (map loop (cdr pattern))))
+                ((quote)
+                 (if (not (and (pair? (cdr pattern))
+                               (null? (cddr pattern))))
+                     (bad-pattern pattern))
+                 (:match-elt (:eqv?) (cadr pattern) (:form)))
+                ((push) (apply :push (map convert-spar-arg (cdr pattern))))
+                ((push-value)
+                 (apply :push-value
+                        (cadr pattern)
+                        (map convert-spar-arg (cddr pattern))))
+                ((list) (apply :call (:list) (map loop (cdr pattern))))
+                ((cons) (apply :call (:cons) (map loop (cdr pattern))))
+                ((call) (apply :call (cadr pattern) (map loop (cddr pattern))))
+                ((spar) (apply :seq (cdr pattern)))
+                ((elt)
+                 (:elt (apply :seq (map loop (cdr pattern)))
+                       (:match-null)))
+                (else
+                 (bad-pattern pattern))))
+             (else
+              (bad-pattern pattern))))
+
+      (define (convert-spar-arg arg)
+       (case arg
+         ((form) (:form))
+         ((hist) (:hist))
+         ((close) (:close))
+         ((senv) (:senv))
+         ((value) (:value))
+         (else arg)))
+
+      (define (bad-pattern pattern)
+       (error:wrong-type-argument pattern "syntax-parser pattern" caller))
+
+      (lambda (pattern)
+       (if (not (list? pattern))
+           (bad-pattern pattern))
+       (:seq (apply :seq (map loop pattern))
+             (:match-null))))))
+\f
+(define (call-with-constructors expr? procedure)
+
+  (define (proc name procedure)
+    (if expr?
+       (lambda args (cons name args))
+       (lambda args (apply procedure args))))
+
+  (define (flat-proc name procedure)
+    (if expr?
+       (lambda args (cons name (elide-seqs args)))
+       (lambda args (apply procedure args))))
+
+  (define (elide-seqs exprs)
+    (append-map (lambda (expr)
+                 (if (and (pair? expr)
+                          (eq? 'spar-seq (car expr)))
+                     (cdr expr)
+                     (list expr)))
+               exprs))
+
+  (define (const name value)
+    (if expr?
+       (lambda () name)
+       (lambda () value)))
+
+  (procedure (flat-proc 'spar* spar*)
+            (flat-proc 'spar+ spar+)
+            (flat-proc 'spar-call-with-values spar-call-with-values)
+            (const 'spar-arg:close spar-arg:close)
+            (const 'cons cons)
+            (flat-proc 'spar-elt spar-elt)
+            (const 'eqv? eqv?)
+            (const 'spar-arg:form spar-arg:form)
+            (const 'spar-arg:hist spar-arg:hist)
+            (const 'identifier? identifier?)
+            (const 'list list)
+            (proc 'spar-match-elt spar-match-elt)
+            (proc 'spar-match-null spar-match-null)
+            (const 'mit-lambda-list? mit-lambda-list?)
+            (flat-proc 'spar-opt spar-opt)
+            (proc 'spar-or spar-or)
+            (proc 'spar-push spar-push)
+            (proc 'spar-push-elt spar-push-elt)
+            (proc 'spar-push-elt-if spar-push-elt-if)
+            (proc 'spar-push-value spar-push-value)
+            (const 'r4rs-lambda-list? r4rs-lambda-list?)
+            (const 'spar-arg:senv spar-arg:senv)
+            (flat-proc 'spar-seq spar-seq)
+            (const 'symbol? symbol?)
+            (const 'spar-arg:value spar-arg:value)))
+
+(define-deferred pattern->spar
+  (make-pattern-compiler #f 'pattern->spar))
+
+(define-deferred pattern->spar-expr
+  (make-pattern-compiler #t 'pattern->spar-expr))
\ No newline at end of file