#lang scheme
(require (only-in scheme/control reset shift))
(require (only-in mzlib/trace trace))

(define run (lambda (e1) (eval `(reset ,e1))))
(trace run)

(define repeat
  (lambda (n x)
    (match n
      (0 `'())
      (_ `(append ,x ,(repeat (- n 1) x))))))
(trace repeat)

(define everyone `(shift c (forall c)))
(define someone `(shift c (exists c)))
(define bind (lambda (e1) `(shift c (let ((x ,e1)) ((c x) x)))))
(define she `(shift c c))

(define alice 'coltrane)
(define bob 'dylan)
(define love eq?)
(define forall (lambda (c) (and (c alice) (c bob))))
(define exists (lambda (c) (or  (c alice) (c bob))))

(define if_
  `(shift c (not (c (lambda (p) (lambda (q) (and p (not q))))))))

; Try applying "run" to the following code values

(define alice-loves-herself
  `(love ,(bind `alice) ,she))
(define everyone-loves-someone
  `(love ,everyone ,someone))
(define everyone-loves-someone-00 ; surface scope
  `(run `(love ,everyone ,someone)))
(define everyone-loves-someone-11 ; surface scope
  `(run `(love ',,everyone ',,someone)))
(define everyone-loves-someone-01 ; inverse scope
  `(run `(love ,everyone ',,someone)))
(define everyone-loves-someone-10 ; surface scope
  `(run `(love ',,everyone ,someone)))
(define if-someone-loves-alice-she-loves-bob
  `((,if_ (love ,(bind someone) alice)) (love ,she bob)))
(define if-someone-loves-alice-alice-loves-her
  `((,if_ (love ,(bind someone) alice)) (love alice ,she)))
(define if-someone_i-loves-someone_j-she_j-loves-she_i
  `(run `((',,if_ (love ',,(bind someone) ,(bind someone)))
          (love ,she ',,she))))