git.fiddlerwoaroof.com
gen-patmatch.lisp
1a481a69
 (defpackage :patmatch
   (:use :cl :alexandria :serapeum)
   (:export pat-match))
 (in-package :patmatch)
 
 (eval-when (:compile-toplevel :load-toplevel :execute)
   (defgeneric handle-pattern (pattern form &rest args)
     (:method ((pattern cons) form &rest args)
       (let ((val-sym (gensym "VAL")))
         (destructuring-bind (car cdr) args
           `((,val-sym ,form)
             (,car (car ,val-sym))
             (,cdr (cdr ,val-sym))))))
 
     (:method ((pattern vector) form &rest args)
       (let ((val-sym (gensym "VAL")))
         `((,val-sym ,form)
           ,@ (loop for arg in args
                 for idx from 0
                 collect `(,arg (aref ,val-sym ,idx))))))
 
     (:method ((pattern hash-table) form &rest args)
       (let* ((val-sym (gensym "VAL"))
              (binding-forms (loop for (key sym) in args
                                append `((,sym (gethash ',key ,val-sym))))))
         `((,val-sym ,form)
           ,@binding-forms)))
 
     (:method ((pattern symbol) form &rest args)
       (apply #'handle-pattern
              (closer-mop:class-prototype
               (find-class pattern))
              form
              args)))) 
 
 (defmacro pattern-match ((&rest clauses) &body body)
   `(let* (,@ (loop for ((discriminator . args) val-form) in clauses
                 append (apply 'handle-pattern discriminator val-form args)))
      ,@body))
 
 
 
 (pattern-match (((hash-table (:a a) (:b b)) (plist-hash-table '(:a 1 :b 2))))
   (+ a b))