derive2.lisp 1.6 KB

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