(program 
  ( // class graph
    (datatype Container 
      (a_Container (contents ItemList)
                   (capacity Number)
		   (total_weight Number)))
    (datatype Item
      (Cont (c Container))
      (Simple (name String) (weight Weight)))

    (datatype Weight
      (a_Weight (v Number)))

    (datatype ItemList
      (Empty)
      (NonEmpty (first Item) (rest ItemList))))


// in EOPL notation:
//(define-datatype Container Container?
//  (a-Container (contents (list-of Item?)) (capacity number?) (total_weight number?)))
//(define-datatype Item Item?
//  (Cont (c Container?))
//  (Simple (name string?) (weight number?)))

  // object graph
  (a_Container 
     (NonEmpty
       (Simple "apple" 5)
       (NonEmpty
         (Cont 
	   (a_Container
	     (NonEmpty
	       (Simple "orange" 8)
	       (Empty)
	     )
             4 // capacity
	     0 // total_weight
           )
         )
	 (Empty)
       )
     )
     5 // capacity
     0 // total_weight
  )

  // strategy
  (from-to Container Weight)

  // visitor
  (visitor summingVis 
    0 // initialize visitor with 0 
    // FinishAction
    summingVis
    before (host Container) (set! host total_weight summingVis)
    after (host Container) (set! host total_weight (- summingVis (get host total_weight)))
    before (host Weight) (+ summingVis (fetch (from-to Weight Number) host))))

// only for checking visitor
(program    
  ((datatype X))
  (X)
  (from-to X Y)
  (visitor PersonCountVisitor 
    0
    PersonCountVisitor
    before (host Person) (+ PersonCountVisitor 1)
  )
)

// only for checking object graph
(program    
  (
    (datatype H (aH (f F)))
    (datatype F 
      (Hid_A (e E) (g G))
      (Hid_B (e E) (g G))
      (Hid_C (g G))
    )
    (datatype E 
      (aE))
    (datatype G 
      (aG))
  )
  (X)
  (from-to X Y)
  (visitor PersonCountVisitor 
    0
    PersonCountVisitor
    before (host Person) (+ PersonCountVisitor 1)
  )
)
