doc-src/Exercises/2003/a6/a6.thy
changeset 15891 260090b54ef9
parent 15890 ff6787d730d5
child 15892 153541e29155
equal deleted inserted replaced
15890:ff6787d730d5 15891:260090b54ef9
     1 (*<*)
       
     2 theory a6 = Main:
       
     3 (*>*)
       
     4 
       
     5 
       
     6 subsection {* Optimising Compiler Verification *}
       
     7 
       
     8 text {*
       
     9 Section 3.3 of the Isabelle tutorial describes an expression compiler for a stack machine. In this exercise we will build and verify an optimising expression compiler for a register machine.
       
    10 *}
       
    11 
       
    12 text {*\subsubsection*{The Source Language: Expressions}*}
       
    13 
       
    14 text {*
       
    15 The arithmetic expressions we will work with consist of variables, constants, and an arbitrary binary operator @{text "oper"}.
       
    16 *}
       
    17 
       
    18 consts oper :: "nat \<Rightarrow> nat \<Rightarrow> nat";
       
    19 
       
    20 types var = string;
       
    21 
       
    22 datatype exp = 
       
    23     Const nat 
       
    24   | Var var
       
    25   | Op exp exp
       
    26 ;
       
    27 
       
    28 text {*
       
    29 The state in which an expression is evaluated is modelled by an {\em environment} function that maps variables to constants.
       
    30 *}
       
    31 
       
    32 types env = "var \<Rightarrow> nat";
       
    33 
       
    34 text {*
       
    35 Define a function @{text "value"} that evaluates an expression in a given environment.
       
    36 *}
       
    37 
       
    38 consts value :: "exp \<Rightarrow> env \<Rightarrow> nat";
       
    39 
       
    40 text {*\subsubsection*{The Register Machine}*}
       
    41 
       
    42 text {*
       
    43 As the name suggests, a register machine uses a collection of registers to store intermediate results. There exists a special register, called the accumulator, that serves as an implicit argument to each instruction. The rest of the registers make up the register file, and can be randomly accessed using an index. 
       
    44 *}
       
    45 
       
    46 types regIndex = nat;
       
    47 
       
    48 datatype cell = 
       
    49     Acc
       
    50   | Reg regIndex;
       
    51 
       
    52 
       
    53 text {*
       
    54 The state of the register machine is denoted by a function that maps storage cells to constants.
       
    55 *}
       
    56 
       
    57 types state = "cell \<Rightarrow> nat";
       
    58 
       
    59 text {*
       
    60 The instruction set for the register machine is defined as follows:
       
    61 *}
       
    62 
       
    63 datatype instr = 
       
    64   LI nat        
       
    65   -- "Load Immediate: loads a constant into the accumulator." 
       
    66 | LOAD regIndex 
       
    67   -- "Loads the contents of a register into the accumulator."
       
    68 | STORE regIndex 
       
    69   -- "Saves the contents of the accumulator in a register." 
       
    70 | OPER regIndex 
       
    71   -- {* Performs the binary operation @{text "oper"}.*}
       
    72     -- "The first argument is taken from a register."
       
    73     -- "The second argument is taken from the accumulator." 
       
    74     -- "The result of the computation is stored in the accumulator."
       
    75 ;
       
    76 
       
    77 text {*
       
    78 A program is a list of such instructions. The result of running a program is a change of state of the register machine. Define a function @{text "exec"} that models this.
       
    79 *}
       
    80 
       
    81 consts exec :: "state \<Rightarrow> instr list \<Rightarrow> state"
       
    82 
       
    83 text {*\subsubsection*{Compilation}*}
       
    84 
       
    85 text {*
       
    86 The task now is to translate an expression into a sequence of instructions that computes it. At the end of execution, the result should be stored in the accumulator.
       
    87 
       
    88 Before execution, the values of each variable need to be stored somewhere in the register file. A {\it mapping} function maps variables to positions in the register file.
       
    89 *}
       
    90 
       
    91 types map = "var \<Rightarrow> regIndex";
       
    92 
       
    93 text {*
       
    94 Define a function @{text "cmp"} that compiles an expression into a sequence of instructions. The evaluation should proceed in a bottom-up depth-first manner.
       
    95 
       
    96 State and prove a theorem expressing the correctness of @{text "cmp"}.
       
    97 
       
    98 Hints:
       
    99 \begin{itemize}
       
   100   \item The compilation function is dependent on the mapping function.
       
   101   \item The compilation function needs some way of storing intermediate results. It should be clever enough to reuse registers it no longer needs.
       
   102   \item It may be helpful to assume that at each recursive call, compilation is only allowed to use registers with indices greater than a given value to store intermediate results.
       
   103 \end{itemize}
       
   104 *}
       
   105 
       
   106 text {*\subsubsection*{Compiler Optimisation: Common Subexpressions}*}
       
   107 
       
   108 text {*
       
   109 In the previous section, the compiler @{text "cmp"} was allowed to evaluate a subexpression every time it occurred. In situations where arithmetic operations are costly, one may want to compute commonly occurring subexpressions only once.
       
   110 
       
   111 For example, to compute @{text "(a op b) op (a op b)"}, @{text "cmp"} was allowed three calls to @{text "oper"}, when only two were needed.
       
   112 
       
   113 Develop an optimised compiler @{text "optCmp"}, that evaluates every commonly occurring subexpression only once. Prove its correctness.
       
   114 *}
       
   115 
       
   116 (*<*) end (*>*)