
                   Outline of Steps Taken to Implement the Compiler
                        and tests to make sure it works
                 ====================================================

Commands: We implemented the following commands.
  - Assignments: v3 = v4+a[7]; a[v2+2*v3] = v9;
  - If: if( v2 $<$= v8 ) { .. } else { .. }
  - While: while( v2 $<$= v8 ) { .. }
  - Input: in.nextInt()
  - Output: System.out.println( "Hello World" + (v3+v4) );
  - Procedure Calls: p1( v4+a[7], a[v2+2*v3] )
  - Procedure Returns: return v4+a[7];

Data Types: 
  - Integer Variables: All variables are of type integer.
  - Boolean Expressions: Booleans expressions are implemented to be
    used within if and while statements, but not to be assigned to a
    variable.
  - Constant Strings: Strings are implemented to be use within
    System.out.println("Hello World") but not to be assigned to a
    variable or manipulated.
  - Hex to ASCII: The hard part about implementing strings was not
    outputting ``Hello World'', but once MARIE was told to output ASCII
    instead of Decimals, we had to write a program that would convert our
    integers to ASCII. When the MARIE code is running this is by far the
    slowest task. For this reason, the compiler has a second mode, in
    which it produced MARIE code that skips the ``Hello World'' strings
    and outputs the integers as Decimals.

Operations: 
  - Mult,Div,Add,Subt: Complex expressions on integers can be
    constructed like v3 * (v2+7). We had to implement multiplication and
    division in MARIE because these were not primitive operations.
  - Comparisons: Integer comparisons with == ! = $<$ $<=$ $>$ and $>=$ are 
    implemented.
  - And,Or: Complex expressions on booleans can be constructed like
      v2 <= v8 && ( v3 = 0 || v4 < v2 ).

/***********************************************************************************************

Evaluator
=========

Tasks:
------

- I had to learn how the following grammar can be used to express
expressions of the form (v2+3)*4+7 using the following grammar.

   Exp             ==>    Term   
                   ==>    Term +|- Term +|- ... +|- Term

   Term            ==>    Factor
                   ==>    Factor *|/ Factor *|/ ... *|/ Factor
   
   Factor          ==>    Int   
                   ==>    ( Exp ) 
                   ==>    VarName 

   VarName         ==>    v0 | v1 | ... | v9

For example, given the input (v2+3)*4+7
  - (v2+3)*4+7 is an expression because is the sum of the terms (v2+3)*4 and 7.
  - (v2+3)*4 is a term because is the product of the factors (v2+3) and 3.
  - (v2+3) is a factor because is the expression v2+3 in brackets. 
  - v2+3 is an expression because is the sum of the terms v2 and 3.
  - v2 is a term because is a factor.
  - v2 is a factor because is a VarName
  - v2 is VarName because is one of v0, ... ,v9.

- My father already had code (not in Java) for parsing such
expressions. I had rewrite it in Java.

- Then I changed the parser so that the routines GetExp, GetTerm,
and GetFact return evaluations of the expression, term, and factor
found.  For example, given the input v2*3+7

  - How GetFact parses/evaluates v2:
      - It returns the value 2 because the values are set to 
          v0 = 0, v1 = 1, v2 = 2, v3 = 3, ..., v9 = 9

  - How GetTerm parses/evaluates v2*3:
      - Asks GetFact to evaluating the first factor v2. It returns 2.
      - Sees the '*' so continues.
      - Asks GetFact to evaluating the second factor 7. It returns 3.
      - Multiplies these and returns 6.

  - How GetExp parses/evaluates v2*3+7:
      - Asks GetTerm to evaluating the first term v2*3. It returns 6.
      - Sees the '+' so continues.
      - Asks GetTerm to evaluating the second term 7. It returns 7.
      - Adds these and returns 13.

- Then I got the program to read in more than one expression separated
by ';', printing out the values returned.

- This alone would have been a quite good project!

Test Input:
------------
   v3;
   2+v3;
   5*(2+v3)-15;
   (5*(2+v3)-15)*(1+2);
   1+(5*(2+v3)-15)*(1+2)-2;
   10/v5;
   10/v5*v2;
   5-20;
   -20;
   1+1;

Test Output:
-------------
   Main 3
   Main 5
   Main 10
   Main 30
   Main 29
   Main 2
   Main 4
   Main -15
   Error: Bad Factor 45
   Main 0

Note:
  - The "Main" is there to specify that the main program is printing
    it and not say getTerm.
  - The error occurred because "-20" is a bad expression because it starts with - (ascii 45).
  - Errors: The recovery to the next expression "1+1" did not work, but was ignored.

/***********************************************************************************************

Complier of Assignments of Expression to single variable
=========================================================

Tasks: 
------

- Hard wired MARIE memory cells for variables v0, v1, ..., v9.
  The code copied from a file called memorycode is:

      v0,  Dec 0000     / 010  
      v1,  Dec 0001     / 011
      v2,  Dec 0002     / 012
      v3,  Dec 0003     / 013
      v4,  Dec 0004     / 014
      v5,  Dec 0005     / 015
      v6,  Dec 0006     / 016
      v7,  Dec 0007     / 017
      v8,  Dec 0008     / 018
      v9,  Dec 0009     / 019

  This sets up a memory cell at labeled v0 with initial value 0.
  We commented it by / 010 to remind us that this will be the cell addressed by 0010.

- Then I had to extend the parser/grammar to parse assignments the form v1 = (v2+3)+7;

   Assignmentv     ==>    VarName = Exp;

- Then I changed the parser so that the routines GetExp, GetTerm,
  and GetFact no longer return evaluations but outputs MARIE code to evaluate them.

  - ExpS0, ExpS1, ..., ExpSF are memory cells that act as a stack for
  evaluating expressions.

- For example, given the input v1 = v2*3+7
  - How GetFact parses/compiles v2 to get MARIE to put the result in ExpS0:
    The code produced is:
            Load v2
            Store ExpS0

  - How GetTerm parses/compiles v2*3 to get MARIE to put the result in ExpS0:
      - Asks GetFact to write code that evaluates the first factor v2 and
        stores it in ExpS0. 
      - Sees the '*' so continues.
      - Asks GetFact to write code that evaluates the second factor 3 and
        stores it in ExpS1. 
      - Writes code to multiply ExpS0 and ExpS1 and store the result in ExpS0
             ExpS0 = ExpS0 * ExpS1
      - oops MARIE neither has assignments nor multiplication.
        Skip this till later.

  - How GetExp parses/compiles v2*3+7 to get MARIE to put the result in ExpS0:
      - Asks GetTerm to write code that evaluates the first term v2*v3 and
        stores it in ExpS0. 
      - Sees the '*' so continues.
      - Asks GetTerm to write code that evaluates the second term 7 and
        stores it in ExpS1. 
      - Writes code to add ExpS0 and ExpS1 and store the result in ExpS0
        The code produced is:
             Load  ExpS0 
             Add   ExpS1
             Store ExpS0

  - How GetAssignmentv parses/compiles v1 = v2*3+7 to get MARIE to do this assignment. 
      - Asks GetExp to write code that evaluates the expression v2*v3+7 and
        stores it in ExpS0. 
      - Writes code to move this value to v1.
        The code produced is:
             Load  ExpS0 
             Store v1

  - Note the code produced is moves things a little more than it needs to.
             Store  ExpS0 
             Load  ExpS0 
             Store v1

- This alone would have been a sufficiently hard project!

Test Input:
------------
   v4 = v3;
   v5 = 2+v3;
   v6 = 5+(2+v3)-7;
   v7 = (5+(2+v3)-7)+(1+2);
   v8 = 1+(5+(2+v3)-7)+(1+2)-2;

Test Output:
-------------
   Surprisingly long MARIE code.

Result of the MARIE code.
-------------------------
In memory:
      v4,  Dec 0003     / 014
      v5,  Dec 0005     / 015
      v6,  Dec 0003     / 016
      v7,  Dec 0006     / 017
      v8,  Dec 0005     / 018


/***********************************************************************************************

Introducing Arrays
===================

Tasks: 
------

- Hard wired MARIE memory cells for arrays a[0], a[1], ..., a[9].
  The code copied from a file called memorycode is:

a,      Hex 0030      / 003   Address of a[0] 

	Dec 0010      / 030   Cell addressed by 030 contains the value 10 of a[0]
	Dec 0011      / 031   Cell addressed by 031 contains the value 12 of a[1]
	Dec 0012      / 032   ...

  This sets up a memory cell at labeled v0 with initial value 0.
  We commented it by / 010 to remind us that this will be the cell addressed by 0010.

- Then I had to extend the parser/grammar to parse assignments the form a[v2+2*v3] = a[v2+2]+7;

        Assignmenta     ==>    VarName[Exp] = Exp;

- For example, given the input a[v2+2*v3] = a[v2+2]+7;
  - How GetAssignmentv parses/compiles this to get MARIE to do this assignment. 
      - Remembers the variable name 'a'.
      - Asks GetExp to write code that evaluates the expression v2+2*v3 and
        stores it in ExpS0. 
      - Asks GetExp to write code that evaluates the expression a[v2+2]+7 and
        stores it in ExpS1. 
      - Writes code for a[ExpS0] = ExpS1
        The code produced should be:
             Load a          / AC holds address of a[0] (eg 30)
             Add ExpS0       / Address of a[ExpS0] which is 35
             Store A         / Store the address of a[ExpS0] in A 
             Load ExpS1      / Load value to store in a[ExpS0]
             StoreI A        / Store the value in the memory cell addressed by A.

  - But the problem is that MARIE is SO SO simple that is does not an
    the instruction StoreI to indirectly store a value. Hence, my father
    had to figure out a way to get around this. See his document.

Test Input:
------------
   a[1]=a[5];
   a[v9-v7]=7+a[v2];

Test Output:
-------------
   Surprisingly long MARIE code.

Result of the MARIE code.
-------------------------
In memory:
a,      Hex 0030      / 003   Address of a[0] 

	Dec 0010      / 030   Cell addressed by 030 contains the value 10 of a[0]
	Dec 0015      / 031   Cell addressed by 031 contains the value 15 of a[1]
	Dec 0019      / 032   Cell addressed by 033 contains the value 19 of a[2]

/***********************************************************************************************

Introducing if and while
=========================

Tasks: 
------

- Then I implemented Boolean expressions like v2 <= v8 && ( v3 = 0 || v4 < v2 )
  This was very similar to evaluating expressions.

- Then I had to extend the parser/grammar to parse assignments the form if(v1<2) v2=3;

        IfStatement     ==>    if( BooleanExp )
                                 BlockCode
                        ==>    if( BooleanExp )
                                 BlockCode
                               else
                                 BlockCode
        
        WhileStatement  ==>    while( BooleanExp )
                                 BlockCode

- I found a bug that 

    if( v1==1 ) 
        v2=2;
    if( v3==1 )
        v2=3;
    else
        v=4;
  
  was being compiled as 

    if( v1==1 ) 
        v2=2;
        if( v3==1 )
           v2=3;
        else
           v=4;

  The reason is that we had the faulty grammar

      BlockCode     ==>    ListCode
                    ==>    { ListCode }
    
      ListCode      ==>    LineCode
                           LineCode
                             ...
                           LineCode    

  All was well when this grammar was changed to 
      
      BlockCode     ==>    LineCode
                    ==>    { ListCode }

Test Input:
------------

      v1 = 4;
      if( v1 > 3 && v1 < 5 )
         v2 = 3;
      else {
         v2 = 4;
         v3 = 5;
      }
      
      if( v1 < 0 || v1 > 5 ) {
         v4 = 3;
       }
      else 
         v4 = 4;
      
      v1 = 1;
      while( v1 < 5 ) {
        a[v1] = 4; 
        v1 = v1+1;
      }
      
   a[1]=a[5];
   a[v9-v7]=7+a[v2];

Result of the MARIE code.
-------------------------
   As expected.

      
/***********************************************************************************************

Introducing Multiplication and Division
========================================

Tasks: 
------

- My father wrote a program in Java to multiply and one to divide.
Normally, these are accomplished by manipulating and shifting the bits
of the numbers. However, MARIE is so simple that it does not have
such instructions. Hence, he had to do it only with addition,
subtraction, if, and while.

- I used the complier that I had written so far to compile his Java
programs for multiplying and dividing into MARIE code.

- Global change and replace changed the labels used in the MARIE code.

- I added the resulting MARIE code to my compiler so that it could
compile JAVA code into MARIE code that multiplies and divides.

Test Input:
------------

    v0 = 16 * 3;
    v1 = 0 * 5;
    v2 = 4 * 5;
    v3 = -8 * 5;
    v4 = 8 * -5;
    v5 = -8 * -5;
    v6 = 34 * 5;
    v7 = 32767 * 5;
    v8 = 32767 * 2;

    v0 = 16 / 3;
    v1 = 0 / 5;
    v2 = 4 / 5;
    v3 = -8 / 5;
    v4 = 8 / -5;
    v5 = -8 / -5;
    v6 = 34 / 5;
    v7 = 32767 / 5;
    v8 = 32767 / 2;

Result of the MARIE code.
-------------------------
   As expected.


/***********************************************************************************************

Introducing Output
===================

Tasks: 
------
      
- Then I had to extend the parser/grammar to parse output statements 

   OutPut    ==>    System.out.println(Factor+"Hello World"+Factor);      
             ==>    System.out.print("Hello\nWorld"+Factor);                           

- The reason the grammar has a Factor and not an Expression in it is because 
  5 and (2+5) are factors, while 2+5 is an expression.
    System.out.print("Hello\nWorld"+5); is allowed.
    System.out.print("Hello\nWorld"+(2+5)); is allowed.
    System.out.print("Hello\nWorld"+2+5); is also allowed but means something different.

- Hex to ASCII: The hard part about implementing strings was not
  outputting ``Hello World'', but once MARIE was told to output ASCII
  instead of Decimals, my father had to write a program that would convert our
  integers to ASCII. When the MARIE code is running this is by far the
  slowest task. For this reason, the compiler has a second mode, in
  which it produced MARIE code that skips the ``Hello World'' strings
  and outputs the integers as Decimals.

- MARIE did not seem to want to print a blank space, so I replaced it with a '_'.

Test Input:
------------

    System.out.print("Hello World\n" + (2+3) + " Really Hi");  
    System.out.println(" New line");  
    System.out.println("v1 = " + v1);
    System.out.println("a[4] = " + a[4]);
    System.out.println("v3 = " + v3);
    System.out.println("b[2] = " + b[2]);

Result of the MARIE code.
-------------------------
   As expected.


/***********************************************************************************************

Introducing Variable Declarations
==================================

Tasks: 
------
      
- Then I had to extend the parser/grammar to parse output statements 

    LVarName        ==>    any string starting with a small letter
    
    LListVarDec     ==>    LVarDec
                           LVarDec
                             ...
                           LVarDec
    
    LVarDec         ==>    int LVarName;
                    ==>    int LVarName = Int;
                    ==>    int[] LVarName = new int[Int];

    LVarName        ==>    any string starting with a small letter
    GVarName        ==>    any string starting with a capital letter

- Different routines can use the same variable name for their local variables. 
  Hence, the MARIE memory label used is the local variables names concatenated 
  with the procedure name. 

Test Input:
------------

    int v1 = 5;
    int[] a = new int[3]; 

Resulting MARIE code.
----------------------

              Jump S_main  /Jump over data 
    v1_main,  Dec 005 
    a_main,   JnS L000     /Address of a_main[0] 
    L000,     Hex 0        /Memory cell for a_main[0] 
              Hex 0 
              Hex 0 
    S_main,   ...

/***********************************************************************************************

Introducing Procedure Calls
============================

    Program         ==>    ProgramBlock
                           ProgramBlock
                             ...
                           ProgramBlock
    
    ProgramBlock    ==>    GListVarDec  
                    ==>    MainProcedure
                    ==>    Procedure
    
    MainProcedure   ==>    public static void main (String[] args) {
                             LListVarDec
                             ListCode
                           }
    
    Procedure       ==>    public static int ProcedureName( int LVarName, int LVarName, ...) {
                             LListVarDec
                             ListCode
                           }
    
    ProcedureName   ==>    any string starting with a letter


- MARIE provides nice instructions for jumping into and out of procedures.

    The Java code
         public static void main (String[] args) {
             p1();
         }

         public static int p1() {

             return( B );
         }

    is implemented as

    main,    ...
             JnS p1       / Save the current value of PC in memory cell addressed by p1
                          / and jump to the code cell one after that addressed by p1.
             continue ... 
    
    Double   HEX 0         / Entry Point and Return Address of Subroutine p1
             continue ...
    
             JumpI p1      / Return to calling code by jumping to the code cell stored in cell p1.


- Passing Values into a Procedure:

A standard compiler, when compiling the Java code for a procedure declaration
   public static int p2( int x, int y ) { ...
must remember that the first parameter is x and the second is y,
so that when it compiles the corresponding calling of the procedure
   u = p2( 4,5 );
it knows that the value 4 needs to be copied into the variable x and
the 5 into y. In  fact, the compiler must make two passes because the
procedure call may occur before before the procedure
declaration.

Our compiler, however, is one pass and memoryless.  When translating
the calling procedure ``u = p2( 4,5 );'' into MARIE code, the compiler
has access to the values 4 and 5 to be copied but does not know the
variable names x and y.  On the other hand, when translating the called
procedure ``p2( int x, int y )'' into MARIE code, the compiler has
access the variable names x and y, but does not know the values to
copy there.  Who then does the copying?

At first we thought that this meant that the variable names used for
the parameter passing variables would need to be restricted to being
v0, v1, ..., v9, vA, .., vE.

However, we then had the insight that this could be done in two
steps.  The MARIE code will have fixed data cells labeled input0,
input1, ..., imputE, and Return. The calling procedure will evaluate
the values 4 and 5 and copy them into the fixed locations input0 and
input1. The MARIE code then jumps to the called procedure.  The call
procedure will copy these values from the fixed locations input0 and
input1 into its local variables x_p2 and y_p2. When the command ``return
7'' is found, the 7 is copied to the fixed location Return and the MARIE
procedure returns to the calling procedure. The calling procedure then
copies the value from Return into its local variable u_p1.

Test Goals
------------
  - Procedure calls
  - Parameter passing
  - Returning a value
  - Integrating returned value into an expression

Test Input:
------------

public static int p1(int x) {
   System.out.println("x = " + x);
   return 5;
}

public static void main (String[] args) { 
   int u;
   u = p1(31);
   System.out.println("returned "+ u);
   u = 10+2*p1(32);
   System.out.println("returned "+ u);
}


Output of the MARIE code.
--------------------------

   x_=_31
   returned_5
   x_=_32
   returned_20

/***********************************************************************************************
  Larger Test
 =============

Test Goals
------------
  - Larger version of previous
  - Global variables

Test Input:
------------

static int G1 = 8;
static int G2;

public static int p1(int x, int y, int z) {
   int v1 = 9;
   int v2;
   int[] a = new int[5]; 
   
   System.out.println("G1 = " + G1 + " G3 = " + G3);
   v1 = 4;
   a[1] = 5;
   a[2] = v1 + a[1];
   System.out.println("x = " + x + " y = " + y + " z = " + z );
   System.out.println("a = " + a[2] + " G2 = " + G2);
   return 5;
}

static int G3 = 2;

public static void main (String[] args) { 
   int u;
   G2 = 7;
   u = 10+2*p1(31,32,33);
   G2 = p2(41,42);
   System.out.println("u = " + u);
}

static int G4 = 3;

public static int p2(int u, int y) {
   int v1;
   
   v1 = 5;
   System.out.println("u = " + u + " y = " + y + " v1 = " + v1 );
   return 45;
}

Output of the MARIE code.
--------------------------

   G1_=_8_G3_=_2
   x_=_31_y_=_32_z_=_33
   a_=_9_G2_=_7
   u_=_41_y_=_42_v1_=_5
   u_=_20


/***********************************************************************************************
  Implementing Recursion
 ========================

Recursion and the Stack: Implementing Recursion complicates memory
allocation and procedure calls even further. For a procedure to be
able to call itself, each execution of the routine needs to be able to
have its own values in its local variables. Hence, each needs its own
stack frame within which to allocate is own copy of its local
variables. This means that a local variable like x can no longer be
stored in fixed location with the assembler code ``x, Dec 4'' but
needs to addressed with indirect addressing to where this copy is
stored within the current stack frame.

We did not want to worry about this when compiling procedures and even
procedure calls. Hence, we allocate memory for a procedure's local
variables in a fixed block of data cells at the beginning of the code
for the procedure.  Later when implementing recursion calls, the
calling MARIE procedure needs to worry about other executions of the
same procedure stepping on its values.  Hence, it is designed to copy
the values of its local variables in these fixed locations out to a
new stackframe. When this called procedure returns, the calling
procedure's values are recovered from its stack frame and restored in
the fixed memory locations.

To make this coping easier, we insist that all local variables are
declared within a block at the beginning of the procedure declaration.

Test Goals
------------
  - Test Recursion

Test Input:
------------

public static int Fib(int n) {
   int f;
   System.out.println("In:  n = " + n);
   if( n<=1 ) 
	f = n;
   else
	f = Fib(n-1) + Fib(n-2);
   System.out.println("Out: n = " + n + " f = " + f);
   return f;
}

public static void main (String[] args) { 
   Fib(5);
}

Expected Answer
----------------
 
n =  0  1  2  3  4  5
f =  0  1  1  2  3  5

Output of the MARIE code.
--------------------------

   In:__n_=_5
   In:__n_=_4
   In:__n_=_3
   In:__n_=_2
   In:__n_=_1
   Out:_n_=_1_f_=_1
   In:__n_=_0
   Out:_n_=_0_f_=_0
   Out:_n_=_2_f_=_1
   In:__n_=_1
   Out:_n_=_1_f_=_1
   Out:_n_=_3_f_=_2
   In:__n_=_2
   In:__n_=_1
   Out:_n_=_1_f_=_1
   In:__n_=_0
   Out:_n_=_0_f_=_0
   Out:_n_=_2_f_=_1
   Out:_n_=_4_f_=_3
   In:__n_=_3
   In:__n_=_2
   In:__n_=_1
   Out:_n_=_1_f_=_1
   In:__n_=_0
   Out:_n_=_0_f_=_0
   Out:_n_=_2_f_=_1
   In:__n_=_1
   Out:_n_=_1_f_=_1
   Out:_n_=_3_f_=_2
   Out:_n_=_5_f_=_5

