CS212 Section 03/30/98
Given by DLN.


New rules for the environment model:

  * To evaluate (if test cond alt) in an environment env,
     -- evaluate test in env.
     -- if it is true, evaluate cond in env.
        otherwise, evaluate alt in env.

  * To evaluate (bind ((x e)) b) in env:
     -- evaluate e in env.
     -- create a new frame env' pointing to env.
     -- bind x to the value in env'.
     -- evaluate b in env'.

    Note:  to evaluate a binding of more than one variable, translate
    into nested bindings with one variable each.
      (bind ((x-1 e-1) (x-2 e-2) ... (x-n e-n)) b)
    becomes 
      (bind ((x-1 e-1))
        (bind ((x-2 e-2))
          ...
           (bind ((x-n e-n))
             b)...))

    Note the equivalence
      (bind ((x e)) b)
    = 
      ((method (x) b) e).
    You can use this to derive the environment model rule for bind.


    If you look at the picture of a binding, you should see why
    recursion won't work (the environment for a bound closure is
    *above* the frame for that variable binding, so it can't refer to
    itself).


    The only thing that's fishy about all this is that this is _not_
    the way that NOODLLE actually does things.  NOODLLE deals with
    binds in exactly the way that it deals with bind-methods ... which
    matches the environment model rule for bind-methods, but not bind.
    For example,


              (y (method () x))
              (x 2))
         (y))

    will output 2 in NOODLLE but should be 3 by the environment model.


  * To evaluate
      (bind-methods ((f-1 p-1 b-1)
                     (f-2 p-2 b-2)
                      ...
                     (f-n p-2 b-2))
         b)
    in env:
     -- create a new frame env' pointing to env.
     -- "create the closures" in environment env'.
     -- evaluate b in env'.

    This allows mutual recursion ... draw the model for
          (bind-methods
              ((f ((x <integer>))
                 (g (- x 1)))
               (g ((y <integer>))
                 (if (< y 1)
                    0
                    (f (/ y 2)))))
            (f 10))
    and see why bind-methods can't be like bind (is supposed to be).



Suppose we want to write a function count such that:

        ? (count)
        ==> 1
        ? (count)
        ==> 2
        ? (count)
        ==> 3
        ...

Here's one way:
        (define (count <function>)
          (method ()
            (bind ((counter 0))
              (set! counter (+ counter 1))
              counter)))
and here's another:
        (define (count <function>)
          (bind ((counter 0))
            (method ()
              (set! counter (+ counter 1))
              counter)))

One of these works, and one of them doesn't.  Look at them, draw the
environment model diagrams for them, and figure out which one is which.