; Find the derivative of polynomial poly with repect to variable var.
; The polynomial must be in canonical infix form.
(define deriv
SS_LPAREN : "("
KW_DEFINE : "define"
  (lambda (poly var)
IDENTIFIER : "deriv"
SS_LPAREN : "("
KW_LAMBDA : "lambda"
SS_LPAREN : "("
IDENTIFIER : "poly"
IDENTIFIER : "var"
    (let* ((terms (terminize poly)) ; "terminize" the polynomial
SS_RPAREN : ")"
SS_LPAREN : "("
KW_LET_STAR : "let*"
SS_LPAREN : "("
SS_LPAREN : "("
IDENTIFIER : "terms"
SS_LPAREN : "("
IDENTIFIER : "terminize"
IDENTIFIER : "poly"
SS_RPAREN : ")"
SS_RPAREN : ")"
           (deriv-term              ; local procedure deriv-term 
SS_LPAREN : "("
IDENTIFIER : "deriv-term"
             (lambda (term)
SS_LPAREN : "("
KW_LAMBDA : "lambda"
SS_LPAREN : "("
IDENTIFIER : "term"
               (cond
SS_RPAREN : ")"
SS_LPAREN : "("
                 ((null? term) '())
KW_COND : "cond"
SS_LPAREN : "("
SS_LPAREN : "("
IDENTIFIER : "null?"
IDENTIFIER : "term"
SS_RPAREN : ")"
SS_QUOTE : "'"
SS_LPAREN : "("
SS_RPAREN : ")"
                 ((not (member? var term)) '(0))           ; deriv = 0
SS_RPAREN : ")"
SS_LPAREN : "("
SS_LPAREN : "("
IDENTIFIER : "not"
SS_LPAREN : "("
IDENTIFIER : "member?"
IDENTIFIER : "var"
IDENTIFIER : "term"
SS_RPAREN : ")"
SS_RPAREN : ")"
SS_QUOTE : "'"
SS_LPAREN : "("
NUMBER : "0" : value = 0.0
SS_RPAREN : ")"
SS_RPAREN : ")"
                 ((not (member? '^ term)) (upto var term)) ; deriv = coeff
SS_LPAREN : "("
SS_LPAREN : "("
IDENTIFIER : "not"
SS_LPAREN : "("
IDENTIFIER : "member?"
SS_QUOTE : "'"
SYMBOL : "^"
IDENTIFIER : "term"
SS_RPAREN : ")"
SS_RPAREN : ")"
SS_LPAREN : "("
IDENTIFIER : "upto"
IDENTIFIER : "var"
IDENTIFIER : "term"
SS_RPAREN : ")"
SS_RPAREN : ")"
                 (else (deriv-term-expo term var))         ; handle exponent
SS_LPAREN : "("
KW_ELSE : "else"
SS_LPAREN : "("
IDENTIFIER : "deriv-term-expo"
IDENTIFIER : "term"
IDENTIFIER : "var"
SS_RPAREN : ")"
SS_RPAREN : ")"
             )))
SS_RPAREN : ")"
SS_RPAREN : ")"
           (diff (map deriv-term terms)))   ; map deriv-term over the terms
SS_RPAREN : ")"
SS_LPAREN : "("
IDENTIFIER : "diff"
SS_LPAREN : "("
IDENTIFIER : "map"
IDENTIFIER : "deriv-term"
IDENTIFIER : "terms"
SS_RPAREN : ")"
SS_RPAREN : ")"
SS_RPAREN : ")"
      (remove-trailing-plus (polyize diff)) ; finalize the answer
SS_LPAREN : "("
IDENTIFIER : "remove-trailing-plus"
SS_LPAREN : "("
IDENTIFIER : "polyize"
IDENTIFIER : "diff"
SS_RPAREN : ")"
SS_RPAREN : ")"
)))
SS_RPAREN : ")"
SS_RPAREN : ")"

; Convert an infix polynomial into a list of sublists,
; where each sublist is a term.
(define terminize
SS_RPAREN : ")"
SS_LPAREN : "("
KW_DEFINE : "define"
  (lambda (poly)
IDENTIFIER : "terminize"
SS_LPAREN : "("
KW_LAMBDA : "lambda"
SS_LPAREN : "("
IDENTIFIER : "poly"
    (cond
SS_RPAREN : ")"
SS_LPAREN : "("
      ((null? poly) '())
KW_COND : "cond"
SS_LPAREN : "("
SS_LPAREN : "("
IDENTIFIER : "null?"
IDENTIFIER : "poly"
SS_RPAREN : ")"
SS_QUOTE : "'"
SS_LPAREN : "("
SS_RPAREN : ")"
      (else (cons (upto '+ poly) (terminize (after '+ poly))))
SS_RPAREN : ")"
SS_LPAREN : "("
KW_ELSE : "else"
SS_LPAREN : "("
IDENTIFIER : "cons"
SS_LPAREN : "("
IDENTIFIER : "upto"
SS_QUOTE : "'"
SYMBOL : "+"
IDENTIFIER : "poly"
SS_RPAREN : ")"
SS_LPAREN : "("
IDENTIFIER : "terminize"
SS_LPAREN : "("
IDENTIFIER : "after"
SS_QUOTE : "'"
SYMBOL : "+"
IDENTIFIER : "poly"
SS_RPAREN : ")"
SS_RPAREN : ")"
SS_RPAREN : ")"
)))
SS_RPAREN : ")"
SS_RPAREN : ")"
SS_RPAREN : ")"
SS_RPAREN : ")"
EOF : "null"

==== SYMBOL TABLE ====

+
^
after
cons
deriv
deriv-term
deriv-term-expo
diff
map
member?
not
null?
poly
polyize
remove-trailing-plus
term
terminize
terms
upto
var

==== TREE ====

(define deriv 
  (lambda 
    (poly var) 
    (let* 
      (
        (terms 
          (terminize poly)) 
        (deriv-term 
          (lambda 
            (term) 
            (cond 
              (
                (null? term) ' 
                ()) 
              (
                (not 
                  (member? var term)) ' 
                (0)) 
              (
                (not 
                  (member? ' ^ term)) 
                (upto var term)) 
              (else 
                (deriv-term-expo term var))))) 
        (diff 
          (map deriv-term terms))) 
      (remove-trailing-plus 
        (polyize diff)))))

==== TREE ====

(define terminize 
  (lambda 
    (poly) 
    (cond 
      (
        (null? poly) ' 
        ()) 
      (else 
        (cons 
          (upto ' + poly) 
          (terminize 
            (after ' + poly)))))))
