VIEWS: 9 PAGES: 14 POSTED ON: 7/14/2011 Public Domain
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.