(let ((time-stamp "Time-stamp: <2001-05-10 16:08:58 dfried>"))
  (eopl:printf "test-suite.scm: unified test suite ~a~%" (substring time-stamp 13 29)))

(initialize-test-suite!)

  chapter 3 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

  a few tests for 3 - 1 :

(add-test! 'lang3-1 'pgm3-1-1 "1" 1)

(add-test! 'lang3-1 'pgm3-1-2 "add1(x)" 11)

;; this should raise an error
(add-test! 'lang3-1 'test3-1-unbound-variable "foo" 'error)

(add-test! 'lang3-1 'test3-1-primitive-app-2 "+(x,3)" 13)

  serious tests for 3 - 5 :

(add-test! 'lang3-5 'pgm1 "1" 1)

(add-test! 'lang3-1 'pgm2 "add1(x)" 11)

;; this should raise an error
(add-test! 'lang3-5 'unbound-variable "foo" 'error)

(add-test! 'lang3-1 'primitive-app-2 "+(x,3)" 13)

(add-test! 'lang3-5 'pgm3 "if zero?(1) then 3 else 4" 4)

(add-test! 'lang3-5 'pgm4 "if zero?(0) then 3 else 4" 3)

(add-test! 'lang3-5 'pgm5 "let x = 3 y = 4 in +(x,y)" 7)

(add-test! 'lang3-1 'nested-prim-app "+(i,*(3,4))" 13)

(add-test! 'lang3-5 'let-1 "let x = 5 y = 6 in +(x,y)" 11)

(add-test! 'lang3-5 'let-to-proc-1 "(proc (x,y) +(x,y) 5 6)" 11)

(add-test! 'lang3-5 'nested-let-1 "
let z = 5 x = 3
in let x = 4
       y = +(x,z)         % here x = 3
   in *(z, +(x,y))        % here x = 4" 60)

(add-test! 'lang3-5 'nested-let-2 "
(proc (z,x)
 (proc (x,y) *(z, +(x,y)) 4 +(x,z))
 5 3)
" 60)

(add-test! 'lang3-5 'nested-let-3 "let z = let x = 3 in *(x,x) in z" 9)

(add-test! 'lang3-5 'bind-a-proc "let f = proc(x,y)+(x,y) in (f 3 4)" 7)
(add-test! 'lang3-5 'apply-a-proc "(proc(x,y)-(x,y)  4 3)" 1)


(add-test! 'lang3-5 'infinite-loop "
let fix =  proc (f)
            let d = proc (x) proc (z) (f (x x) z)
            in proc (n) (f (d d) n)
in let loop = (fix proc (f,x) (f x))
   in (loop 1)" 'dontrun)

(add-test! 'lang3-5 'poor-mans-letrec "
let fix =  proc (f)
            let d = proc (x) proc (z) (f (x x) z)
            in proc (n) (f (d d) n)
    t4m = proc (f,x) if x then +(4,(f -(x,1))) else 0
in let times4 = (fix t4m)
   in (times4 3)" 12)

(add-test! 'lang3-6 'fact-of-6  "letrec
  fact(x) = if zero?(x) then 1 else *(x, (fact sub1(x)))
in (fact 6)" 720)

(add-test! 'lang3-6 'odd-of-13  "letrec
         even(x) = if zero?(x) then 1 else (odd sub1(x))
         odd(x)  = if zero?(x) then 0 else (even sub1(x))
       in (odd 13)" 1)

(add-test! 'lang3-6 'HO-nested-letrecs
  "letrec even(odd,x) =  if zero?(x) then 1 else (odd sub1(x))
   in letrec  odd(x)  = if zero?(x) then 0 else (even odd sub1(x))
   in (odd 13)" 1)

(add-test! 'lang3-7 'gensym-test
"let g = let count = 0 in proc() 
                        let d = set count = add1(count)
                        in count
in +((g), (g))"
3)

(add-test! 'lang3-7 'even-odd-via-set "
let x = 0
in letrec even() = if zero?(x) then 1 
                                  else let d = set x = sub1(x)
                                       in (odd)
              odd()  = if zero?(x) then 0 
                                  else let d = set x = sub1(x)
                                       in (even)
   in let d = set x = 13 in (odd)" 1)

(add-test! 'lang3-8ref 'basic-by-ref "
let x = 13
    f = proc (y) set y = add1(y)
in begin
    (f x); 
    x
   end"
14)

(add-test! 'lang3-8ref 'swap-by-ref "
let a = 3
    b = 4
    swap = proc (x, y)
             let temp = x
             in begin
                  set x = y;
                  set y = temp
                end
in begin
     (swap a b);
     -(a,b)
   end"
  1 by reference , -1 by value



(add-test! 'lang3-8name 'basic-by-name "
let x = 13
    f = proc (y) set y = add1(y)
in begin
    (f x); 
    x
   end"
14)

(add-test! 'lang3-8name 'swap-by-name "
let a = 3
    b = 4
    swap = proc (x, y)
             let temp = x
             in begin
                  set x = y;
                  set y = temp
                end
in begin
     (swap a b);
     -(a,b)
   end"
  1 by reference , -1 by value

(add-test! 'lang3-8name 'ignore-arg-name "
let a = 3
in let f = proc () set a = add1(a)
       g = proc (x) 11
   in begin 
        (g (f));
        a
      end"
3)

(add-test! 'lang3-8name 'check-multiple-evals-by-name "
let g = let count = 0 in proc () begin 
                                   set count = add1(count); 
                                   count
                                 end
in (proc(x) +(x,x)
    (g))"
  3 for name , 2 for need

(add-test! 'lang3-8need 'basic-by-need "
let x = 13
    f = proc (y) set y = add1(y)
in begin
    (f x); 
    x
   end"
14)

(add-test! 'lang3-8need 'swap-by-need "
let a = 3
    b = 4
    swap = proc (x, y)
             let temp = x
             in begin
                  set x = y;
                  set y = temp
                end
in begin
     (swap a b);
     -(a,b)
   end"
  1 by reference , -1 by value

(add-test! 'lang3-8need 'ignore-arg-by-need "
let a = 3
in let f = proc () set a = add1(a)
       g = proc (x) 11
   in begin 
        (g (f));
        a
      end"
3)

(add-test! 'lang3-8need 'check-multiple-evals-by-need "
let g = let count = 0 in proc () begin 
                                   set count = add1(count); 
                                   count
                                 end
in (proc(x) +(x,x)
    (g))"
  3 for name , 2 for need


;; the test harness doesn't look at output, so these tests are pretty
;; useless. 

(add-test! 'lang3-9 'print-1 "print(10)" #t) 

(add-test! 'lang3-9 'pgm3-9-1 "var x,y; {x = 3; y = 4; print(+(x,y))}"
  #t)

(add-test! 'lang3-9 'pgm3-9-2 "
  { x = 3 ; y = 4 ; z = 0 ;
  x =  ) } ;
            print(z)}"
  #t)

(add-test! 'lang3-9 'pgm3-9-3 "
  { x = 3 ; print(x ) ;
  { x = 4 ; print(x ) } ;
        print(x)}"
  #t)

(add-test! 'lang3-9 'pgm3-9-4 "
var f,x; {f = proc (x, y) *(x,y);
          x = 3;
          print((f 4 x))}"
  #t)


  chapter 4 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

(add-typed-test! 'lang4-2 'literal "1" 'int 1)

;; this one should now raise a type error
(add-typed-test! 'lang4-2 'primitive-app-1 "add1(x)" 'error 'dontrun)

(add-typed-test! 'lang4-2 'primitive-app-2-typed "+(2,3)" 'int 5)

(add-typed-test! 'lang4-2 'primitive-app-3 "+(2,true)" 'error 'dontrun)

(add-typed-test! 'lang4-2 'type-a-proc-1 "proc(int x, bool y) x"
  '(int * bool -> int) 'dontrun)

(add-typed-test! 'lang4-2 'type-ho-proc-1
      "proc(int x, (int * int -> bool) f) (f x 3)"
      '(int * (int * int -> bool) -> bool)
      'dontrun)

(add-typed-test! 'lang4-2 'type-ho-proc-2
      "proc(int x, (int * int -> bool) f) (f x true)"
      'error 'dontrun)

(add-typed-test! 'lang4-2 'apply-a-proc-typed
  "(proc(int x, int y)-(x,y)  4 3)"
  'int 1)

(add-typed-test! 'lang4-2 'simple-let "let x = 3 y = 4 in +(x,y)" 'int 7) 

(add-typed-test! 'lang4-2 'bind-a-proc-typed
  "let f = proc (int x) add1(x) in (f 4)" 'int 5) 

(add-typed-test! 'lang4-2 'bind-a-proc-return-proc
  "let f = proc (int x) add1(x) in f"
  '(int -> int) 'dontrun)

(add-typed-test! 'lang4-2 'apply-ho-proc "
let apply = proc ((int * int -> int) f, int x) (f add1(x) x)
    g     = proc (int x, int y) *(x,y)
in (apply g 3)"
  'int 12)

(add-typed-test! 'lang4-2 'wrong-no-of-args "let f = proc (int x) add1(x) in (f 4 3)" 'error 'dontrun)

(add-typed-test! 'lang4-2 'unbound-variable-2 "let f = proc (int x) add1(x) in (g 4 3)" 'error 'dontrun)

(add-typed-test! 'lang4-2 'apply-a-proc-2-typed "(proc (int x) add1(x) 4)" 'int 5)

(add-typed-test! 'lang4-2 'apply-a-letrec "
letrec int f(int x, int y) = +(x,y) 
in (f 40 50)"
  'int 90)

(add-typed-test! 'lang4-2 'letrec-return-fact "
letrec 
  int fact(int x)= if zero?(x) then 1 else *(x, (fact sub1(x)))
in fact" '(int -> int) 'dontrun)

(add-typed-test! 'lang4-2 'letrec-apply-fact "
letrec 
  int fact(int x)= if zero?(x) then 1 else *(x, (fact sub1(x)))
in (fact 6)" 'int 720)

(add-typed-test! 'lang4-2 'letrec-return-odd "
letrec int odd(int x)  = if zero?(x) then 0 else (even sub1(x))
       int even(int x) = if zero?(x) then 1 else (odd  sub1(x))
in odd"
  '(int -> int) 'dontrun)

(add-typed-test! 'lang4-2 'letrec-apply-odd "
letrec int odd(int x)  = if zero?(x) then 0 else (even sub1(x))
       int even(int x) = if zero?(x) then 1 else (odd  sub1(x))
in (odd 13)" 'int 1)

(add-typed-test! 'lang4-2 'apply-fcn-to-wrong-type "
letrec int odd(int x)  = if zero?(x) then 0 else (even sub1(x))
       int even(int x) = if zero?(x) then 1 else (odd  sub1(x))
in (even odd)" 'error 'dontrun)

(add-typed-test! 'lang4-2 'types-fail-but-program-works "
let fix =  proc (int f)
            let d = proc (int x) proc (int z) (f (x x) z)
            in proc (int n) (f (d d) n)
    t4m = proc (int f, int x) if x then +(4,(f -(x,1))) else 0
in let times4 = (fix t4m)
   in (times4 3)" 'error 12)

;;; a good one to add types to.
  ( add - typed - test ! '  - 4 ' pgm11
    " letrecproc even(odd , x ) =   if  ) then 1 else ( odd  ) )
     in letrecproc   odd(x )   = if  ) then 0 else ( even odd  ) )
     in ( odd 13 ) " ' error 1 )

(add-typed-test! 'lang4-3 'lettype-type-check-exported-fcn "
lettype foo = int
 foo m(int x) = add1(x)
in m" '(int -> foo) 'dontrun)

(add-typed-test! 'lang4-3 'lettype-apply-exported-fcn-1 "
lettype foo = int
 foo m(int x) = add1(x)
in (m 3)"
  'foo 4)

(add-typed-test! 'lang4-3 'lettype-foo-isnt-int  "
lettype foo = int
 foo m (int x) = add1(x)
in add1((m 3))"
  'error 5)

(add-typed-test! 'lang4-3 'lettype-error-in-defns "
lettype ff = (int -> int)
  ff zero-ff (int k) = 0                % a real type error!
  ff extend-ff (int k, int val, ff old-ff) =
       proc (int k1) if zero?(-(k1,k)) then val else (old-ff k1)
  int apply-ff (int k, ff f) = (f k)
in let ff1 = (extend-ff 1 11 (extend-ff 2 22 zero-ff))
   in (apply-ff ff1 2)"
'error 'dontrun)

(add-typed-test! 'lang4-3 'opaque-finite-fcns-0 "
lettype ff = (int -> int)
  ff zero-ff () = proc (int k) 0               
  ff extend-ff (int k, int val, ff old-ff) =
       proc (int k1) if zero?(-(k1,k)) then val else (old-ff k1)
  int apply-ff (ff f, int k) = (f k)
in let ff1 = (extend-ff 1 11 (extend-ff 2 22 (zero-ff)))
   in (apply-ff ff1 2)" 'int 22)



(add-typed-test! 'lang4-3 'opaque-finite-fcns-letrec-of-internal-fcns "
lettype ff = (int -> int)
  ff zero-ff () = proc (int k) 0               
  ff extend-ff (int k, int val, ff old-ff) =
       proc (int k1) if zero?(-(k1,k)) then val else (apply-ff old-ff k1)
  int apply-ff (ff f, int k) = (f k)
in let ff1 = (extend-ff 1 11 (extend-ff 2 22 (zero-ff)))
   in (apply-ff ff1 2)" 'int 22)

(add-typed-test! 'lang4-3 'opaque-finite-fcns-try-violating-abstraction-boundary "
lettype ff = (int -> int)
  ff zero-ff () = proc (int k) 0               
  ff extend-ff (int k, int val, ff old-ff) =
       proc (int k1) if zero?(-(k1,k)) then val else (old-ff k1)
  int apply-ff (ff f, int k) = (f k)
in let ff1 = (extend-ff 1 11 (extend-ff 2 22 (zero-ff)))
   in (ff1 2)"
  ' error , 22


(add-typed-test! 'lang4-3 'myint1 "
lettype
  myint = int  % like the integers, but zero is represented as 1!
  myint zero() = 1
  myint succ(myint x) = add1(x)
  myint pred(myint x) = sub1(x)
  bool  iszero?(myint x) =  zero?(-(x,1))
in (succ (zero))"
  myint , 2

(add-typed-test! 'lang4-3 'myint2 "
lettype
  myint = int  % like the integers, but zero is represented as 1!
  myint zero() = 1
  myint succ(myint x) = add1(x)
  myint pred(myint x) = sub1(x)
  bool  iszero?(myint x) =  zero?(-(x,1))
in add1((zero))"
  'error 2)   

;;; tests of type inference

(add-typed-test! 'lang4-4 'pgm4b "let f = proc (? x) add1(x) in (f 4)"
  'int 5)

(add-typed-test! 'lang4-4 'pgm4-0b "let f = proc (? x) add1(x) in f"
  '(int -> int) 'dontrun)

(add-typed-test! 'lang4-4 'pgm4-1b "
let apply = proc (?f, ? x) (f add1(x) x)
    g     = proc (? x, ? y) *(x,y)
in (apply g 3)"
  int , 12

(add-typed-test! 'lang4-4 'pgm6b "letrec int f(? x,? y) = +(x,y) 
              in (f 40 50)"
  int , 90

(add-typed-test! 'lang4-4 'pgm7b "
letrec 
  ? fact(? x)= if zero?(x) then 1 else *(x, (fact sub1(x)))
in fact"
  '(int -> int) 'dontrun)

(add-typed-test! 'lang4-4 'pgm8b "
letrec ? odd(? x)  = if zero?(x) then 0 else (even sub1(x))
       ? even(? x) = if zero?(x) then 1 else (odd  sub1(x))
in odd" '(int -> int) 'dontrun)


(add-typed-test! 'lang4-4 'pgm8ab "
letrec ? odd(? x)  = if zero?(x) then 0 else (even sub1(x))
       ? even(bool x) = if zero?(x) then 1 else (odd  sub1(x))
in (odd 13)" 'error 'dontrun)

;; circular type
(add-typed-test! 'lang4-4 'circular-type "
let fix =  proc (? f)
            let d = proc (? x) proc (? z) (f (x x) z)
            in proc (? n) (f (d d) n)
    t4m = proc (? f, ? x) if zero?(x) then 0 else +(4,(f -(x,1)))
in let times4 = (fix t4m)
   in (times4 3)"
  'error 12)

(add-typed-test! 'lang4-4 'pgm11b
  "letrec ? even(? odd, ? x) =  if zero?(x) then 1 else (odd sub1(x))
   in letrec  ? odd(? x)  = if zero?(x) then 0 else (even odd sub1(x))
   in (odd 13)"
  'int 1)

(add-typed-test! 'lang4-4 'infer-in-body-using-opaque-type "
lettype
  myint = int  % like the integers, but zero is represented as 1!
  myint zero() = 1
  myint succ(myint x) = add1(x)
  myint pred(myint x) = sub1(x)
  bool  iszero?(myint x) =  zero?(-(x,1))
in letrec ? plus(? x,? y) = if (iszero? x) then y else (succ (plus (pred x) y))
in plus"
  '(myint * myint -> myint)  'dontrun)

(add-typed-test! 'lang4-4 'infer-in-impl-1 "
lettype
  myint = int  % like the integers, but zero is represented as 1!
  myint zero() = 1
  myint succ(myint x) = let f = proc(? x) x in add1((f x))
  myint pred(myint x) = sub1(x)
  bool  iszero?(myint x) =  zero?(-(x,1))
in letrec ? plus(? x,? y) = if (iszero? x) then y else (succ (plus (pred x) y))
in plus"
      '(myint * myint -> myint)  'dontrun)

(add-typed-test! 'lang6 'create-empty-class
  "class c1 extends object  3" 'int 3)

(add-typed-test! 'lang6 'create-class-with-method "
class c1 extends object 
 field int y 
 method int gety()y
  
33 "
'int 33)

(add-typed-test! 'lang6 'create-object "
class c1 extends object  
 method int initialize()0 
let o1 = new c1() in 11
" 'int 11)


(add-typed-test! 'lang6 'send-msg-1 "
class c1 extends object 
 field int s
 method void initialize()set s = 44
 method int gets()s
 method void sets(int v)set s = v                               

let o1 = new c1() in send o1 gets()
"
'int 44)

;; these tests are more serious


(add-typed-test! 'lang6 'send-msg-2 "
class c1 extends object 
          field int s 
          method void initialize()set s = 44 
          method int gets()s
          method int sets(int v)set s = v  % type error here
                
let o1 = new c1() 
    t1 = 0
    t2 = 0 
in begin
     set t1 = send o1 gets();
     send o1 sets(33);
     set t2 = send o1 gets();
     list(t1, t2)
  end
"
'error '(44 33))

  chapter 5 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

(add-test! 'oop 'create-empty-class
  "class c1 extends object  3" 3)

(add-test! 'oop 'create-class-with-method "
class c1 extends object 
  field y 
  method gety () y 
33                       % 33 is the body"
33)

(add-test! 'oop 'create-object "
class c1 extends object  
 method initialize()0 
let o1 = new c1() in 11
" 11)


(add-test! 'oop 'send-msg-1 "
class c1 extends object 
  field s 
  method initialize() set s = 44
  method gets()s
  method sets(v)set s = v
  
let o1 = new c1() in send o1 gets()
"
44)

(add-test! 'oop 'send-msg-2 "
class c1 extends object 
  field s 
  method initialize() set s = 44
  method gets()s
  method sets(v)set s = v
  
let o1 = new c1() 
    t1 = 0
    t2 = 0 
in begin
     set t1 = send o1 gets();
     send o1 sets(33);
     set t2 = send o1 gets();
     list(t1, t2)
  end
"
'(44 33))

(add-test! 'oop 'test-self-1 "
class c extends object 
  field s
  method initialize(v)set s = v
  method sets(v)set s = v
  method gets()s
  method testit()send self sets(13)
  
let o = new c (11)
       t1 = 0
       t2 = 0
   in begin 
       set t1 = send o gets();
       send o testit();
       set t2 = send o gets();
       list(t1,t2)
      end" '(11 13))

(add-test! 'oop 'chris-1 "
class aclass extends object 
  field i
  method initialize(x) set i = x
  method m(y) +(i,y)
  
let o1 = new aclass(3)
in send o1 m(2)"
5)

(add-test! 'oop 'for-book-1 "
class c1 extends object
  field i
  field j
  method initialize(x) begin set i = x; set j = -(0,x) end
  method countup(d) begin set i = +(i,d); set j = -(j,d) end
  method getstate()list(i,j)
  
let o1 = new c1(3)
    t1 = 0
    t2 = 0
in begin
    set t1 = send o1 getstate();
    send o1 countup(2);
    set t2 = send o1 getstate();
    list(t1,t2)
   end"
'((3 -3) (5 -5)))


(add-test! 'oop 'odd-even-via-self "
class oddeven extends object 
  method initialize()1
  method even(n)if zero?(n) then 1 else send self odd(sub1(n))
  method odd(n) if zero?(n) then 0 else send self even(sub1(n))
  
let o1 = new oddeven() in send o1 odd(13)"
1)

;;; inheritance starts here

(add-test! 'oop 'inherit-1 "
class c1 extends object 
  field ivar1
  method initialize()set ivar1 = 1
  
class c2 extends c1 
  field ivar2
  method initialize() 
   begin
    super initialize(); 
    set ivar2 = 1
   end
  method setiv1(n)set ivar1 = n
  method getiv1()ivar1
  
let o = new c2 ()
    t1 = 0
in begin
       send o setiv1(33);
       send o getiv1()
   end                      
" 33)

(add-test! 'oop 'inherit-2 "
class c1 extends object 
  field ivar1
  method initialize()set ivar1 = 1

  method setiv1(n)set ivar1 = n
  method getiv1()ivar1

  method foo()1
  method call-foo-from-superclass()send self foo()

  
class c2 extends c1 
  field ivar2
  method initialize() 
  set ivar2 = 1 end
   

  method foo()2

  method setiv2(n)set ivar2 = n
  method getiv2()ivar2

  method self-and-super-foo()
    list( send self foo(),  super foo())

  method test-self-from-super()
     super call-foo-from-superclass()

   
let o = new c2 ()
    t1 = 0 t2 = 0 t3 = 0 t4 = 0
in begin
       send o setiv1(33);
       list(
         send o getiv1(),
         send o self-and-super-foo(),
         send o call-foo-from-superclass(),
         send o test-self-from-super()
         )
      end                      
" '(33 (2 1) 2 2))

      ( inherit-2 , inherit-2 ( 33 ( 2 1 ) 2   2 22 33 ) )

(add-test! 'oop 'inherit-3 "
class c1 extends object 
  method initialize()1
  method m1()1
  
class c2 extends c1 
  method m1()super m1()
  method m2()2
  
class c3 extends c2 
  method m1()3
  method m2()super m2()
  method m3()super m1()
  
let o = new c3 ()
in list( send o m1(),
         send o m2(),
         send o m3()
        )
" '(3 2 1))

   's first example
; program
;   let a = new aclass init(3)
;   in call a m(2)
;   class aclass (i)
;     method init(x) fieldassign aclass this i = x;
;     method m(y) +(field aclass this i, y)
;   end
; end


(add-test! 'oop 'chris-2 "
class c1 extends object 
  method initialize() 1
  method ma()1
  method mb()send self ma()
  
class c2 extends c1   % just use c1's initialize
  method ma() 2
  
let x = new c2 ()
in list(send x ma(),send x mb())
"
'(2 2))


(add-test! 'oop 'for-book-2 "
class c1 extends object 
  method initialize()1
  method m1()1
  method m2()100
  method m3()send self m2()
  
class c2 extends c1 
  method m2()2
  
let o1 = new c1()
    o2 = new c2()
in list(send o1 m1(),           % returns 1
        send o1 m2(),           % returns 100
        send o1 m3(),           % returns 100
        send o2 m1(),           % returns 1 (from c1)
        send o2 m2(),           % returns 2 (from c2)
        send o2 m3()            % returns 2 (c1's m3 calls c2's m2)
       )
"
'(1 100 100 1 2 2))

(add-test! 'oop 'sum-leaves "
class tree extends object 
  method initialize()1
  
class interior_node extends tree 
  field left
  field right
  method initialize(l,r)
   begin
    set left = l; set right = r
   end
  method sum()+(send left sum(), send right sum())
  
class leaf_node extends tree 
  field value
  method initialize(v)set value = v
  method sum()value
  
let o1 = new interior_node (
          new interior_node (
            new leaf_node(3),
            new leaf_node(4)),
          new leaf_node(5))
in send o1 sum()
"
12)

(add-test! 'oop 'check-shadowed-fields "
class c1 extends object 
  field x
  field y
  method initialize(v) begin set x = v; set y = 0 end
  method m1() x

class c2 extends c1 
  field x
  method initialize(v1,v2) begin set x = v2; 
                                    super initialize(v1) end
  method m2()list(x,y)

class c3 extends c2 
  field x
  method initialize(v1,v2,v3) begin set x = v3; 
                                       super initialize(v1,v2)
                                 end
  method m3()x

let o = new c3(1,2,3)
in list (send o m1(), send o m2(), send o m3())
"
'(1 (2 0) 3))

(add-test! 'oop 'static-super "
class c1 extends object
 method initialize () 1
 method m2() send self m3()
 method m3() 13
class c2 extends c1
 method m2() 22
 method m3() 23
 method m1() super m2()
class c3 extends c2
 method m2() 32
 method m3() 33
let o3 = new c3()
in send o3 m1()"
33)



(add-typed-test! 'lang6 'test-self-1 "
class c extends object 
         field int s
         method void initialize(int v)set s = v
         method void sets(int v)set s = v    
         method int gets()s
         method void testit()send self sets(13)
              
let o = new c (11)
       t1 = 0
       t2 = 0
   in begin 
       set t1 = send o gets();
       send o testit();
       set t2 = send o gets();
       list(t1,t2)
      end" '(list int) '(11 13))

  chapter 6 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

(add-typed-test! 'lang6 'counter-1 "
class counter extends object
  field int count
   method void initialize()set count = 0
   method void countup()set count = add1(count)
   method int getcount()count
   
let o1 = new counter ()
    t1 = 0
    t2 = 0
in begin
    set t1 = send o1 getcount();
    send o1 countup();
    set t2 = send o1 getcount();
    list(t1,t2)
end
" '(list int) '(0 1))

(add-typed-test! 'lang6 'shared-counter-1 "
class counter extends object
  field int count
   method void initialize()set count = 0
   method void countup()set count = add1(count)
   method int getcount()count
   
class c1 extends object 
   field int n
   field counter counter1
   method void initialize(counter a_counter)
    begin
     set n = 0;
     set counter1 = a_counter
    end
   method void countup()
     begin
      send counter1 countup();
      set n = add1(n)
     end
   method list int getstate()list(n, send counter1 getcount())
   
let counter1 = new counter()
in let o1 = new c1(counter1)
       o2 = new c1(counter1)
in begin
     send o1 countup();
     send o2 countup();
     send o2 countup();
     list( send o1 getstate(),
           send o2 getstate())
   end
" '(list (list int)) '((1 3) (2 3)))


(add-typed-test! 'lang6 'inherit-1 "
class c1 extends object 
  field int ivar1
  method void initialize()set ivar1 = 1
  
class c2 extends c1 
  field int ivar2
  method void initialize() 
   begin
    super initialize(); 
    set ivar2 = 1
   end
  method void setiv1(int n)set ivar1 = n
  method int getiv1()ivar1
  
let o = new c2 ()
    t1 = 0
in begin
       send o setiv1(33);
       send o getiv1()
   end                      
" 'int 33)

(add-typed-test! 'lang6 'inherit-3 "
class c1 extends object 
  method int initialize()1
  method int m1()1
  
class c2 extends c1 
  method int initialize()1 
  method int m1()super m1()
  method int m2()2
  
class c3 extends c2 
  method int initialize()1
  method int m1()3
  method int m2()super m2()
  method int m3()super m1()
  
let o = new c3 ()
in list( send o m1(),
         send o m2(),
         send o m3()
        )
"  '(list int) '(3 2 1))

(add-typed-test! 'lang6 'chris-1 "
class aclass extends object 
  field int i
  method void initialize(int x) set i = x
  method int m(int y) +(i,y)
  
let o1 = new aclass(3)
in send o1 m(2)"
'int 5)

(add-typed-test! 'lang6 'chris-2 "
class c1 extends object 
  method int initialize() 1
  method int ma()1
  method int mb()send self ma()
  
class c2 extends c1   % just use c1's initialize
  method int ma() 2
  
let x = new c2 ()
in list(send x ma(),send x mb())
"
'(list int) '(2 2))

(add-typed-test! 'lang6 'for-book-1 "
class c1 extends object 
  field int i
  field int j
  method void initialize(int x) begin set i = x; set j = -(0,x) end
  method void countup(int d) begin set i = +(i,d); set j = -(j,d) end
  method list int getstate()list(i,j)
  
let o1 = new c1(3)
    t1 = nil[int]
    t2 = nil[int]
in begin
    set t1 = send o1 getstate();
    send o1 countup(2);
    set t2 = send o1 getstate();
    list(t1,t2)
   end"
'(list (list int)) '((3 -3) (5 -5)))


(add-typed-test! 'lang6 'odd-even-via-self "
class oddeven extends object 
  method int initialize()1
  method bool even(int n)if zero?(n) then true else send self odd(sub1(n))
  method bool odd(int n) if zero?(n) then false else send self even(sub1(n))
  
let o1 = new oddeven() in send o1 odd(13)"
'bool 1)

(add-typed-test! 'lang6 'for-book-2 "
class c1 extends object 
  method int initialize()1
  method int m1()1
  method int m2()100
  method int m3()send self m2()
  
class c2 extends c1 
  method int initialize()1
  method int m2()2
  
let o1 = new c1()
    o2 = new c2()
in list(send o1 m1(),           % returns 1
        send o1 m2(),           % returns 100
        send o1 m3(),           % returns 100
        send o2 m1(),           % returns 1 (from c1)
        send o2 m2(),           % returns 2 (from c2)
        send o2 m3()            % returns 2 (c1's m3 calls c2's m2)
       )
"
'(list int) '(1 100 100 1 2 2))

(add-typed-test! 'lang6 'sum-leaves "
class tree extends object 
  method int initialize()1
  
class interior_node extends tree 
  field node left
  field node right
  method void initialize(node l, node r)
   begin
    set left = l; set right = r
   end
  method int sum()+(send left sum(), send right sum())
  
class leaf_node extends tree 
  field int value
  method void initialize(int v)set value = v
  method int sum()value
  
let o1 = new interior_node (
          new interior_node (
            new leaf_node(3),
            new leaf_node(4)),
          new leaf_node(5))
in send o1 sum()
"
'error 12)

(add-typed-test! 'lang6 'sum-leaves-2 "
abstract class tree extends object 
  method int initialize()1
  
class interior_node extends tree 
  field tree left
  field tree right
  method void initialize(tree l, tree r)
   begin
    set left = l; set right = r
   end
  method int sum()+(send left sum(), send right sum())
  
class leaf_node extends tree 
  field int value
  method void initialize(int v)set value = v
  method int sum()value
  
let o1 = new interior_node (
          new interior_node (
            new leaf_node(3),
            new leaf_node(4)),
          new leaf_node(5))
in send o1 sum()
"
'error 12)

(add-typed-test! 'lang6 'sum-leaves-with-abstract-method "
abstract class tree extends object 
  method int  initialize()1
  abstractmethod int sum()
  
class interior_node extends tree 
  field tree left
  field tree right
  method void initialize(tree l, tree r)
   begin
    set left = l; set right = r
   end
  method int sum()+(send left sum(), send right sum())
  
class leaf_node extends tree 
  field int value
  method void initialize(int v)set value = v
  method int sum()value
  
let o1 = new interior_node (
          new interior_node (
            new leaf_node(3),   %% need subtyping to make this ok.
            new leaf_node(4)),
          new leaf_node(5))
in send o1 sum()
"
'int 12)


(add-typed-test! 'lang6 'equal-trees-1 "
abstract class tree extends object 
  method int  initialize()1
  abstractmethod int sum()
  abstractmethod bool equal(tree t)
  
class interior_node extends tree 
  field tree left
  field tree right
  method void initialize(tree l, tree r)
   begin
    set left = l; set right = r
   end
  method tree getleft()left
  method tree getright()right
  method int sum()+(send left sum(), send right sum())
  method bool equal(tree t) 
    if instanceof t interior_node
     then if send left equal(send cast t interior_node getleft())
          then send right equal(send cast t interior_node getright())
          else false
     else false 
     
  
class leaf_node extends tree 
  field int value
  method void initialize(int v)set value = v
  method int sum()value
  method int getvalue()value
  method bool equal(tree t) 
   if instanceof t leaf_node
    then zero?(-(value, send cast t leaf_node getvalue()))
    else false
    
  
let o1 = new interior_node (
          new interior_node (
            new leaf_node(3),   
            new leaf_node(4)),
          new leaf_node(5))
in send o1 equal(o1)
"
'bool 1)

(add-typed-test! 'lang6 'bad-cast-1 "
class c1 extends object 
class c2 extends object 
proc (c1 o) cast o c2
"
'error 'dontrun)

(add-typed-test! 'lang6 'good-instanceof-1 "
class c1 extends object 
class c2 extends object 
let p = proc (c1 o) instanceof o c2 in 11
"
'int 11)

(add-typed-test! 'lang6 'up-cast-1 "
class c1 extends object 
  method int initialize ()1
  method int get()2
  
class c2 extends c1 
let f = proc (c2 o) send cast o c1 get() in (f new c2())
"
'int 2)

(add-typed-test! 'lang6 'up-instance-1 "
class c1 extends object 
  method int initialize ()1
  method int get()2
  
class c2 extends c1 
let f = proc (c2 o) instanceof o c1 in (f new c2())
"
'bool 1)

(add-typed-test! 'lang6 'missing-initialize-method-1 "
class c1 extends object 
  method int initialize ()1
  method int get()2
  
class c2 extends object   % no initialize method!
let f = proc (c2 o) instanceof o c1 in (f new c2())
"
'error 'dontrun)

(add-typed-test! 'lang6 'duplicate-methods-1 "
class c1 extends object
  method int initialize() 1
class c2 extends c1
  method int m1() 1
  method int m1() 2
33"
'error 33)

(add-typed-test! 'lang6 'incomparable-instanceof-2 "
class c1 extends object 
  method int initialize ()1
  method int get()2
  
class c2 extends object 
  method int initialize () 100
    
let f = proc (c2 o) if instanceof o c1 then 1 else 2 in (f new c2())
"
'int 2)

(add-typed-test! 'lang6 'equal-trees-by-double-dispatch "
abstract class tree extends object 
  method int  initialize()1
  abstractmethod int sum()
  abstractmethod bool equal(tree t)
  abstractmethod bool equal_int(tree l, tree r)
  abstractmethod bool equal_leaf(int val)
  
class interior_node extends tree 
  field tree left
  field tree right
  method void initialize(tree l, tree r)
   begin
    set left = l; set right = r
   end
  method int sum()+(send left sum(), send right sum())
  method bool equal(tree t) send t equal_int(left, right)
  method bool equal_int(tree l, tree r) 
     if send left equal(l)
     then send right equal(r)
     else false
     
  method bool equal_leaf(int v) false
  
class leaf_node extends tree 
  field int value
  method void initialize(int v)set value = v
  method int sum()value
  method bool equal(tree t) send t equal_leaf(value)
  method bool equal_int(tree l, tree r) false
  method bool equal_leaf(int otherval) zero?(-(value, otherval))
  
let o1 = new interior_node (
          new interior_node (
            new leaf_node(3),   
            new leaf_node(4)),
          new leaf_node(5))
in send o1 equal(o1)
"
'bool 1)

(add-typed-test! 'lang6 'bad-super-1 "
class c1 extends object 
 method int initialize() 1
 
class c2 extends c1 
 method int m1() super m2()
 
class c3 extends c2 
 method int m2() 2
 
class c4 extends c3 
let o = new c4() in send o m1()
"
'error 'dontrun)

(add-typed-test! 'lang6 'missing-concrete "
class c1 extends object 
 method int initialize() 1
 abstractmethod int foo()
 
class c2 extends c1 
let o = new c2() in 33"
'error 33)

(add-typed-test! 'lang6 'cant-apply-abstract-method "
class c1 extends object 
 method int initialize() 1
 abstractmethod int m()
 
let o = new c1() in send o m()
"
'error 'dontrun)

(add-typed-test! 'lang6 'cant-apply-abstract-super "
abstract class c1 extends object 
  abstractmethod int m1()
 
class c2 extends c1 
 method int m1 () 1
 method int m2 () super m1 ()
 
33"
'error 'dontrun)

(add-typed-test! 'lang6 'goldberg-80 "
class c1 extends object 
  method int initialize () 1
  method int test () 1
  method int result1 () send self test ()
  
class c2 extends c1 
  method int test () 2
  
class c3 extends c2 
  method int result2 () send self result1 ()
  method int result3 () super test ()
  
class c4 extends c3 
  method int test () 4
  
let o3 = new c3 ()
    o4 = new c4 ()
in list(send o3 test(),
        send o4 result1 (),
        send o3 result2 (),   
        send o4 result2 (),
        send o3 result3 (),
        send o4 result3 ())
"
'(list int) '(2 4 2 4 2 2))

(add-typed-test! 'lang6 'abstract-method-never-overridden "
abstract class c1 extends object 
  abstractmethod int m1() 
  
class c2 extends c1 
  method int m2 ()send self m1()
  
33"
'error 'dontrun)

(add-typed-test! 'lang6 'overriding-method-changes-type-1 "
abstract class c1 extends object 
  abstractmethod int m1()
  
class c2 extends c1 
  method bool m1() false
  
33"
'error 'dontrun)

(add-typed-test! 'lang6 'test6-3-1 "
abstract class c1 extends object
 method int initialize () 1 
 method int m1 () 11
 abstractmethod int m2 () 
class c2 extends c1 
 method int m1 () 21
 method int m2 () 22
 method int m3 () 23
class c3 extends c2 
 method int m4 () 34
class c4 extends c3 
 method int m2 () 42 
proc (c3 o) send o m2()
"
'(c3 -> int) 'dontrun)

  chapter 7 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

  most of chapter 7 reuses the languages from chapter 3 .

  only a simple test for 7.4 :

(add-test! 'lang7-4 'raise-exception-1 "
let index = proc (n, l)
              letrec                            
                loop (l) = if null?(l) 
                           then raise sub1(0)  
                           else if equal?(n,car(l)) 
                                then 0   
                                else add1((loop cdr(l)))
              in try (loop l) handle proc (x) x
in (index 1 list(2,3))"
-1)

  for 7.5 , the final answers capture only a small part of the
;; program's behavior.

(add-test! 'lang7-5 'pgm7-5-1 "
let acc = 0 done = 0
in let d = spawn set acc = 20
   in letrec 
        loop () = if acc 
                  then let d = set done = 1
                       in acc
                  else (loop)
      in (loop)
" 20)

(add-test! 'lang7-5 'pgm7-5-2 "
let buf1 = 0 buf2 = 0 buf3 = 0
in let d1 = spawn set buf1 = 20
       d2 = spawn letrec 
                    loop () = if buf1 
                              then set buf2 = +(buf1,2)
                              else (loop)
                  in (loop)
       d3 = spawn letrec 
                    loop () = if buf2 
                              then set buf3 = +(buf2,2)
                              else (loop)
                  in (loop)
   in letrec
        loop () = if buf3 then buf3 else (loop)
      in (loop)
"
  24)

(add-test! 'lang7-5 'pgm7-5-3 "
letrec 
  noisy (l) = let d = print(l)
              in if null?(l) 
                 then 0 
                 else (noisy cdr(l))
in let d1 = spawn (noisy list(1,2,3,4,5))
       d2 = spawn (noisy list(6,7,8,9,10))
       d3 = spawn (noisy list(11,12,13,14,15,16,17))
   in 33
"
  33)

(add-test! 'lang7-5 'shared-variable-1 "
let l = lock list(0)
    done = 0
in let t1 = spawn let c = acquire l
                  in begin
                       setcar(c,add1(car(c)));
                       setcar(c,add1(car(c)));
                       print(list(1,car(c)));
                       set done = add1(done);
                       release l
                     end
       t2 = spawn let c = acquire l
                  in begin 
                       setcar(c,add1(car(c)));
                       setcar(c,add1(car(c)));
                       print(list(2,car(c)));
                       set done = add1(done);
                       release l
                     end
   in let v = 0
      in letrec loop() = if equal?(done,2)
                         then let c = acquire l
                              in begin
                                   set v = car(c);
                                   release l;
                                   v
                                 end
                         else (loop)
         in (loop)
"
4)  

  chapter 8 : cps ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

(add-test! 'lang8-4 'cps-1 "letrec
  fact(x) = if zero?(x) then 1 else *(x, (fact sub1(x)))
in (fact 6)"
' (lambda (k1)
    (letrec ((fact
               (lambda (x k1)
                 (if (zero? x)
                   (k1 1)
                   (fact (sub1 x) (lambda (v1) (k1 (* x v1))))))))
      (fact 6 k1))))

(add-test! 'lang8-4 'cps-2 "letrec
         even(x) = if zero?(x) then 1 else (odd sub1(x))
         odd(x)  = if zero?(x) then 0 else (even sub1(x))
       in (odd 13)"
  '(lambda (k1)
     (letrec ((even
                (lambda (x k1) (if (zero? x) (k1 1) (odd (sub1 x) k1))))
              (odd
                (lambda (x k1) (if (zero? x) (k1 0) (even (sub1 x) k1)))))
       (odd 13 k1))))

(add-test! 'lang8-4 'cps-3 "
letrec even(odd,x) =  if zero?(x) then 1 else (odd sub1(x))
   in letrec  odd(x)  = if zero?(x) then 0 else (even odd sub1(x))
   in (odd 13)"
  '(lambda (k1)
     (letrec ((even
                (lambda (odd x k1) (if (zero? x) (k1 1) (odd (sub1 x) k1)))))
       (letrec ((odd
                  (lambda (x k1)
                    (if (zero? x) (k1 0) (even odd (sub1 x) k1)))))
         (odd 13 k1)))))

(add-test! 'lang8-4 'cps-4 "
add1(if (f zero?(x)) then 1 else *(x, (fact sub1(x))))"
  '(lambda (k1)
     (f (zero? x)
       (lambda (v2)
         (if v2
           (let ((v1 1)) (k1 (add1 v1)))
           (fact (sub1 x)
             (lambda (v3) (let ((v1 (* x v3))) (k1 (add1 v1))))))))))

(add-test! 'lang8-4 'cps-5 "
let a = (f x) b = (g x) c = (h (i (j (t x))))
in cons(a,cons(b,cons(c,emptylist())))"
  '(lambda (k1)
     (f x
       (lambda (z1)
         (g x
           (lambda (z2)
             (t x
               (lambda (v6)
                 (j v6
                   (lambda (v5)
                     (i v5
                       (lambda (v4)
                         (h v4
                           (lambda (z3)
                             (k1 (let ((a z1) (b z2) (c z3))
                                   (cons a
                                     (cons b
                                       (cons c
                                         (empty))))))))))))))))))))

(add-test! 'lang8-4 'cps-6 "
proc(f) let foo = proc(foo,ls) 
                   if null?(ls)
                   then emptylist()
                   else cons((f car(ls)), (foo foo cdr(ls)))
        in proc(ls)(foo foo ls)"
  '(lambda (k1)
     (k1 (lambda (f k1)
           (k1 (let ((foo
                       (lambda (foo ls k1)
                         (if (null? ls)
                           (k1 (empty))
                           (f (car ls)
                             (lambda (v1)
                               (foo foo
                                 (cdr ls)
                                 (lambda (v2) (k1 (cons v1 v2))))))))))
                 (lambda (ls k1) (foo foo ls k1))))))))

(add-test! 'lang8-4 'cps-7 "
 (f let f = 3 in add1(f))"
  '(lambda (k1) (f (let ((f 3)) (add1 f)) k1)))

(add-test! 'lang8-4 'cps-8 "(k (g let g=3 in (f g x)))"
  '(lambda (k1)
     (let ((k1 (lambda (v2) (g v2 (lambda (v1) (k v1 k1))))))
       (let ((g 3)) (f g x k1)))))

(add-test! 'lang8-4 'cps-8 "(even
  letrec
    even(x) = if zero?(x) then 1 else (odd sub1(x))
    odd(x)  = if zero?(x) then 0 else (even sub1(x))
  in (odd 13))"
  '(lambda (k1)
     (let ((k1 (lambda (v1) (even v1 k1))))
       (letrec ((even
                  (lambda (x k1) (if (zero? x) (k1 1) (odd (sub1 x) k1))))
                (odd
                  (lambda (x k1) (if (zero? x) (k1 0) (even (sub1 x) k1)))))
         (odd 13 k1)))))

(add-test! 'lang8-5print 'two-prints
  "(f print((g x)) print(4))"
  '(lambda (k1)
  (g x
     (lambda (v3)
       (printc
         v3
         (lambda (v1) (printc 4 (lambda (v2) (f v1 v2 k1)))))))))

(add-test! 'lang8-5print 'letcc-no-set-1
  "+(1, letcc j in +(4, throw 3 to j))"
  '(lambda (k1)
     (let ((k1 (lambda (v1) (k1 (+ 1 v1)))))
       (let ((j k1)) (j 3)))))

(add-test! 'lang8-5print 'letcc-no-set-2
  "let x = 4 g = proc(n)*(n,n) in (g letcc g in (f throw x to g))"
  '(lambda (k1)
     (let ((x 4) (g (lambda (n k1) (k1 (* n n)))))
       (let ((k1 (lambda (v1) (g v1 k1)))) (let ((g k1)) (g x))))))


  tests for 8-5set.scm .   These duplicate the tests in 8-4.scm , since
;;; they cps differently.

(add-test!
  'lang8-5set
  'pgm8-5-1
  "letrec
  fact(x) = if zero?(x) then 1 else *(x, (fact sub1(x)))
in (fact 6)"
  '(lambda (k1)
     (letrec ((fact
               (lambda (x k1)
                 (derefc
                   x
                   (lambda (v7)
                     (let ((v1 (zero? v7)))
                       (if v1
                           (k1 1)
                           (derefc
                             x
                             (lambda (v2)
                               (derefc
                                 fact
                                 (lambda (v4)
                                   (derefc
                                     x
                                     (lambda (v6)
                                       (let ((v5 (sub1 v6)))
                                         (v4 v5
                                             (lambda (v3)
                                               (k1 (* v2
                                                      v3))))))))))))))))))
       (derefc fact (lambda (v8) (v8 6 k1))))))
(add-test!
  'lang8-5set
  'pgm8-5-2
  "letrec
         even(x) = if zero?(x) then 1 else (odd sub1(x))
         odd(x)  = if zero?(x) then 0 else (even sub1(x))
       in (odd 13)"
  '(lambda (k1)
     (letrec ((even
               (lambda (x k1)
                 (derefc
                   x
                   (lambda (v10)
                     (let ((v6 (zero? v10)))
                       (if v6
                           (k1 1)
                           (derefc
                             odd
                             (lambda (v7)
                               (derefc
                                 x
                                 (lambda (v9)
                                   (let ((v8 (sub1 v9)))
                                     (v7 v8 k1))))))))))))
              (odd
               (lambda (x k1)
                 (derefc
                   x
                   (lambda (v5)
                     (let ((v1 (zero? v5)))
                       (if v1
                           (k1 0)
                           (derefc
                             even
                             (lambda (v2)
                               (derefc
                                 x
                                 (lambda (v4)
                                   (let ((v3 (sub1 v4)))
                                     (v2 v3 k1)))))))))))))
       (derefc odd (lambda (v11) (v11 13 k1))))))
(add-test!
  'lang8-5set
  'pgm8-5-3
  "letrec even(odd,x) =  if zero?(x) then 1 else (odd sub1(x))
   in letrec  odd(x)  = if zero?(x) then 0 else (even odd sub1(x))
   in (odd 13)"
  '(lambda (k1)
     (letrec ((even
               (lambda (odd x k1)
                 (derefc
                   x
                   (lambda (v5)
                     (let ((v1 (zero? v5)))
                       (if v1
                           (k1 1)
                           (derefc
                             odd
                             (lambda (v2)
                               (derefc
                                 x
                                 (lambda (v4)
                                   (let ((v3 (sub1 v4)))
                                     (v2 v3 k1)))))))))))))
       (letrec ((odd
                 (lambda (x k1)
                   (derefc
                     x
                     (lambda (v11)
                       (let ((v6 (zero? v11)))
                         (if v6
                             (k1 0)
                             (derefc
                               even
                               (lambda (v7)
                                 (derefc
                                   odd
                                   (lambda (v8)
                                     (derefc
                                       x
                                       (lambda (v10)
                                         (let ((v9 (sub1 v10)))
                                           (v7 v8 v9 k1)))))))))))))))
         (derefc odd (lambda (v12) (v12 13 k1)))))))
(add-test!
  'lang8-5set
  'pgm8-5-4
  "+(1, letcc j in +(4, throw 3 to j))"
  '(lambda (k1)
     (let ((k1 (lambda (v1) (k1 (+ 1 v1)))))
       (let ((j k1)) (derefc j (lambda (v3) (v3 3)))))))
(add-test!
  'lang8-5set
  'pgm8-5-5
  "add1(if (f zero?(x)) then 1 else *(x, (fact sub1(x))))"
  '(lambda (k1)
     (derefc
       f
       (lambda (v8)
         (derefc
           x
           (lambda (v10)
             (let ((v9 (zero? v10)))
               (v8 v9
                   (lambda (v2)
                     (if v2
                         (let ((v1 1)) (k1 (add1 v1)))
                         (derefc
                           x
                           (lambda (v3)
                             (derefc
                               fact
                               (lambda (v5)
                                 (derefc
                                   x
                                   (lambda (v7)
                                     (let ((v6 (sub1 v7)))
                                       (v5 v6
                                           (lambda (v4)
                                             (let ((v1 (* v3 v4)))
                                               (k1 (add1 v1))))))))))))))))))))))
(add-test!
  'lang8-5set
  'pgm8-5-6
  "
let a = (f x) b = (g x) c = (h (i (j (t x))))
in cons(a,cons(b,cons(c,emptylist())))"
  '(lambda (k1)
     (derefc
       f
       (lambda (v19)
         (derefc
           x
           (lambda (v20)
             (v19 v20
                  (lambda (z1)
                    (derefc
                      g
                      (lambda (v17)
                        (derefc
                          x
                          (lambda (v18)
                            (v17 v18
                                 (lambda (z2)
                                   (derefc
                                     h
                                     (lambda (v9)
                                       (derefc
                                         i
                                         (lambda (v11)
                                           (derefc
                                             j
                                             (lambda (v13)
                                               (derefc
                                                 t
                                                 (lambda (v15)
                                                   (derefc
                                                     x
                                                     (lambda (v16)
                                                       (v15 v16
                                                            (lambda (v14)
                                                              (v13 v14
                                                                   (lambda (v12)
                                                                     (v11 v12
                                                                          (lambda (v10)
                                                                            (v9 v10
                                                                                (lambda (z3)
                                                                                  (let ((a
                                                                                         z1)
                                                                                        (b
                                                                                         z2)
                                                                                        (c
                                                                                         z3))
                                                                                    (derefc
                                                                                      a
                                                                                      (lambda (v4)
                                                                                        (derefc
                                                                                          b
                                                                                          (lambda (v6)
                                                                                            (derefc
                                                                                              c
                                                                                              (lambda (v8)
                                                                                                (let ((v7
                                                                                                       (cons v8
                                                                                                             (empty))))
                                                                                                  (let ((v5
                                                                                                         (cons v6
                                                                                                               v7)))
                                                                                                    (k1 (cons v4
                                                                                                              v5)))))))))))))))))))))))))))))))))))))))))))
(add-test!
  'lang8-5set
  'pgm8-5-7
  "
proc(f) let foo = proc(foo,ls) 
                   if null?(ls)
                   then emptylist()
                   else cons((f car(ls)), (foo foo cdr(ls)))
        in proc(ls)(foo foo ls)"
  '(lambda (k1)
     (k1 (lambda (f k1)
           (k1 (let ((foo
                      (lambda (foo ls k1)
                        (derefc
                          ls
                          (lambda (v11)
                            (let ((v1 (null? v11)))
                              (if v1
                                  (k1 (empty))
                                  (derefc
                                    f
                                    (lambda (v8)
                                      (derefc
                                        ls
                                        (lambda (v10)
                                          (let ((v9 (car v10)))
                                            (v8 v9
                                                (lambda (v2)
                                                  (derefc
                                                    foo
                                                    (lambda (v4)
                                                      (derefc
                                                        foo
                                                        (lambda (v5)
                                                          (derefc
                                                            ls
                                                            (lambda (v7)
                                                              (let ((v6
                                                                     (cdr v7)))
                                                                (v4 v5
                                                                    v6
                                                                    (lambda (v3)
                                                                      (k1 (cons v2
                                                                                v3)))))))))))))))))))))))))
                 (lambda (ls k1)
                   (derefc
                     foo
                     (lambda (v12)
                       (derefc
                         foo
                         (lambda (v13)
                           (derefc
                             ls
                             (lambda (v14) (v12 v13 v14 k1))))))))))))))
(add-test!
  'lang8-5set
  'pgm8-5-8
  "
 (f let f = 3 in add1(f))"
  '(lambda (k1)
     (derefc
       f
       (lambda (v1)
         (let ((k1 (lambda (v2) (v1 v2 k1))))
           (let ((f 3)) (derefc f (lambda (v3) (k1 (add1 v3))))))))))
(add-test!
  'lang8-5set
  'pgm8-5-9
  "(k (g let g=3 in (f g x)))"
  '(lambda (k1)
     (derefc
       k
       (lambda (v1)
         (derefc
           g
           (lambda (v3)
             (let ((k1 (lambda (v4) (v3 v4 (lambda (v2) (v1 v2 k1))))))
               (let ((g 3))
                 (derefc
                   f
                   (lambda (v5)
                     (derefc
                       g
                       (lambda (v6)
                         (derefc x (lambda (v7) (v5 v6 v7 k1)))))))))))))))
(add-test!
  'lang8-5set
  'pgm8-5-10
  "  (even
  letrec
    even(x) = if zero?(x) then 1 else (odd sub1(x))
    odd(x)  = if zero?(x) then 0 else (even sub1(x))
  in (odd 13))"
  '(lambda (k1)
     (derefc
       even
       (lambda (v1)
         (let ((k1 (lambda (v2) (v1 v2 k1))))
           (letrec ((even
                     (lambda (x k1)
                       (derefc
                         x
                         (lambda (v12)
                           (let ((v8 (zero? v12)))
                             (if v8
                                 (k1 1)
                                 (derefc
                                   odd
                                   (lambda (v9)
                                     (derefc
                                       x
                                       (lambda (v11)
                                         (let ((v10 (sub1 v11)))
                                           (v9 v10 k1))))))))))))
                    (odd
                     (lambda (x k1)
                       (derefc
                         x
                         (lambda (v7)
                           (let ((v3 (zero? v7)))
                             (if v3
                                 (k1 0)
                                 (derefc
                                   even
                                   (lambda (v4)
                                     (derefc
                                       x
                                       (lambda (v6)
                                         (let ((v5 (sub1 v6)))
                                           (v4 v5 k1)))))))))))))
             (derefc odd (lambda (v13) (v13 13 k1)))))))))

 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
 this should raise an error
 this should raise an error
 


 



 
 



 
 the test harness doesn't look at output, so these tests are pretty
 useless. 
 y = 4 ; z = 0 ;

 print(x ) ;
 print(x ) } ;
 {f = proc (x, y) *(x,y);

 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
 this one should now raise a type error
 a good one to add types to.
 tests of type inference
 circular type
 these tests are more serious



 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;






 set j = -(0,x) end
 set j = -(j,d) end



 inheritance starts here
 


 program
   let a = new aclass init(3)
   in call a m(2)
   class aclass (i)
     method init(x) fieldassign aclass this i = x;
     method m(y) +(field aclass this i, y)
   end
 end
 set right = r
 set y = 0 end
 
 



 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;








 

 set j = -(0,x) end
 set j = -(j,d) end



 set right = r
 set right = r
 set right = r
 set right = r
 set right = r
 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
 program's behavior.










 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
 they cps differently.
(let ((time-stamp "Time-stamp: <2001-05-10 16:08:58 dfried>"))
  (eopl:printf "test-suite.scm: unified test suite ~a~%" (substring time-stamp 13 29)))

(initialize-test-suite!)


  a few tests for 3 - 1 :

(add-test! 'lang3-1 'pgm3-1-1 "1" 1)

(add-test! 'lang3-1 'pgm3-1-2 "add1(x)" 11)

(add-test! 'lang3-1 'test3-1-unbound-variable "foo" 'error)

(add-test! 'lang3-1 'test3-1-primitive-app-2 "+(x,3)" 13)

  serious tests for 3 - 5 :

(add-test! 'lang3-5 'pgm1 "1" 1)

(add-test! 'lang3-1 'pgm2 "add1(x)" 11)

(add-test! 'lang3-5 'unbound-variable "foo" 'error)

(add-test! 'lang3-1 'primitive-app-2 "+(x,3)" 13)

(add-test! 'lang3-5 'pgm3 "if zero?(1) then 3 else 4" 4)

(add-test! 'lang3-5 'pgm4 "if zero?(0) then 3 else 4" 3)

(add-test! 'lang3-5 'pgm5 "let x = 3 y = 4 in +(x,y)" 7)

(add-test! 'lang3-1 'nested-prim-app "+(i,*(3,4))" 13)

(add-test! 'lang3-5 'let-1 "let x = 5 y = 6 in +(x,y)" 11)

(add-test! 'lang3-5 'let-to-proc-1 "(proc (x,y) +(x,y) 5 6)" 11)

(add-test! 'lang3-5 'nested-let-1 "
let z = 5 x = 3
in let x = 4
       y = +(x,z)         % here x = 3
   in *(z, +(x,y))        % here x = 4" 60)

(add-test! 'lang3-5 'nested-let-2 "
(proc (z,x)
 (proc (x,y) *(z, +(x,y)) 4 +(x,z))
 5 3)
" 60)

(add-test! 'lang3-5 'nested-let-3 "let z = let x = 3 in *(x,x) in z" 9)

(add-test! 'lang3-5 'bind-a-proc "let f = proc(x,y)+(x,y) in (f 3 4)" 7)
(add-test! 'lang3-5 'apply-a-proc "(proc(x,y)-(x,y)  4 3)" 1)


(add-test! 'lang3-5 'infinite-loop "
let fix =  proc (f)
            let d = proc (x) proc (z) (f (x x) z)
            in proc (n) (f (d d) n)
in let loop = (fix proc (f,x) (f x))
   in (loop 1)" 'dontrun)

(add-test! 'lang3-5 'poor-mans-letrec "
let fix =  proc (f)
            let d = proc (x) proc (z) (f (x x) z)
            in proc (n) (f (d d) n)
    t4m = proc (f,x) if x then +(4,(f -(x,1))) else 0
in let times4 = (fix t4m)
   in (times4 3)" 12)

(add-test! 'lang3-6 'fact-of-6  "letrec
  fact(x) = if zero?(x) then 1 else *(x, (fact sub1(x)))
in (fact 6)" 720)

(add-test! 'lang3-6 'odd-of-13  "letrec
         even(x) = if zero?(x) then 1 else (odd sub1(x))
         odd(x)  = if zero?(x) then 0 else (even sub1(x))
       in (odd 13)" 1)

(add-test! 'lang3-6 'HO-nested-letrecs
  "letrec even(odd,x) =  if zero?(x) then 1 else (odd sub1(x))
   in letrec  odd(x)  = if zero?(x) then 0 else (even odd sub1(x))
   in (odd 13)" 1)

(add-test! 'lang3-7 'gensym-test
"let g = let count = 0 in proc() 
                        let d = set count = add1(count)
                        in count
in +((g), (g))"
3)

(add-test! 'lang3-7 'even-odd-via-set "
let x = 0
in letrec even() = if zero?(x) then 1 
                                  else let d = set x = sub1(x)
                                       in (odd)
              odd()  = if zero?(x) then 0 
                                  else let d = set x = sub1(x)
                                       in (even)
   in let d = set x = 13 in (odd)" 1)

(add-test! 'lang3-8ref 'basic-by-ref "
let x = 13
    f = proc (y) set y = add1(y)
in begin
    x
   end"
14)

(add-test! 'lang3-8ref 'swap-by-ref "
let a = 3
    b = 4
    swap = proc (x, y)
             let temp = x
             in begin
                  set y = temp
                end
in begin
     -(a,b)
   end"
  1 by reference , -1 by value



(add-test! 'lang3-8name 'basic-by-name "
let x = 13
    f = proc (y) set y = add1(y)
in begin
    x
   end"
14)

(add-test! 'lang3-8name 'swap-by-name "
let a = 3
    b = 4
    swap = proc (x, y)
             let temp = x
             in begin
                  set y = temp
                end
in begin
     -(a,b)
   end"
  1 by reference , -1 by value

(add-test! 'lang3-8name 'ignore-arg-name "
let a = 3
in let f = proc () set a = add1(a)
       g = proc (x) 11
   in begin 
        a
      end"
3)

(add-test! 'lang3-8name 'check-multiple-evals-by-name "
let g = let count = 0 in proc () begin 
                                   count
                                 end
in (proc(x) +(x,x)
    (g))"
  3 for name , 2 for need

(add-test! 'lang3-8need 'basic-by-need "
let x = 13
    f = proc (y) set y = add1(y)
in begin
    x
   end"
14)

(add-test! 'lang3-8need 'swap-by-need "
let a = 3
    b = 4
    swap = proc (x, y)
             let temp = x
             in begin
                  set y = temp
                end
in begin
     -(a,b)
   end"
  1 by reference , -1 by value

(add-test! 'lang3-8need 'ignore-arg-by-need "
let a = 3
in let f = proc () set a = add1(a)
       g = proc (x) 11
   in begin 
        a
      end"
3)

(add-test! 'lang3-8need 'check-multiple-evals-by-need "
let g = let count = 0 in proc () begin 
                                   count
                                 end
in (proc(x) +(x,x)
    (g))"
  3 for name , 2 for need



(add-test! 'lang3-9 'print-1 "print(10)" #t) 

(add-test! 'lang3-9 'pgm3-9-1 "var x,y; {x = 3; y = 4; print(+(x,y))}"
  #t)

(add-test! 'lang3-9 'pgm3-9-2 "
            print(z)}"
  #t)

(add-test! 'lang3-9 'pgm3-9-3 "
        print(x)}"
  #t)

(add-test! 'lang3-9 'pgm3-9-4 "
          print((f 4 x))}"
  #t)



(add-typed-test! 'lang4-2 'literal "1" 'int 1)

(add-typed-test! 'lang4-2 'primitive-app-1 "add1(x)" 'error 'dontrun)

(add-typed-test! 'lang4-2 'primitive-app-2-typed "+(2,3)" 'int 5)

(add-typed-test! 'lang4-2 'primitive-app-3 "+(2,true)" 'error 'dontrun)

(add-typed-test! 'lang4-2 'type-a-proc-1 "proc(int x, bool y) x"
  '(int * bool -> int) 'dontrun)

(add-typed-test! 'lang4-2 'type-ho-proc-1
      "proc(int x, (int * int -> bool) f) (f x 3)"
      '(int * (int * int -> bool) -> bool)
      'dontrun)

(add-typed-test! 'lang4-2 'type-ho-proc-2
      "proc(int x, (int * int -> bool) f) (f x true)"
      'error 'dontrun)

(add-typed-test! 'lang4-2 'apply-a-proc-typed
  "(proc(int x, int y)-(x,y)  4 3)"
  'int 1)

(add-typed-test! 'lang4-2 'simple-let "let x = 3 y = 4 in +(x,y)" 'int 7) 

(add-typed-test! 'lang4-2 'bind-a-proc-typed
  "let f = proc (int x) add1(x) in (f 4)" 'int 5) 

(add-typed-test! 'lang4-2 'bind-a-proc-return-proc
  "let f = proc (int x) add1(x) in f"
  '(int -> int) 'dontrun)

(add-typed-test! 'lang4-2 'apply-ho-proc "
let apply = proc ((int * int -> int) f, int x) (f add1(x) x)
    g     = proc (int x, int y) *(x,y)
in (apply g 3)"
  'int 12)

(add-typed-test! 'lang4-2 'wrong-no-of-args "let f = proc (int x) add1(x) in (f 4 3)" 'error 'dontrun)

(add-typed-test! 'lang4-2 'unbound-variable-2 "let f = proc (int x) add1(x) in (g 4 3)" 'error 'dontrun)

(add-typed-test! 'lang4-2 'apply-a-proc-2-typed "(proc (int x) add1(x) 4)" 'int 5)

(add-typed-test! 'lang4-2 'apply-a-letrec "
letrec int f(int x, int y) = +(x,y) 
in (f 40 50)"
  'int 90)

(add-typed-test! 'lang4-2 'letrec-return-fact "
letrec 
  int fact(int x)= if zero?(x) then 1 else *(x, (fact sub1(x)))
in fact" '(int -> int) 'dontrun)

(add-typed-test! 'lang4-2 'letrec-apply-fact "
letrec 
  int fact(int x)= if zero?(x) then 1 else *(x, (fact sub1(x)))
in (fact 6)" 'int 720)

(add-typed-test! 'lang4-2 'letrec-return-odd "
letrec int odd(int x)  = if zero?(x) then 0 else (even sub1(x))
       int even(int x) = if zero?(x) then 1 else (odd  sub1(x))
in odd"
  '(int -> int) 'dontrun)

(add-typed-test! 'lang4-2 'letrec-apply-odd "
letrec int odd(int x)  = if zero?(x) then 0 else (even sub1(x))
       int even(int x) = if zero?(x) then 1 else (odd  sub1(x))
in (odd 13)" 'int 1)

(add-typed-test! 'lang4-2 'apply-fcn-to-wrong-type "
letrec int odd(int x)  = if zero?(x) then 0 else (even sub1(x))
       int even(int x) = if zero?(x) then 1 else (odd  sub1(x))
in (even odd)" 'error 'dontrun)

(add-typed-test! 'lang4-2 'types-fail-but-program-works "
let fix =  proc (int f)
            let d = proc (int x) proc (int z) (f (x x) z)
            in proc (int n) (f (d d) n)
    t4m = proc (int f, int x) if x then +(4,(f -(x,1))) else 0
in let times4 = (fix t4m)
   in (times4 3)" 'error 12)

  ( add - typed - test ! '  - 4 ' pgm11
    " letrecproc even(odd , x ) =   if  ) then 1 else ( odd  ) )
     in letrecproc   odd(x )   = if  ) then 0 else ( even odd  ) )
     in ( odd 13 ) " ' error 1 )

(add-typed-test! 'lang4-3 'lettype-type-check-exported-fcn "
lettype foo = int
 foo m(int x) = add1(x)
in m" '(int -> foo) 'dontrun)

(add-typed-test! 'lang4-3 'lettype-apply-exported-fcn-1 "
lettype foo = int
 foo m(int x) = add1(x)
in (m 3)"
  'foo 4)

(add-typed-test! 'lang4-3 'lettype-foo-isnt-int  "
lettype foo = int
 foo m (int x) = add1(x)
in add1((m 3))"
  'error 5)

(add-typed-test! 'lang4-3 'lettype-error-in-defns "
lettype ff = (int -> int)
  ff zero-ff (int k) = 0                % a real type error!
  ff extend-ff (int k, int val, ff old-ff) =
       proc (int k1) if zero?(-(k1,k)) then val else (old-ff k1)
  int apply-ff (int k, ff f) = (f k)
in let ff1 = (extend-ff 1 11 (extend-ff 2 22 zero-ff))
   in (apply-ff ff1 2)"
'error 'dontrun)

(add-typed-test! 'lang4-3 'opaque-finite-fcns-0 "
lettype ff = (int -> int)
  ff zero-ff () = proc (int k) 0               
  ff extend-ff (int k, int val, ff old-ff) =
       proc (int k1) if zero?(-(k1,k)) then val else (old-ff k1)
  int apply-ff (ff f, int k) = (f k)
in let ff1 = (extend-ff 1 11 (extend-ff 2 22 (zero-ff)))
   in (apply-ff ff1 2)" 'int 22)



(add-typed-test! 'lang4-3 'opaque-finite-fcns-letrec-of-internal-fcns "
lettype ff = (int -> int)
  ff zero-ff () = proc (int k) 0               
  ff extend-ff (int k, int val, ff old-ff) =
       proc (int k1) if zero?(-(k1,k)) then val else (apply-ff old-ff k1)
  int apply-ff (ff f, int k) = (f k)
in let ff1 = (extend-ff 1 11 (extend-ff 2 22 (zero-ff)))
   in (apply-ff ff1 2)" 'int 22)

(add-typed-test! 'lang4-3 'opaque-finite-fcns-try-violating-abstraction-boundary "
lettype ff = (int -> int)
  ff zero-ff () = proc (int k) 0               
  ff extend-ff (int k, int val, ff old-ff) =
       proc (int k1) if zero?(-(k1,k)) then val else (old-ff k1)
  int apply-ff (ff f, int k) = (f k)
in let ff1 = (extend-ff 1 11 (extend-ff 2 22 (zero-ff)))
   in (ff1 2)"
  ' error , 22


(add-typed-test! 'lang4-3 'myint1 "
lettype
  myint = int  % like the integers, but zero is represented as 1!
  myint zero() = 1
  myint succ(myint x) = add1(x)
  myint pred(myint x) = sub1(x)
  bool  iszero?(myint x) =  zero?(-(x,1))
in (succ (zero))"
  myint , 2

(add-typed-test! 'lang4-3 'myint2 "
lettype
  myint = int  % like the integers, but zero is represented as 1!
  myint zero() = 1
  myint succ(myint x) = add1(x)
  myint pred(myint x) = sub1(x)
  bool  iszero?(myint x) =  zero?(-(x,1))
in add1((zero))"
  'error 2)   


(add-typed-test! 'lang4-4 'pgm4b "let f = proc (? x) add1(x) in (f 4)"
  'int 5)

(add-typed-test! 'lang4-4 'pgm4-0b "let f = proc (? x) add1(x) in f"
  '(int -> int) 'dontrun)

(add-typed-test! 'lang4-4 'pgm4-1b "
let apply = proc (?f, ? x) (f add1(x) x)
    g     = proc (? x, ? y) *(x,y)
in (apply g 3)"
  int , 12

(add-typed-test! 'lang4-4 'pgm6b "letrec int f(? x,? y) = +(x,y) 
              in (f 40 50)"
  int , 90

(add-typed-test! 'lang4-4 'pgm7b "
letrec 
  ? fact(? x)= if zero?(x) then 1 else *(x, (fact sub1(x)))
in fact"
  '(int -> int) 'dontrun)

(add-typed-test! 'lang4-4 'pgm8b "
letrec ? odd(? x)  = if zero?(x) then 0 else (even sub1(x))
       ? even(? x) = if zero?(x) then 1 else (odd  sub1(x))
in odd" '(int -> int) 'dontrun)


(add-typed-test! 'lang4-4 'pgm8ab "
letrec ? odd(? x)  = if zero?(x) then 0 else (even sub1(x))
       ? even(bool x) = if zero?(x) then 1 else (odd  sub1(x))
in (odd 13)" 'error 'dontrun)

(add-typed-test! 'lang4-4 'circular-type "
let fix =  proc (? f)
            let d = proc (? x) proc (? z) (f (x x) z)
            in proc (? n) (f (d d) n)
    t4m = proc (? f, ? x) if zero?(x) then 0 else +(4,(f -(x,1)))
in let times4 = (fix t4m)
   in (times4 3)"
  'error 12)

(add-typed-test! 'lang4-4 'pgm11b
  "letrec ? even(? odd, ? x) =  if zero?(x) then 1 else (odd sub1(x))
   in letrec  ? odd(? x)  = if zero?(x) then 0 else (even odd sub1(x))
   in (odd 13)"
  'int 1)

(add-typed-test! 'lang4-4 'infer-in-body-using-opaque-type "
lettype
  myint = int  % like the integers, but zero is represented as 1!
  myint zero() = 1
  myint succ(myint x) = add1(x)
  myint pred(myint x) = sub1(x)
  bool  iszero?(myint x) =  zero?(-(x,1))
in letrec ? plus(? x,? y) = if (iszero? x) then y else (succ (plus (pred x) y))
in plus"
  '(myint * myint -> myint)  'dontrun)

(add-typed-test! 'lang4-4 'infer-in-impl-1 "
lettype
  myint = int  % like the integers, but zero is represented as 1!
  myint zero() = 1
  myint succ(myint x) = let f = proc(? x) x in add1((f x))
  myint pred(myint x) = sub1(x)
  bool  iszero?(myint x) =  zero?(-(x,1))
in letrec ? plus(? x,? y) = if (iszero? x) then y else (succ (plus (pred x) y))
in plus"
      '(myint * myint -> myint)  'dontrun)

(add-typed-test! 'lang6 'create-empty-class
  "class c1 extends object  3" 'int 3)

(add-typed-test! 'lang6 'create-class-with-method "
class c1 extends object 
 field int y 
 method int gety()y
  
33 "
'int 33)

(add-typed-test! 'lang6 'create-object "
class c1 extends object  
 method int initialize()0 
let o1 = new c1() in 11
" 'int 11)


(add-typed-test! 'lang6 'send-msg-1 "
class c1 extends object 
 field int s
 method void initialize()set s = 44
 method int gets()s
 method void sets(int v)set s = v                               

let o1 = new c1() in send o1 gets()
"
'int 44)



(add-typed-test! 'lang6 'send-msg-2 "
class c1 extends object 
          field int s 
          method void initialize()set s = 44 
          method int gets()s
          method int sets(int v)set s = v  % type error here
                
let o1 = new c1() 
    t1 = 0
    t2 = 0 
in begin
     list(t1, t2)
  end
"
'error '(44 33))


(add-test! 'oop 'create-empty-class
  "class c1 extends object  3" 3)

(add-test! 'oop 'create-class-with-method "
class c1 extends object 
  field y 
  method gety () y 
33                       % 33 is the body"
33)

(add-test! 'oop 'create-object "
class c1 extends object  
 method initialize()0 
let o1 = new c1() in 11
" 11)


(add-test! 'oop 'send-msg-1 "
class c1 extends object 
  field s 
  method initialize() set s = 44
  method gets()s
  method sets(v)set s = v
  
let o1 = new c1() in send o1 gets()
"
44)

(add-test! 'oop 'send-msg-2 "
class c1 extends object 
  field s 
  method initialize() set s = 44
  method gets()s
  method sets(v)set s = v
  
let o1 = new c1() 
    t1 = 0
    t2 = 0 
in begin
     list(t1, t2)
  end
"
'(44 33))

(add-test! 'oop 'test-self-1 "
class c extends object 
  field s
  method initialize(v)set s = v
  method sets(v)set s = v
  method gets()s
  method testit()send self sets(13)
  
let o = new c (11)
       t1 = 0
       t2 = 0
   in begin 
       list(t1,t2)
      end" '(11 13))

(add-test! 'oop 'chris-1 "
class aclass extends object 
  field i
  method initialize(x) set i = x
  method m(y) +(i,y)
  
let o1 = new aclass(3)
in send o1 m(2)"
5)

(add-test! 'oop 'for-book-1 "
class c1 extends object
  field i
  field j
  method getstate()list(i,j)
  
let o1 = new c1(3)
    t1 = 0
    t2 = 0
in begin
    list(t1,t2)
   end"
'((3 -3) (5 -5)))


(add-test! 'oop 'odd-even-via-self "
class oddeven extends object 
  method initialize()1
  method even(n)if zero?(n) then 1 else send self odd(sub1(n))
  method odd(n) if zero?(n) then 0 else send self even(sub1(n))
  
let o1 = new oddeven() in send o1 odd(13)"
1)


(add-test! 'oop 'inherit-1 "
class c1 extends object 
  field ivar1
  method initialize()set ivar1 = 1
  
class c2 extends c1 
  field ivar2
  method initialize() 
   begin
    set ivar2 = 1
   end
  method setiv1(n)set ivar1 = n
  method getiv1()ivar1
  
let o = new c2 ()
    t1 = 0
in begin
       send o getiv1()
   end                      
" 33)

(add-test! 'oop 'inherit-2 "
class c1 extends object 
  field ivar1
  method initialize()set ivar1 = 1

  method setiv1(n)set ivar1 = n
  method getiv1()ivar1

  method foo()1
  method call-foo-from-superclass()send self foo()

  
class c2 extends c1 
  field ivar2
  method initialize() 
  set ivar2 = 1 end
   

  method foo()2

  method setiv2(n)set ivar2 = n
  method getiv2()ivar2

  method self-and-super-foo()
    list( send self foo(),  super foo())

  method test-self-from-super()
     super call-foo-from-superclass()

   
let o = new c2 ()
    t1 = 0 t2 = 0 t3 = 0 t4 = 0
in begin
       list(
         send o getiv1(),
         send o self-and-super-foo(),
         send o call-foo-from-superclass(),
         send o test-self-from-super()
         )
      end                      
" '(33 (2 1) 2 2))

      ( inherit-2 , inherit-2 ( 33 ( 2 1 ) 2   2 22 33 ) )

(add-test! 'oop 'inherit-3 "
class c1 extends object 
  method initialize()1
  method m1()1
  
class c2 extends c1 
  method m1()super m1()
  method m2()2
  
class c3 extends c2 
  method m1()3
  method m2()super m2()
  method m3()super m1()
  
let o = new c3 ()
in list( send o m1(),
         send o m2(),
         send o m3()
        )
" '(3 2 1))

   's first example


(add-test! 'oop 'chris-2 "
class c1 extends object 
  method initialize() 1
  method ma()1
  method mb()send self ma()
  
class c2 extends c1   % just use c1's initialize
  method ma() 2
  
let x = new c2 ()
in list(send x ma(),send x mb())
"
'(2 2))


(add-test! 'oop 'for-book-2 "
class c1 extends object 
  method initialize()1
  method m1()1
  method m2()100
  method m3()send self m2()
  
class c2 extends c1 
  method m2()2
  
let o1 = new c1()
    o2 = new c2()
in list(send o1 m1(),           % returns 1
        send o1 m2(),           % returns 100
        send o1 m3(),           % returns 100
        send o2 m1(),           % returns 1 (from c1)
        send o2 m2(),           % returns 2 (from c2)
        send o2 m3()            % returns 2 (c1's m3 calls c2's m2)
       )
"
'(1 100 100 1 2 2))

(add-test! 'oop 'sum-leaves "
class tree extends object 
  method initialize()1
  
class interior_node extends tree 
  field left
  field right
  method initialize(l,r)
   begin
   end
  method sum()+(send left sum(), send right sum())
  
class leaf_node extends tree 
  field value
  method initialize(v)set value = v
  method sum()value
  
let o1 = new interior_node (
          new interior_node (
            new leaf_node(3),
            new leaf_node(4)),
          new leaf_node(5))
in send o1 sum()
"
12)

(add-test! 'oop 'check-shadowed-fields "
class c1 extends object 
  field x
  field y
  method m1() x

class c2 extends c1 
  field x
                                    super initialize(v1) end
  method m2()list(x,y)

class c3 extends c2 
  field x
                                       super initialize(v1,v2)
                                 end
  method m3()x

let o = new c3(1,2,3)
in list (send o m1(), send o m2(), send o m3())
"
'(1 (2 0) 3))

(add-test! 'oop 'static-super "
class c1 extends object
 method initialize () 1
 method m2() send self m3()
 method m3() 13
class c2 extends c1
 method m2() 22
 method m3() 23
 method m1() super m2()
class c3 extends c2
 method m2() 32
 method m3() 33
let o3 = new c3()
in send o3 m1()"
33)



(add-typed-test! 'lang6 'test-self-1 "
class c extends object 
         field int s
         method void initialize(int v)set s = v
         method void sets(int v)set s = v    
         method int gets()s
         method void testit()send self sets(13)
              
let o = new c (11)
       t1 = 0
       t2 = 0
   in begin 
       list(t1,t2)
      end" '(list int) '(11 13))


(add-typed-test! 'lang6 'counter-1 "
class counter extends object
  field int count
   method void initialize()set count = 0
   method void countup()set count = add1(count)
   method int getcount()count
   
let o1 = new counter ()
    t1 = 0
    t2 = 0
in begin
    list(t1,t2)
end
" '(list int) '(0 1))

(add-typed-test! 'lang6 'shared-counter-1 "
class counter extends object
  field int count
   method void initialize()set count = 0
   method void countup()set count = add1(count)
   method int getcount()count
   
class c1 extends object 
   field int n
   field counter counter1
   method void initialize(counter a_counter)
    begin
     set counter1 = a_counter
    end
   method void countup()
     begin
      set n = add1(n)
     end
   method list int getstate()list(n, send counter1 getcount())
   
let counter1 = new counter()
in let o1 = new c1(counter1)
       o2 = new c1(counter1)
in begin
     list( send o1 getstate(),
           send o2 getstate())
   end
" '(list (list int)) '((1 3) (2 3)))


(add-typed-test! 'lang6 'inherit-1 "
class c1 extends object 
  field int ivar1
  method void initialize()set ivar1 = 1
  
class c2 extends c1 
  field int ivar2
  method void initialize() 
   begin
    set ivar2 = 1
   end
  method void setiv1(int n)set ivar1 = n
  method int getiv1()ivar1
  
let o = new c2 ()
    t1 = 0
in begin
       send o getiv1()
   end                      
" 'int 33)

(add-typed-test! 'lang6 'inherit-3 "
class c1 extends object 
  method int initialize()1
  method int m1()1
  
class c2 extends c1 
  method int initialize()1 
  method int m1()super m1()
  method int m2()2
  
class c3 extends c2 
  method int initialize()1
  method int m1()3
  method int m2()super m2()
  method int m3()super m1()
  
let o = new c3 ()
in list( send o m1(),
         send o m2(),
         send o m3()
        )
"  '(list int) '(3 2 1))

(add-typed-test! 'lang6 'chris-1 "
class aclass extends object 
  field int i
  method void initialize(int x) set i = x
  method int m(int y) +(i,y)
  
let o1 = new aclass(3)
in send o1 m(2)"
'int 5)

(add-typed-test! 'lang6 'chris-2 "
class c1 extends object 
  method int initialize() 1
  method int ma()1
  method int mb()send self ma()
  
class c2 extends c1   % just use c1's initialize
  method int ma() 2
  
let x = new c2 ()
in list(send x ma(),send x mb())
"
'(list int) '(2 2))

(add-typed-test! 'lang6 'for-book-1 "
class c1 extends object 
  field int i
  field int j
  method list int getstate()list(i,j)
  
let o1 = new c1(3)
    t1 = nil[int]
    t2 = nil[int]
in begin
    list(t1,t2)
   end"
'(list (list int)) '((3 -3) (5 -5)))


(add-typed-test! 'lang6 'odd-even-via-self "
class oddeven extends object 
  method int initialize()1
  method bool even(int n)if zero?(n) then true else send self odd(sub1(n))
  method bool odd(int n) if zero?(n) then false else send self even(sub1(n))
  
let o1 = new oddeven() in send o1 odd(13)"
'bool 1)

(add-typed-test! 'lang6 'for-book-2 "
class c1 extends object 
  method int initialize()1
  method int m1()1
  method int m2()100
  method int m3()send self m2()
  
class c2 extends c1 
  method int initialize()1
  method int m2()2
  
let o1 = new c1()
    o2 = new c2()
in list(send o1 m1(),           % returns 1
        send o1 m2(),           % returns 100
        send o1 m3(),           % returns 100
        send o2 m1(),           % returns 1 (from c1)
        send o2 m2(),           % returns 2 (from c2)
        send o2 m3()            % returns 2 (c1's m3 calls c2's m2)
       )
"
'(list int) '(1 100 100 1 2 2))

(add-typed-test! 'lang6 'sum-leaves "
class tree extends object 
  method int initialize()1
  
class interior_node extends tree 
  field node left
  field node right
  method void initialize(node l, node r)
   begin
   end
  method int sum()+(send left sum(), send right sum())
  
class leaf_node extends tree 
  field int value
  method void initialize(int v)set value = v
  method int sum()value
  
let o1 = new interior_node (
          new interior_node (
            new leaf_node(3),
            new leaf_node(4)),
          new leaf_node(5))
in send o1 sum()
"
'error 12)

(add-typed-test! 'lang6 'sum-leaves-2 "
abstract class tree extends object 
  method int initialize()1
  
class interior_node extends tree 
  field tree left
  field tree right
  method void initialize(tree l, tree r)
   begin
   end
  method int sum()+(send left sum(), send right sum())
  
class leaf_node extends tree 
  field int value
  method void initialize(int v)set value = v
  method int sum()value
  
let o1 = new interior_node (
          new interior_node (
            new leaf_node(3),
            new leaf_node(4)),
          new leaf_node(5))
in send o1 sum()
"
'error 12)

(add-typed-test! 'lang6 'sum-leaves-with-abstract-method "
abstract class tree extends object 
  method int  initialize()1
  abstractmethod int sum()
  
class interior_node extends tree 
  field tree left
  field tree right
  method void initialize(tree l, tree r)
   begin
   end
  method int sum()+(send left sum(), send right sum())
  
class leaf_node extends tree 
  field int value
  method void initialize(int v)set value = v
  method int sum()value
  
let o1 = new interior_node (
          new interior_node (
            new leaf_node(3),   %% need subtyping to make this ok.
            new leaf_node(4)),
          new leaf_node(5))
in send o1 sum()
"
'int 12)


(add-typed-test! 'lang6 'equal-trees-1 "
abstract class tree extends object 
  method int  initialize()1
  abstractmethod int sum()
  abstractmethod bool equal(tree t)
  
class interior_node extends tree 
  field tree left
  field tree right
  method void initialize(tree l, tree r)
   begin
   end
  method tree getleft()left
  method tree getright()right
  method int sum()+(send left sum(), send right sum())
  method bool equal(tree t) 
    if instanceof t interior_node
     then if send left equal(send cast t interior_node getleft())
          then send right equal(send cast t interior_node getright())
          else false
     else false 
     
  
class leaf_node extends tree 
  field int value
  method void initialize(int v)set value = v
  method int sum()value
  method int getvalue()value
  method bool equal(tree t) 
   if instanceof t leaf_node
    then zero?(-(value, send cast t leaf_node getvalue()))
    else false
    
  
let o1 = new interior_node (
          new interior_node (
            new leaf_node(3),   
            new leaf_node(4)),
          new leaf_node(5))
in send o1 equal(o1)
"
'bool 1)

(add-typed-test! 'lang6 'bad-cast-1 "
class c1 extends object 
class c2 extends object 
proc (c1 o) cast o c2
"
'error 'dontrun)

(add-typed-test! 'lang6 'good-instanceof-1 "
class c1 extends object 
class c2 extends object 
let p = proc (c1 o) instanceof o c2 in 11
"
'int 11)

(add-typed-test! 'lang6 'up-cast-1 "
class c1 extends object 
  method int initialize ()1
  method int get()2
  
class c2 extends c1 
let f = proc (c2 o) send cast o c1 get() in (f new c2())
"
'int 2)

(add-typed-test! 'lang6 'up-instance-1 "
class c1 extends object 
  method int initialize ()1
  method int get()2
  
class c2 extends c1 
let f = proc (c2 o) instanceof o c1 in (f new c2())
"
'bool 1)

(add-typed-test! 'lang6 'missing-initialize-method-1 "
class c1 extends object 
  method int initialize ()1
  method int get()2
  
class c2 extends object   % no initialize method!
let f = proc (c2 o) instanceof o c1 in (f new c2())
"
'error 'dontrun)

(add-typed-test! 'lang6 'duplicate-methods-1 "
class c1 extends object
  method int initialize() 1
class c2 extends c1
  method int m1() 1
  method int m1() 2
33"
'error 33)

(add-typed-test! 'lang6 'incomparable-instanceof-2 "
class c1 extends object 
  method int initialize ()1
  method int get()2
  
class c2 extends object 
  method int initialize () 100
    
let f = proc (c2 o) if instanceof o c1 then 1 else 2 in (f new c2())
"
'int 2)

(add-typed-test! 'lang6 'equal-trees-by-double-dispatch "
abstract class tree extends object 
  method int  initialize()1
  abstractmethod int sum()
  abstractmethod bool equal(tree t)
  abstractmethod bool equal_int(tree l, tree r)
  abstractmethod bool equal_leaf(int val)
  
class interior_node extends tree 
  field tree left
  field tree right
  method void initialize(tree l, tree r)
   begin
   end
  method int sum()+(send left sum(), send right sum())
  method bool equal(tree t) send t equal_int(left, right)
  method bool equal_int(tree l, tree r) 
     if send left equal(l)
     then send right equal(r)
     else false
     
  method bool equal_leaf(int v) false
  
class leaf_node extends tree 
  field int value
  method void initialize(int v)set value = v
  method int sum()value
  method bool equal(tree t) send t equal_leaf(value)
  method bool equal_int(tree l, tree r) false
  method bool equal_leaf(int otherval) zero?(-(value, otherval))
  
let o1 = new interior_node (
          new interior_node (
            new leaf_node(3),   
            new leaf_node(4)),
          new leaf_node(5))
in send o1 equal(o1)
"
'bool 1)

(add-typed-test! 'lang6 'bad-super-1 "
class c1 extends object 
 method int initialize() 1
 
class c2 extends c1 
 method int m1() super m2()
 
class c3 extends c2 
 method int m2() 2
 
class c4 extends c3 
let o = new c4() in send o m1()
"
'error 'dontrun)

(add-typed-test! 'lang6 'missing-concrete "
class c1 extends object 
 method int initialize() 1
 abstractmethod int foo()
 
class c2 extends c1 
let o = new c2() in 33"
'error 33)

(add-typed-test! 'lang6 'cant-apply-abstract-method "
class c1 extends object 
 method int initialize() 1
 abstractmethod int m()
 
let o = new c1() in send o m()
"
'error 'dontrun)

(add-typed-test! 'lang6 'cant-apply-abstract-super "
abstract class c1 extends object 
  abstractmethod int m1()
 
class c2 extends c1 
 method int m1 () 1
 method int m2 () super m1 ()
 
33"
'error 'dontrun)

(add-typed-test! 'lang6 'goldberg-80 "
class c1 extends object 
  method int initialize () 1
  method int test () 1
  method int result1 () send self test ()
  
class c2 extends c1 
  method int test () 2
  
class c3 extends c2 
  method int result2 () send self result1 ()
  method int result3 () super test ()
  
class c4 extends c3 
  method int test () 4
  
let o3 = new c3 ()
    o4 = new c4 ()
in list(send o3 test(),
        send o4 result1 (),
        send o3 result2 (),   
        send o4 result2 (),
        send o3 result3 (),
        send o4 result3 ())
"
'(list int) '(2 4 2 4 2 2))

(add-typed-test! 'lang6 'abstract-method-never-overridden "
abstract class c1 extends object 
  abstractmethod int m1() 
  
class c2 extends c1 
  method int m2 ()send self m1()
  
33"
'error 'dontrun)

(add-typed-test! 'lang6 'overriding-method-changes-type-1 "
abstract class c1 extends object 
  abstractmethod int m1()
  
class c2 extends c1 
  method bool m1() false
  
33"
'error 'dontrun)

(add-typed-test! 'lang6 'test6-3-1 "
abstract class c1 extends object
 method int initialize () 1 
 method int m1 () 11
 abstractmethod int m2 () 
class c2 extends c1 
 method int m1 () 21
 method int m2 () 22
 method int m3 () 23
class c3 extends c2 
 method int m4 () 34
class c4 extends c3 
 method int m2 () 42 
proc (c3 o) send o m2()
"
'(c3 -> int) 'dontrun)


  most of chapter 7 reuses the languages from chapter 3 .

  only a simple test for 7.4 :

(add-test! 'lang7-4 'raise-exception-1 "
let index = proc (n, l)
              letrec                            
                loop (l) = if null?(l) 
                           then raise sub1(0)  
                           else if equal?(n,car(l)) 
                                then 0   
                                else add1((loop cdr(l)))
              in try (loop l) handle proc (x) x
in (index 1 list(2,3))"
-1)

  for 7.5 , the final answers capture only a small part of the

(add-test! 'lang7-5 'pgm7-5-1 "
let acc = 0 done = 0
in let d = spawn set acc = 20
   in letrec 
        loop () = if acc 
                  then let d = set done = 1
                       in acc
                  else (loop)
      in (loop)
" 20)

(add-test! 'lang7-5 'pgm7-5-2 "
let buf1 = 0 buf2 = 0 buf3 = 0
in let d1 = spawn set buf1 = 20
       d2 = spawn letrec 
                    loop () = if buf1 
                              then set buf2 = +(buf1,2)
                              else (loop)
                  in (loop)
       d3 = spawn letrec 
                    loop () = if buf2 
                              then set buf3 = +(buf2,2)
                              else (loop)
                  in (loop)
   in letrec
        loop () = if buf3 then buf3 else (loop)
      in (loop)
"
  24)

(add-test! 'lang7-5 'pgm7-5-3 "
letrec 
  noisy (l) = let d = print(l)
              in if null?(l) 
                 then 0 
                 else (noisy cdr(l))
in let d1 = spawn (noisy list(1,2,3,4,5))
       d2 = spawn (noisy list(6,7,8,9,10))
       d3 = spawn (noisy list(11,12,13,14,15,16,17))
   in 33
"
  33)

(add-test! 'lang7-5 'shared-variable-1 "
let l = lock list(0)
    done = 0
in let t1 = spawn let c = acquire l
                  in begin
                       release l
                     end
       t2 = spawn let c = acquire l
                  in begin 
                       release l
                     end
   in let v = 0
      in letrec loop() = if equal?(done,2)
                         then let c = acquire l
                              in begin
                                   v
                                 end
                         else (loop)
         in (loop)
"
4)  


(add-test! 'lang8-4 'cps-1 "letrec
  fact(x) = if zero?(x) then 1 else *(x, (fact sub1(x)))
in (fact 6)"
' (lambda (k1)
    (letrec ((fact
               (lambda (x k1)
                 (if (zero? x)
                   (k1 1)
                   (fact (sub1 x) (lambda (v1) (k1 (* x v1))))))))
      (fact 6 k1))))

(add-test! 'lang8-4 'cps-2 "letrec
         even(x) = if zero?(x) then 1 else (odd sub1(x))
         odd(x)  = if zero?(x) then 0 else (even sub1(x))
       in (odd 13)"
  '(lambda (k1)
     (letrec ((even
                (lambda (x k1) (if (zero? x) (k1 1) (odd (sub1 x) k1))))
              (odd
                (lambda (x k1) (if (zero? x) (k1 0) (even (sub1 x) k1)))))
       (odd 13 k1))))

(add-test! 'lang8-4 'cps-3 "
letrec even(odd,x) =  if zero?(x) then 1 else (odd sub1(x))
   in letrec  odd(x)  = if zero?(x) then 0 else (even odd sub1(x))
   in (odd 13)"
  '(lambda (k1)
     (letrec ((even
                (lambda (odd x k1) (if (zero? x) (k1 1) (odd (sub1 x) k1)))))
       (letrec ((odd
                  (lambda (x k1)
                    (if (zero? x) (k1 0) (even odd (sub1 x) k1)))))
         (odd 13 k1)))))

(add-test! 'lang8-4 'cps-4 "
add1(if (f zero?(x)) then 1 else *(x, (fact sub1(x))))"
  '(lambda (k1)
     (f (zero? x)
       (lambda (v2)
         (if v2
           (let ((v1 1)) (k1 (add1 v1)))
           (fact (sub1 x)
             (lambda (v3) (let ((v1 (* x v3))) (k1 (add1 v1))))))))))

(add-test! 'lang8-4 'cps-5 "
let a = (f x) b = (g x) c = (h (i (j (t x))))
in cons(a,cons(b,cons(c,emptylist())))"
  '(lambda (k1)
     (f x
       (lambda (z1)
         (g x
           (lambda (z2)
             (t x
               (lambda (v6)
                 (j v6
                   (lambda (v5)
                     (i v5
                       (lambda (v4)
                         (h v4
                           (lambda (z3)
                             (k1 (let ((a z1) (b z2) (c z3))
                                   (cons a
                                     (cons b
                                       (cons c
                                         (empty))))))))))))))))))))

(add-test! 'lang8-4 'cps-6 "
proc(f) let foo = proc(foo,ls) 
                   if null?(ls)
                   then emptylist()
                   else cons((f car(ls)), (foo foo cdr(ls)))
        in proc(ls)(foo foo ls)"
  '(lambda (k1)
     (k1 (lambda (f k1)
           (k1 (let ((foo
                       (lambda (foo ls k1)
                         (if (null? ls)
                           (k1 (empty))
                           (f (car ls)
                             (lambda (v1)
                               (foo foo
                                 (cdr ls)
                                 (lambda (v2) (k1 (cons v1 v2))))))))))
                 (lambda (ls k1) (foo foo ls k1))))))))

(add-test! 'lang8-4 'cps-7 "
 (f let f = 3 in add1(f))"
  '(lambda (k1) (f (let ((f 3)) (add1 f)) k1)))

(add-test! 'lang8-4 'cps-8 "(k (g let g=3 in (f g x)))"
  '(lambda (k1)
     (let ((k1 (lambda (v2) (g v2 (lambda (v1) (k v1 k1))))))
       (let ((g 3)) (f g x k1)))))

(add-test! 'lang8-4 'cps-8 "(even
  letrec
    even(x) = if zero?(x) then 1 else (odd sub1(x))
    odd(x)  = if zero?(x) then 0 else (even sub1(x))
  in (odd 13))"
  '(lambda (k1)
     (let ((k1 (lambda (v1) (even v1 k1))))
       (letrec ((even
                  (lambda (x k1) (if (zero? x) (k1 1) (odd (sub1 x) k1))))
                (odd
                  (lambda (x k1) (if (zero? x) (k1 0) (even (sub1 x) k1)))))
         (odd 13 k1)))))

(add-test! 'lang8-5print 'two-prints
  "(f print((g x)) print(4))"
  '(lambda (k1)
  (g x
     (lambda (v3)
       (printc
         v3
         (lambda (v1) (printc 4 (lambda (v2) (f v1 v2 k1)))))))))

(add-test! 'lang8-5print 'letcc-no-set-1
  "+(1, letcc j in +(4, throw 3 to j))"
  '(lambda (k1)
     (let ((k1 (lambda (v1) (k1 (+ 1 v1)))))
       (let ((j k1)) (j 3)))))

(add-test! 'lang8-5print 'letcc-no-set-2
  "let x = 4 g = proc(n)*(n,n) in (g letcc g in (f throw x to g))"
  '(lambda (k1)
     (let ((x 4) (g (lambda (n k1) (k1 (* n n)))))
       (let ((k1 (lambda (v1) (g v1 k1)))) (let ((g k1)) (g x))))))


  tests for 8-5set.scm .   These duplicate the tests in 8-4.scm , since

(add-test!
  'lang8-5set
  'pgm8-5-1
  "letrec
  fact(x) = if zero?(x) then 1 else *(x, (fact sub1(x)))
in (fact 6)"
  '(lambda (k1)
     (letrec ((fact
               (lambda (x k1)
                 (derefc
                   x
                   (lambda (v7)
                     (let ((v1 (zero? v7)))
                       (if v1
                           (k1 1)
                           (derefc
                             x
                             (lambda (v2)
                               (derefc
                                 fact
                                 (lambda (v4)
                                   (derefc
                                     x
                                     (lambda (v6)
                                       (let ((v5 (sub1 v6)))
                                         (v4 v5
                                             (lambda (v3)
                                               (k1 (* v2
                                                      v3))))))))))))))))))
       (derefc fact (lambda (v8) (v8 6 k1))))))
(add-test!
  'lang8-5set
  'pgm8-5-2
  "letrec
         even(x) = if zero?(x) then 1 else (odd sub1(x))
         odd(x)  = if zero?(x) then 0 else (even sub1(x))
       in (odd 13)"
  '(lambda (k1)
     (letrec ((even
               (lambda (x k1)
                 (derefc
                   x
                   (lambda (v10)
                     (let ((v6 (zero? v10)))
                       (if v6
                           (k1 1)
                           (derefc
                             odd
                             (lambda (v7)
                               (derefc
                                 x
                                 (lambda (v9)
                                   (let ((v8 (sub1 v9)))
                                     (v7 v8 k1))))))))))))
              (odd
               (lambda (x k1)
                 (derefc
                   x
                   (lambda (v5)
                     (let ((v1 (zero? v5)))
                       (if v1
                           (k1 0)
                           (derefc
                             even
                             (lambda (v2)
                               (derefc
                                 x
                                 (lambda (v4)
                                   (let ((v3 (sub1 v4)))
                                     (v2 v3 k1)))))))))))))
       (derefc odd (lambda (v11) (v11 13 k1))))))
(add-test!
  'lang8-5set
  'pgm8-5-3
  "letrec even(odd,x) =  if zero?(x) then 1 else (odd sub1(x))
   in letrec  odd(x)  = if zero?(x) then 0 else (even odd sub1(x))
   in (odd 13)"
  '(lambda (k1)
     (letrec ((even
               (lambda (odd x k1)
                 (derefc
                   x
                   (lambda (v5)
                     (let ((v1 (zero? v5)))
                       (if v1
                           (k1 1)
                           (derefc
                             odd
                             (lambda (v2)
                               (derefc
                                 x
                                 (lambda (v4)
                                   (let ((v3 (sub1 v4)))
                                     (v2 v3 k1)))))))))))))
       (letrec ((odd
                 (lambda (x k1)
                   (derefc
                     x
                     (lambda (v11)
                       (let ((v6 (zero? v11)))
                         (if v6
                             (k1 0)
                             (derefc
                               even
                               (lambda (v7)
                                 (derefc
                                   odd
                                   (lambda (v8)
                                     (derefc
                                       x
                                       (lambda (v10)
                                         (let ((v9 (sub1 v10)))
                                           (v7 v8 v9 k1)))))))))))))))
         (derefc odd (lambda (v12) (v12 13 k1)))))))
(add-test!
  'lang8-5set
  'pgm8-5-4
  "+(1, letcc j in +(4, throw 3 to j))"
  '(lambda (k1)
     (let ((k1 (lambda (v1) (k1 (+ 1 v1)))))
       (let ((j k1)) (derefc j (lambda (v3) (v3 3)))))))
(add-test!
  'lang8-5set
  'pgm8-5-5
  "add1(if (f zero?(x)) then 1 else *(x, (fact sub1(x))))"
  '(lambda (k1)
     (derefc
       f
       (lambda (v8)
         (derefc
           x
           (lambda (v10)
             (let ((v9 (zero? v10)))
               (v8 v9
                   (lambda (v2)
                     (if v2
                         (let ((v1 1)) (k1 (add1 v1)))
                         (derefc
                           x
                           (lambda (v3)
                             (derefc
                               fact
                               (lambda (v5)
                                 (derefc
                                   x
                                   (lambda (v7)
                                     (let ((v6 (sub1 v7)))
                                       (v5 v6
                                           (lambda (v4)
                                             (let ((v1 (* v3 v4)))
                                               (k1 (add1 v1))))))))))))))))))))))
(add-test!
  'lang8-5set
  'pgm8-5-6
  "
let a = (f x) b = (g x) c = (h (i (j (t x))))
in cons(a,cons(b,cons(c,emptylist())))"
  '(lambda (k1)
     (derefc
       f
       (lambda (v19)
         (derefc
           x
           (lambda (v20)
             (v19 v20
                  (lambda (z1)
                    (derefc
                      g
                      (lambda (v17)
                        (derefc
                          x
                          (lambda (v18)
                            (v17 v18
                                 (lambda (z2)
                                   (derefc
                                     h
                                     (lambda (v9)
                                       (derefc
                                         i
                                         (lambda (v11)
                                           (derefc
                                             j
                                             (lambda (v13)
                                               (derefc
                                                 t
                                                 (lambda (v15)
                                                   (derefc
                                                     x
                                                     (lambda (v16)
                                                       (v15 v16
                                                            (lambda (v14)
                                                              (v13 v14
                                                                   (lambda (v12)
                                                                     (v11 v12
                                                                          (lambda (v10)
                                                                            (v9 v10
                                                                                (lambda (z3)
                                                                                  (let ((a
                                                                                         z1)
                                                                                        (b
                                                                                         z2)
                                                                                        (c
                                                                                         z3))
                                                                                    (derefc
                                                                                      a
                                                                                      (lambda (v4)
                                                                                        (derefc
                                                                                          b
                                                                                          (lambda (v6)
                                                                                            (derefc
                                                                                              c
                                                                                              (lambda (v8)
                                                                                                (let ((v7
                                                                                                       (cons v8
                                                                                                             (empty))))
                                                                                                  (let ((v5
                                                                                                         (cons v6
                                                                                                               v7)))
                                                                                                    (k1 (cons v4
                                                                                                              v5)))))))))))))))))))))))))))))))))))))))))))
(add-test!
  'lang8-5set
  'pgm8-5-7
  "
proc(f) let foo = proc(foo,ls) 
                   if null?(ls)
                   then emptylist()
                   else cons((f car(ls)), (foo foo cdr(ls)))
        in proc(ls)(foo foo ls)"
  '(lambda (k1)
     (k1 (lambda (f k1)
           (k1 (let ((foo
                      (lambda (foo ls k1)
                        (derefc
                          ls
                          (lambda (v11)
                            (let ((v1 (null? v11)))
                              (if v1
                                  (k1 (empty))
                                  (derefc
                                    f
                                    (lambda (v8)
                                      (derefc
                                        ls
                                        (lambda (v10)
                                          (let ((v9 (car v10)))
                                            (v8 v9
                                                (lambda (v2)
                                                  (derefc
                                                    foo
                                                    (lambda (v4)
                                                      (derefc
                                                        foo
                                                        (lambda (v5)
                                                          (derefc
                                                            ls
                                                            (lambda (v7)
                                                              (let ((v6
                                                                     (cdr v7)))
                                                                (v4 v5
                                                                    v6
                                                                    (lambda (v3)
                                                                      (k1 (cons v2
                                                                                v3)))))))))))))))))))))))))
                 (lambda (ls k1)
                   (derefc
                     foo
                     (lambda (v12)
                       (derefc
                         foo
                         (lambda (v13)
                           (derefc
                             ls
                             (lambda (v14) (v12 v13 v14 k1))))))))))))))
(add-test!
  'lang8-5set
  'pgm8-5-8
  "
 (f let f = 3 in add1(f))"
  '(lambda (k1)
     (derefc
       f
       (lambda (v1)
         (let ((k1 (lambda (v2) (v1 v2 k1))))
           (let ((f 3)) (derefc f (lambda (v3) (k1 (add1 v3))))))))))
(add-test!
  'lang8-5set
  'pgm8-5-9
  "(k (g let g=3 in (f g x)))"
  '(lambda (k1)
     (derefc
       k
       (lambda (v1)
         (derefc
           g
           (lambda (v3)
             (let ((k1 (lambda (v4) (v3 v4 (lambda (v2) (v1 v2 k1))))))
               (let ((g 3))
                 (derefc
                   f
                   (lambda (v5)
                     (derefc
                       g
                       (lambda (v6)
                         (derefc x (lambda (v7) (v5 v6 v7 k1)))))))))))))))
(add-test!
  'lang8-5set
  'pgm8-5-10
  "  (even
  letrec
    even(x) = if zero?(x) then 1 else (odd sub1(x))
    odd(x)  = if zero?(x) then 0 else (even sub1(x))
  in (odd 13))"
  '(lambda (k1)
     (derefc
       even
       (lambda (v1)
         (let ((k1 (lambda (v2) (v1 v2 k1))))
           (letrec ((even
                     (lambda (x k1)
                       (derefc
                         x
                         (lambda (v12)
                           (let ((v8 (zero? v12)))
                             (if v8
                                 (k1 1)
                                 (derefc
                                   odd
                                   (lambda (v9)
                                     (derefc
                                       x
                                       (lambda (v11)
                                         (let ((v10 (sub1 v11)))
                                           (v9 v10 k1))))))))))))
                    (odd
                     (lambda (x k1)
                       (derefc
                         x
                         (lambda (v7)
                           (let ((v3 (zero? v7)))
                             (if v3
                                 (k1 0)
                                 (derefc
                                   even
                                   (lambda (v4)
                                     (derefc
                                       x
                                       (lambda (v6)
                                         (let ((v5 (sub1 v6)))
                                           (v4 v5 k1)))))))))))))
             (derefc odd (lambda (v13) (v13 13 k1)))))))))
