Browse Source

Started rewriting derivative program

Samuel W. Flint 8 years ago
parent
commit
505ff1ad40
1 changed files with 59 additions and 0 deletions
  1. 59 0
      derive2.lisp

+ 59 - 0
derive2.lisp

@@ -0,0 +1,59 @@
+;;;; derive2.lisp
+;;;;
+;;;; Copyright (c) 2015 Samuel W. Flint <swflint@flintfam.org>
+
+(defpackage #:derive2
+  (:use #:cl)
+  (:export :derive))
+
+(in-package #:derive2)
+
+;;; "derive2" goes here.
+
+(defvar *rules* '())
+
+(defun generate-match-expression (on arity &optional (type '=))
+  (declare (symbol on type)
+           (integer arity))
+  (case type
+    (=
+     `(and (eq function ',on)
+         (= arg-count ,arity)))
+    (>
+     `(and (eq function ',on)
+         (> arg-count ,arity)))
+    (>=
+     `(and (eq function ',on)
+         (>= arg-count ,arity)))))
+
+(defmacro def-expansion (name (on arity &optional type) (&rest arguments) &body expansion)
+  (declare (ignorable name on arity type arguments expansion))
+  (let ((match-expression (if type
+                              (generate-match-expression on arity type)
+                              (generate-match-expression on arity))))
+    `(progn
+       (push (list ',name
+                   (lambda (function &rest arguments &aux (arg-count (length arguments)))
+                     ,match-expression)
+                   (lambda (,@arguments)
+                     ,@expansion))
+             *rules*)
+       ',name)))
+
+(defun derive (function)
+  (declare (cons function))
+  (let ((op (first function)))
+    (cond
+      ((numberp op)
+       0)
+      ((and (symbolp op)
+          (= 1 (length function)))
+       1)
+      (t
+       (let ((expansion-function))
+         (loop for (name test expander) in *rules*
+            do (if (apply test function)
+                   (setf expansion-function expander)))
+         (apply expansion-function (rest function)))))))
+
+;;; End derive2