#|
Okay I want to use jmbr's ( @rwxrwxrwx@mathstodon.xyz ) polynomial rings
from cl-buchberger as lambda definitions
with my note generation.

Edit : I took out the McCLIM dependency stuff.
|#

;;; My note stuff, targetted in lispusers
;; (asdf:oos 'asdf:load-op :lispusers/tfw/high/turntable)

;;; jmbr's
(require :cl-buchberger)

;;; clim backend (not used right now)
;; (require :McCLIM)

;;; Package to play in.
(uiop:define-package music-user 
 (:mix :cl-buchberger 
;;       :clim :clim-lisp :lispusers/tfw/high/turntable
  :cl))
(in-package :music-user)

;;; Not used atm.
#|
(defvar *frame*
 (make-application-frame 'turntable 
  :note-path #P"~/synthember/008.raw"))
|#
;;; Just leave :base-ring as default
;; (defvar *ring* (make-instance 'polynomial-ring :variables '(x y z)))

;;; Some trivial polynomials.
(defvar *100* (make-polynomial 100))
(defvar *x* (make-polynomial '(expt x 1)))
(defvar *y* (make-polynomial '(expt y 1)))
(defvar *z* (make-polynomial '(expt z 1)))

;;; I found this function so hard to write, seriously, but I feel
;;; like I need it.
;;; It turns a cl-buchberger polynomial into a numerical lamdba form.
;;; Needs to be compiled (evaluated) by the caller.
;;; Note this is a run time thing even though it looks like a macro.
(defun lambdaise (poly)
 (let* ((Variables (cl-buchberger::variables
                    (cl-buchberger::base-ring poly)))
        (co-mos 
         (flet ((ret-co-mos (term)
                 (list (cl-buchberger::coefficient term)
                       (cl-buchberger::monomial term))))
          (mapterm #'ret-co-mo poly)))
        (cos (mapcar 'car co-mos))
        (mos (mapcar 'cadr co-mos)))
  `(lambda (,@variables)
    (+
     ,@(loop for co in cos for mo in mos collect
       `(* ,co
          ,@(loop for m across mo for v in variables collect
              `(expt ,v ,m))))))))

;;; Example of lambdaise returning a lambda that evaluates correctly.
(let ((form
       (lambdaise 
        (ring+ (ring* *x* *y* *y*) (ring* *100* *z*) *100*))))
 (print `(funcall (eval ,form) 1 2 3))
 (print '=)
 (print (funcall (eval form) 1 2 3))
 (print '=)
 (print 404))