;;; cont.ss
;;;   A set of continuation-passing-style functions.  Written 
;;;   as part of an answer key of CS302 98S.
;;; Author
;;;   Samuel A. Rebelsky
;;; Version
;;;   1.0 of April 1998
;;; Requires
;;;   utils.ss
;;; Copyright (c) Samuel A. Rebelsky.  All rights reserved.

;;; Add two values, calling an appropriate continuation on the result.
(define (cadd a b failcont succcont)
  (if (and (number? a) (number? b))
      (succcont (+ a b))
      (failcont "Attempted to add non-numeric values")))

;;; Subtract one value from another and call an appropriate continuation 
;;; on the result.
(define (csub a b failcont succcont)
  (if (and (number? a) (number? b))
      (succcont (- a b))
      (failcont "Attempted to subtract non-numeric values")))

;;; Multiply two values and call an appropriate continuation on the
;;; result.
(define (cmult a b failcont succcont)
  (if (not (number? a))
      (failcont "Attempted to multiply a non-numeric value")
  (if (not (number? b))
      (failcont "Attempted to multiply a non-nuemric value")
  (succcont (* a b)))))

;;; Divide one value by another and call an appropriate continuation 
;;; on the result.
(define (cdiv numerator divisor failcont succcont)
  (if (not (number? numerator))
      (failcont "Attempted to divide a non-numeric value")
  (if (not (number? divisor))
      (failcont "Attempted to divide by a non-nuemric value")
  (if (zero? divisor)
      (failcont "Attempted to divide by 0")
  (succcont (/ numerator divisor))))))

;;; Compute the square root of a nonnegative number.
(define (csqurt a failcont succcont)
  (if (not (number? a))
      (failcont "Can't compute the square root of a non-numeric value")
  (if (< a 0)
      (failcont "Can't compute the square root of a negative number")
  (succcont (sqrt a)))))

;;; Given a continuation, make a new continuation that reads and
;;; prints an error message and then calls the original continuation
;;; on 0.
(define (makefail cont)
  (lambda (err)
    (display (string-append "Failure: " err))
    (newline)
    (cont 0)))

;;; Call a CPS function with parameters A and B, using the current "real" 
;;; continuation.  Note that A and B have to be defined.
(define (call-cps cps)
  (call/cc (lambda (cont)
    (cps A B (makefail cont) cont))))
