;;
;; Chapter 5 OOP Tests
;;

(load "5-3.scm")
(load "5-4-1.scm")

(run ;; A simple OO example with invariant i=-j.
"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
")

(run ;; An example displaying dynamic dispatch
"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()
")

(run ;; Sending messages to itself
"
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)
")
;; Exercise:  change oddeven so that initial number is stored in a field

(run ;; Example using inheritance
"
class c1 extends object 
  field ivar1
  method initialize()set ivar1 = 1
  
class c2 extends c1 
  field ivar1
  method initialize() 
   begin
    super initialize() %; 
%    set ivar1 = 2
   end
  method setiv1(n)set ivar1 = n
  method getiv1()ivar1
  
let o = new c2 ()
    t1 = 0
in begin
       set t1 = send o getiv1();
       send o setiv1(33);
       list(t1,send o getiv1())
   end                      
" )



(run ;; invoking superclass methods
"
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()
        )
"
)

(run ;; dynamic dispatching from superclass
"
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
%  method mb() super ma()

let x = new c2 ()
in list(send x ma(),send x mb())
"
)

(run ;; invoking a subclass method from a superclass
"
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(),
        send o1 m2(),
        send o1 m3(),
        send o2 m1(),
        send o2 m2(),
        send o2 m3() 
       )
"
)

(run  ;; accessing super-class shadowed fields through methods
"
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())
"
)

(run  ;; super is static, send self is dynamic
"
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()
")

;; Exercise:   go over the following code, then try it out!

(run
"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() 
   begin super 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                      
")
