Docstoc

Interpreters

Document Sample
Interpreters Powered By Docstoc
					        Interpreters

Language of Booleans
          BNF for Booleans
t ::= True | False | if t1 then t2 else t3
v ::= True | False
• t stands for the terms of the language
• v stands for the values of the language
• Values are subsets of terms – we will try to
maintain this subset relationship in all
languages we study.
                   Notes
• The language of Booleans is the “object
language” or the “defined language”. This is
the language we will write an interpreter for.
• The interpreter will be written in another
language; this language is called the
“metalanguage” or the “defining language”.
• For this course the metalanguage will
always be OCaml.
          Representing terms
• We want to represent the terms of
Booleans in OCaml. How to do that?
• The answer to the question is the same as
the answer to: “How to represent different
geometric shapes as values of a type”?
• Hence we must declare a new type, terms, and
tag the different terms with different constructors.
That is: Use “sum-of-product types”.
    Representing terms (contd.)
Recall:
type figure = Circ of int | Rect of int * int | Tri of int * int * int
Recall:
type ’a bintree = Leaf | Node of ’a bintree * ’a * ’a bintree

Similarly:
type term = True | False | Cnd of term * term * term

The Cnd tag is for the if-then-else or “conditional”
term.
        The interpreter: type
• The interpreter, eval, has type
term -> term
• That is, eval takes a term as input and
grinds out a value as output, if the
computation terminates.
• We said: values are subsets of terms. So it
makes sense for eval to have the above
type.
        The interpreter: code
exception NoEvaluationPossible;;
let rec eval = fun
    True -> True
  | False -> False
  | Cnd(t1, t2, t3) -> match (eval t1) with
        True -> eval t2
      | False -> eval t3
      | _     -> raise NoEvaluationPossible
      Notes on interpreter code
• Instead of let rec eval = function …we could
have written: let rec eval t = match t with …
• A term can be thought of as a tree with True and
False labelling its leaves and Cnd labelling its internal
nodes.
• Interpreting a term is like processing a tree: find
results of subtrees and “glue” the results.
• Example: to process Cnd, find result of subtree
t1, and depending on the result, process subtree t2
or t3.
• Note how the meaning of Cnd (in object language) is
defined in terms of match (or if-then-else) in OCaml.
                      Example
let s = if True then False else False;;
let t = if s then True else True;;
let u = if False then True else True;;
Then: eval Cnd(t, False, True) = let b = eval t in …
Note that: eval s = False so that eval t = True
Thus eval Cnd(t, False, True)
= let b = True in
     match b with
        True -> eval False
      | …
This yields the final value of False.
                 One-step evaluation
• eval computes the final value of an input term.
• What if we wanted to observe intermediate results of the
computation?
• For the example on slide 9 we would like:
    if t then False else True
-> if (if False then True else True) then False else True
because in one step:
           t = if s then True else False -> if False then True else True
And this is because in one step:
          s = if True then False else False -> False
If we want to further evaluate if (if False then True else True) then False else True,
we get if True then False else True in one step and then False in a further step.

The notation t1 -> t2 should be read: t1 goes to t2 in one step.
• You can also think of -> as describing transitions in an abstract
machine: A state of the machine is a term of the language. The
machine “goes to” the next state via the transition function, ->.
                          ->
(0) if True then t1 else t2 -> t1

(1) if False then t1 else t2 -> t2

                        t1 -> t1’
(2) -----------------------------------------------------
    if t1 then t2 else t3 -> if t1’ then t2 else t3
                       Explaining ->
• Rule (0) says: if True then t1 else t2 goes to t1 in one evaluation
step.
• Rule (1) says: if False then t1 else t2 goes to t2 in one evaluation
step.
• Rule (2) says: provided t1 goes to t1’ in one evaluation step, then :
if t1 then t2 else t3 goes to if t1’ then t2 else t3 in one evaluation step.
• Recall the inference-rule notation in Rule (2) from the Tegrity
lectures on “A Quick Tour of OCaml”.
• Note how the rules enforce the “evaluation is left-to-right and by
value” principle of evaluation.
• Note that there are no rules of the form: True -> True or
False -> False; this is because the rules describe one-step evaluation.
Values are “atomic”: they evaluate to themselves in zero steps.
  The one-step interpreter code
exception NoEvaluationPossible;;
let rec eval1 = fun
     Cnd(True, t2, t3) -> t2
   | Cnd(False, t2, t3) -> t3
   | Cnd(t1, t2, t3) ->
       let t1’ = eval1 t1 in Cnd(t1’, t2, t3)
   | _ -> raise NoEvaluationPossible;;
            Notes on eval1
• The ordering of the cases in the match
matters.
• The _ is a “wild-card pattern”: it matches
all terms other than the ones described in
the match.
• Because there are no rules for True and
False, the _ raises an exception.