          Com S 342 --- Principles of Programming Languages

           HOMEWORK 9: ENVIRONMENT PASSING INTERPRETERS III
                  (File $Date: 2006/04/05 16:39:25 $)

Due: problems 3-5 at beginning of class, Thursday, April 13, 2006;
     problems 8-10 at beginning of class, Tuesday, April 18, 2006.

In this homework, you will learn more about interpreters, including
variable assignment and call by reference.  

For this homework, be sure to clearly mark what parts of the code you
changed (e.g., with a comment in the Scheme code) to solve what problems.
For coding problems, aside from your printout of the code, you must
also hand in a transcript of testing.  See the directory
$PUB/homework/hw9 for test scripts for each coding problem. Use the
procedure test-hw9 to run our tests.   If you want to see more
output, execute (show-test-output!); to see less output, execute
(hide-test-output!).

The section headings below give the readings related to the problems.
Please read them.  Refer to homework 7 for some ideas to help aid your
understanding when reading chapter 3 of the text.

ESSENTIALS OF PROGRAMMING LANGUAGES: Section 3.7

1. (suggested practice)
   Think about how you would do exercise 3.39 on page 104 of the text.
   This is already implemented in our interpreters, but using the funky
   named lambda feature of Scheme, so you might want to implement it
   yourself using the parts of Scheme you understand better.

2. (suggested practice)
   Do exercise 3.40 on page 104 of the text.
   Note that this is different than the implementation of define in
   homework 7, although it can use the same or a similar grammar. The
   difference is that there is an assignment that can take place for
   redefinitions. 

3. 
   Roughly following exercise 3.42 on page 105 of the text, your task
   in this problem is to add arrays to the defined language of section
   3.7.  This is done using 4 new primitives in the defined language:
   array, arrayref, arraylen, and arrayset.

a. (40 points) [arrays]
   To do this, first change to a directory of your own where you want
   to keep files for these problems, and then do the following to copy
   files to this directory:

     cp $PUB/homework/hw9/my-3-7.scm my-3-7.scm

   This file has been adapted from ch3-7.scm in the library by adding
   arrays to the domain of expressed values.  These changes have made
   the domain equations contain:

      Expressed-Value = Number + ProcVal + List(Expressed-Value)
                               + Arr
      Arr = (Ref(Expressed-Value))*

   We have also made my-3-7.scm require the file "indirect-arrays.scm"
   from the course library.  This library file defines a datatype for
   array values.  You should read the code there, and consult the
   section on vectors in the Revised^5 Report on Scheme, if need be,
   to see what this code does.

   Your task is to edit the code in my-3-7.scm file to add the
   primitives "array", "arrayref", "arraylen", and "arrayset" to the
   defined language.  First, add the grammar and the abstract syntax
   these four primitives.  Then add their semantics, by modifying
   apply-primitive.  The four primitives are specified as follows.

    For all numbers n, for all arrays a, for all expressed values v,

      array(n) is a fresh array of n elements, where each element in
               the result is the expressed value 0
      arrayref(a, n) is the nth, zero-indexed element of a
      arrayset(a, n, v) changes the value of the nth, zero-indexed
                        element of a to be v, and returns 0
      arraylen(a) is the length of a

    Thus we have the following equations between terms in the defined
    language

     for all non-negative integers n, for all arrays a of length n,
     for all expressed values v,
     for all i such that 0 <= i and i < n,
     and for all j such that 0 <= j and j < n:

      arraylen(array(n)) == n,

      arrayref(array(n), i) == 0

      arrayset(a, i, v) == 0

      arraylen(a) == begin arrayset(a, i, v); arraylen(a) end

      begin arrayset(a, i, v); arrayref(array(a, j)) end
        == if -(i,j)           % i.e., if i is not equal to j
           then arrayref(a, j)
           else v

   After changing the apply-primitive procedure, you can test your
   solution using:

      (test-hw9 "arrays")

   As always hand in a printout of a transcript of your testing and
   your code.  However, you can wait to print out your code, until you
   are done with the problems in this section.  If you do that,
   clearly mark with comments the part of the code used to solve this
   problem.

b. (5 points) [arrays question]
   Answer the question at the end of exercise 3.42 in the text.  (Note
   that that question has a syntax error: the expression p(a) should
   be (p a) in the body of the begin.)  Check your answer by running
   your code for part a.

4. [ref]
(a) (30 points)
   Do exercise 3.43 on page 105.

   For this problem, work in the file my-3-7.scm that you worked on
   for the previous problem.

   To solve the problem, you'll have to change the interpreter's grammar
   to add the "ref" expression and to add the "deref" and "setref"
   primitives.  You also must make similar changes to the abstract syntax.

   The change to the domain of Expressed-Values is as follows:

     Expressed-Value = Number + ProcVal + List(Expressed-Value)
                       + Arr  + Ref(Expressed-Value) 

   After changing the concrete and abstract syntax, in this problem
   you just have to add a treatment of the ref expression, and the
   deref and setref primitives to the interpreter in my-3-7.scm.   

   To explain the semantics of these two primitives a bit more, note
   that the ref expression is supposed to return a reference (pointer
   essentially) to a variable.  It's like the C language's & operator.
   The deref expression obtains the value from a reference, like the C
   language's * operator (not multiplication, but dereference as in
   *p).  Thus deref(ref x) has the same value as the variable x.  The
   setref primitive sets the value pointed to by a reference, which is
   like a combination of * and = in C.  We define the value returned
   by calling the setref primitive to be 0.  For example,

            let x = 3
            in let rx = ref x
               in let srv = setref(rx, 5)
                  in +(+(*(x,100), *(rx,10)), srv)

   would return 550.

   You can test your code with

       (test-hw9 "ref")

   As always hand in a printout of a transcript of your testing and
   your code.  This is the time to print your code for this section.
   Please clearly mark with comments the part of the code used to solve this
   problem (and the previous one).

(b) (10 points)
   Write answers to the two (English) questions at the end of
   exercise 3.43 on page 105. (Hint for the first question: look at
   the test output, using (show-test-output!) before running the tests). 

5. (10 points) [recursion using two passes and assignment]
   Do exercise 3.44 on page 106 of the text.  Just describe how this
   translation works to produce the right answer.  In particular,
   describe how the closure formed for times4 in the translation gets
   the right environment.  You don't have to write any code for this.

6. (suggested practice) [setdynamic]
   Do exercise 3.47 on page 107 of the text.

ESSENTIALS OF PROGRAMMING LANGUAGES: Section 3.8

7. (suggested practice)
   Read and play with the code for the call by reference interpreter
   in $PUB/lib342/ch3-8ref.scm.

8. [drawing pictures for call by reference]

(a) (20 points)
    Draw 2 pictures, corresponding to the state of the expression
    when execution reaches the places indicated by the comments in the code.
    Your pictures should be like those shown in class.  In this
    problem use call by reference.

   let a0 = 342
       a1 = 541
   in let i = 100
      in let f = proc(x,b0,b1) begin
                                %% Draw the first picture for this point
                                set x = +(9,i);
                                set a0 = i;
                                set b1 = b0
                              end
         in begin
             (f i a0 a1);
             %% Draw the second picture for this point
             +(*(100000,i),+(*(1000,a0),a1))
            end

(b) (10 points)
   Give the output of the above expression, using call by reference.
   (You should do this by hand, and only use the computer to check the answer.)

9. (30 points) [drawing pictures for call by value result]
    Repeat the previous problem using call by value result.  Call by
    value result is described in exercise 3.55 on page 114.

10. (50 points) [call by value-result]

   Do exercise 3.55 on page 114 of the text.  However, as with call by
   reference, we won't consider it an error to pass an expression as
   an argument; instead we will assume that a new location (i.e., a direct
   target) is created to hold such arguments, and thus a call such as
   (f add1(c)) will copy the value of add1(c) into the formal, but
   the actual will be copied back to this new location instead of into
   any previously existing variable's location (i.e., the variable c
   won't be affected). 

   To start, change to a directory of your own, and then copy a
   non-module version of the section 3.8 call-by-reference interpreter,
   as follows: 

      cp $PUB/homework/value-result.scm value-result.scm
   
   There are no grammar changes for this problem.  The domains are
   also unchanged.  You just have to change the interpreter to use
   call by value-result as described in the problem.  It may help to
   look at the test cases in $PUB/homework/hw9/value-result.tst to
   understand this better.

   For the implementation, it's very helpful to think about the types
   and the way that refrences and targets are used in the
   implementation of call by reference.  Then think about what you
   want to do, in apply-procval, to copy the arguments' values to new
   targets, execute the procedure body, and then copy the values back
   to the original argument targets at the end.

   (Hint: I found it helpful to reuse some of the code of deref, by
   making a helping procedure from part of it, and having deref call
   that.)

   Hand in a printout of your changes to the interpreter and a
   transcript of your testing.  You can test this problem using

       (test-hw9 "value-result")

11. (suggested practice) [call by reference with arrays]
   Do exercise 3.54 in the text.  Note that the example in the
   exercise at the end, 

      (swap (arrayref a i) (arrayref a j))

   has the wrong syntax, as arrayref is not a user-defined procedure.
   Since arrayref is a primitive, the syntax of the example should
   instead be:

      (swap arrayref(a,i) arrayref(a,j)).

   However, can arrayref really be a primitive for this
   problem?  The alternative is to make it an expression, and then the
   syntax would look, perhaps, like:

      (swap access(a,i) access(a,j))

   where you have added a new access expression to the language.

   Hand in a printout of your changes to the interpreter and a
   transcript of your testing.
