derive2.lisp 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. ;;;; derive2.lisp
  2. ;;;;
  3. ;;;; Copyright (c) 2015 Samuel W. Flint <swflint@flintfam.org>
  4. (defpackage #:derive2
  5. (:use #:cl)
  6. (:export :derive
  7. :csc
  8. :sec))
  9. (in-package #:derive2)
  10. ;;; "derive2" goes here.
  11. (defvar *rules* '())
  12. (defun generate-match-expression (on arity &optional (type '=))
  13. (declare (symbol on type)
  14. (integer arity))
  15. (case type
  16. (=
  17. `(and (eq function ',on)
  18. (= arg-count ,arity)))
  19. (>
  20. `(and (eq function ',on)
  21. (> arg-count ,arity)))
  22. (>=
  23. `(and (eq function ',on)
  24. (>= arg-count ,arity)))))
  25. (defmacro def-expansion (name (on arity &optional type) (&rest arguments) &body expansion)
  26. (declare (ignorable name on arity type arguments expansion))
  27. (let ((match-expression (if type
  28. (generate-match-expression on arity type)
  29. (generate-match-expression on arity))))
  30. `(progn
  31. (push (list ',name
  32. (lambda (function &rest arguments &aux (arg-count (length arguments)))
  33. ,match-expression)
  34. (lambda (,@arguments)
  35. ,@expansion))
  36. *rules*)
  37. ',name)))
  38. (defun derive (function)
  39. (declare (cons function))
  40. (let ((op (first function)))
  41. (cond
  42. ((numberp op)
  43. 0)
  44. ((and (symbolp op)
  45. (= 1 (length function)))
  46. 1)
  47. (t
  48. (let ((expansion-function))
  49. (loop for (name test expander) in *rules*
  50. do (if (apply test function)
  51. (setf expansion-function expander)))
  52. (apply expansion-function (rest function)))))))
  53. ;;; End derive2