(* F# examples seen in class *) (* From Chap 1 of the Sestoft *) (* Every programming language has a - a _concrete syntax, i.e., a textual representation for its programs – an _abstract syntax_, a tree-like representation for its programs *) (* Representing abstract syntax using recursive datatypes *) type expr = | CstI of int | Prim of string * expr * expr // Values of type can be used as abstract syntax version // of the usual arithmetic expressions over the integers let e1 = CstI 17 (* Represents constant expression: 17 *) let e2 = Prim("-", CstI 3, CstI 4) (* - / \ 3 4 Structured representation of the expression: 3 - 4 The value of e2 is an _abstract syntax tree_ of (3 - 4) *) let e3 = Prim("+", Prim("*", CstI 2, CstI 9), CstI 10) (* + / \ * 10 / \ 2 9 Abstract syntax tree of: (2 * 9) + 10 *) let e4 = Prim("*", CstI 2, Prim("+", CstI 9, CstI 10)) (* * / \ 2 + / \ 9 10 Abstract syntax tree of: 2 * (9 + 10) *) let e5 = Prim("+", Prim("*", CstI 7, CstI 9), Prim("/", CstI 2, CstI 10)) (* + / \ / \ * * / \ / \ 7 9 2 10 Abstract syntax tree of: 3*9 + 2*10 *) (* Evaluating expressions using recursive functions *) let rec eval (e : expr) : int = match e with | CstI i -> i | Prim("+", e1, e2) -> eval e1 + eval e2 | Prim("*", e1, e2) -> eval e1 * eval e2 | Prim("-", e1, e2) -> eval e1 - eval e2 | Prim _ -> failwith "unknown primitive" // The eval function is an interpreter for _programs_ in the expr language // The meaning of the operators is defined by eval (in terms of F# operators) // 17 let v1 = eval e1 // 3 - 4 let v2 = eval e2 // (2 * 9) + 10 let v3 = eval e3 // 2 * (9 + 10) let v4 = eval e4 (* Changing the meaning of subtraction *) let rec eval2 (e : expr) : int = match e with | CstI i -> i | Prim("+", e1, e2) -> eval2 e1 + eval2 e2 | Prim("*", e1, e2) -> eval2 e1 * eval2 e2 | Prim("-", e1, e2) -> let res = eval2 e1 - eval2 e2 in if res < 0 then 0 else res | Prim _ -> failwith "unknown primitive" // eval2 interprets - as cut-off subtraction, whose result is never negative // This yieds a _new_ language even if the abstract syntax is the same let e4v = eval2 (Prim("-", CstI 10, CstI 27))