Docstoc

machine

Document Sample
machine Powered By Docstoc
					  CALCULATING AN
EXCEPTIONAL MACHINE




Graham Hutton and Joel Wright
   University of Nottingham
Exception

 An event that causes a computation
  to terminate in a non-standard way.



Abstract Machine

 A term-rewriting system for executing
  programs in a particular language.

                                          1
This Talk

 We show how to calculate an abstract machine
  for a small language with exceptions;


 The key technique is defunctionalization, first
  introduced by John Reynolds in 1972;


 Somewhat neglected in recent years, but now
  re-popularised by Olivier Danvy et al.

                                                    2
Arithmetic Expressions

Syntax:


     data Expr = Val Int | Add Expr Expr


Semantics:


     eval          :: Expr  Int
     eval (Val n)   = n
     eval (Add x y) = eval x + eval y
                                           3
Step 1 - Add Continuations

Make the evaluation order explicit, by rewriting the
semantics in continuation-passing style.


Definition:



    A continuation is a function that is applied to
         the result of another computation.

                                                       4
Example:

                  eval x    + eval y


              computation   continuation


Basic idea:



       Generalise the semantics to make the
           use of continuations explicit.

                                              5
Aim: define a new semantics

     eval’ :: Expr  (Int  Int)  Int


such that

     eval’ e c = c (eval e)


and hence

     eval e = eval’ e (n  n)

                                         6
Case: e = Add x y

    eval’ (Add x y) c

 = c (eval (Add x y))

 = c (eval x + eval y)

 = (n  c (n + eval y)) (eval x)

 = eval’ x (n  c (n + eval y))

 = eval’ x (n  (m  c (n+m)) (eval y))

 = eval’ x (n  eval’ y (m  c (n+m))
                                            7
New semantics:



    eval’                :: Expr  Cont  Int

    eval’ (Val n)      c = c n

    eval’ (Add x y) c = eval’ x (n 

                            eval’ y (m 

                            c (n+m)))



The evaluation order is now explicit.
                                                8
Step 2 - Defunctionalize

Make the semantics first-order again, by rewriting
eval’ using the defunctionalization technique.


Basic idea:



          Represent the continuations we
          actually need using a datatype.

                                                     9
Continuations:


   eval    :: Expr  Int
   eval e = eval’ e (n  n)



   eval’             :: Expr  Cont  Int
   eval’ (Val n)    c = c n
   eval’ (Add x y) c =
       eval’ x (n  eval’ y (m  c (n+m)))
                                     (n+m))

                                               10
Combinators:


     c1    :: Cont
     c1        = n  n



     c2    :: Expr  Cont  Cont
     c2 y c = n  eval’ y (c3 n c)



     c3    :: Int  Cont  Cont
     c3 n c = m  c (n+m)
                                      11
Datatype:

      data CONT = C1
                 | C2 Expr CONT
                 | C3 Int     CONT


Semantics:

      apply         :: CONT  Cont
      apply C1         = c1
      apply (C2 y c) = c2 y (apply c)
      apply (C3 n c) = c3 n (apply c)
                                        12
Aim: define a function

     eval’’ :: Expr  CONT  Int


such that

     eval’’ e c = eval’ e (apply c)


and hence

     eval e = eval’’ e C1
                                      13
By calculation, we obtain:


    eval’’ (Val n)        c = apply c n
    eval’’ (Add x y) c = eval’’ x (C2 y c)



    apply C1          n      = n
    apply (C2 y c) n         = eval’’ y (C3 n c)
    apply (C3 n c) m         = apply c (n+m)



The semantics is now first-order again.
                                                   14
Step 3 - Refactor

Question:


  What have we actually produced?


Answer:


  An abstract machine, but this only becomes
   clear after we refactor the components.

                                                15
Abstract machine:

    data Cont          = STOP
                       | EVAL Expr Cont
                       | ADD Int Cont

    run e              = eval e STOP

    eval (Val n)   c   = exec c n
    eval (Add x y) c   = eval x (EVAL y c)

    exec STOP       n = n
    exec (EVAL y c) n = eval y (ADD n c)
    exec (ADD n c) m = exec c (n+m)
                                             16
Example:

     run (Add (Val 1) (Val 2))

  = eval (Add (Val 1) (Val 2)) STOP
  = eval (Val 1) (EVAL (Val 2) STOP)
  = exec (EVAL (Val 2) STOP) 1
  = eval (Val 2) (ADD 1 STOP)
  = exec (ADD 1 STOP) 2
  = exec 3 STOP
  = 3
                                       17
Adding Exceptions

Syntax:

   data Expr = ••• | Throw | Catch Expr Expr


Semantics:

   eval              ::   Expr  Maybe Int
   eval   (Val n)     =   Just n
   eval   (Throw)     =   Nothing
   eval   (Add   x y) =   eval x  eval y
   eval   (Catch x y) =   eval x  eval y
                                               18
Step 1 - Add Continuations

   Make evaluation order explicit.


Step 2 - Defunctionalize

   Make first-order once again.


Step 3 - Refactor

   Reveal the abstract machine.
                                     19
Control stack:

  data Cont =    STOP
            |    EVAL Expr Cont
            |    ADD Int Cont
            |    HAND Expr Cont


Evaluating an expression:

  eval                 ::   Expr  Cont  Maybe Int
  eval   (Val n)      c =   exec c n
  eval   (Throw)      c =   unwind c
  eval   (Add    x y) c =   eval x (EVAL y c)
  eval   (Catch x y) c =    eval x (HAND y c)
                                                      20
Executing the control stack:

  exec               ::   Cont    Int  Maybe Int
  exec   STOP       n =   Just   n
  exec   (EVAL y c) n =   eval   y (ADD n c)
  exec   (ADD n c) m =    exec   c (n+m)
  exec   (HAND _ c) n =   exec   c n


Unwinding the control stack:

  unwind             ::   Cont  Maybe Int
  unwind   STOP       =   Nothing
  unwind   (EVAL _ c) =   unwind c
  unwind   (ADD _ c) =    unwind c
  unwind   (HAND y c) =   eval y c
                                                     21
Summary

 Purely calculational development of an abstract
  machine for a language with exceptions;


 Key ideas of marking/unmarking and unwinding
  the stack arise directly from the calculations;


 Techniques have been used to systematically
  design many other machines - Danvy et al.

                                                    22
Further Work

 Exploiting monads and folds;


 Reasoning about efficiency;


 Generalising the language;


 Calculating a compiler.


                                 23

				
DOCUMENT INFO