2.5 Some examples
2.5.1 Defining constants
This is a way to represent constants by some name. The quotation
expander is just a string matching. Here is the file
``foo.ml
'':
let exp _ =
function
"keyPressEvent" -> "2"
| "exposeEvent" -> "12"
| "configureNotifyEvent" -> "22"
;;
Quotation.add "const" (Quotation.ExStr exp);;
Quotation.default := "const";;
The compilation command is:
ocamlc -c -I `camlp4 -where` foo.ml
Now, the following piece of program, in some file ``bar.ml
''
match event.typ with
<<configureNotifyEvent>> -> ...
| <<exposeEvent>> -> ...
| <<keyPressEvent>> -> ...
will be interpreted like:
match event.typ with
22 -> ...
| 12 -> ...
| 2 -> ...
It can be compiled using the command:
ocamlc -pp "camlp4o ./foo.cmo" bar.ml
or pretty printed:
camlp4o pr_o.cmo ./foo.cmo bar.ml
2.5.2 Lambda Calculus
This is another example, more complicated, for treating ``lambda
calculus terms''. A type ``term'' is defined as:
type term =
Abs of term
| Ref of int
| App of term * term
;;
but instead of manipulating terms, like:
Abs (Ref 0)
Abs (Abs (Ref 1))
App (Abs (App (Ref 0, Ref 0)), Abs (App (Ref 0, Ref 0)))
Abs (App (Abs (Ref 0), Abs (App (Ref 1, Ref 0))))
we want to represent them by a concrete syntax in quotations:
<< [x]x >>
<< [x,y]x >>
<< ([x](x x) [x](x x)) >>
<< [x]([y]y [z](x z)) >>
The details of the complete syntax of lambda terms is not described
here. What is important is that the users of lambda terms prefer to
write in their programs this concrete syntax instead of a combination
of values of type term, harder to understand.
Here, we choose to implement the quotation expander using a Camlp4
grammar (see chapter 3). Just have a fast look of this
code for the moment and return here when you have read the chapter on
grammars:
type lambda =
Lam of string * lambda
| App of lambda * lambda
| Var of string
| Antiquot of string
;;
let gram = Grammar.create (Plexer.make ());;
let lambda_eoi = Grammar.Entry.create gram "lambda";;
let lambda = Grammar.Entry.create gram "lambda";;
EXTEND
lambda_eoi: [[ x = lambda; EOI -> x ]];
lambda: [[ "["; x = LIDENT; "]"; t = lambda -> Lam (x, t)
| "("; t1 = lambda; t2 = lambda; ")" -> App (t1, t2)
| x = LIDENT -> Var x
| "^"; x = LIDENT -> Antiquot x
| "["; x = LIDENT; ","; l = LIST1 LIDENT SEP ","; "]";
t = lambda
-> List.fold_right (fun x t -> Lam (x, t)) (x::l) t ]];
END;;
let rec index x =
function
[] -> raise Not_found
| y::l -> if x = y then 0 else succ (index x l)
;;
let rec convert env =
function
Lam x t ->
"Abs (" ^ convert (x::env) t ^ ")"
| App t1 t2 ->
"App (" ^ convert env t1 ^ ", " ^ convert env t2 ^ ")"
| Var x ->
let i =
try index x env with
Not_found -> failwith ("unbound variable " ^ x)
in
"Ref " ^ string_of_int i
| Antiquot x -> x
;;
let lam_exp _ str =
let cs = Stream.of_string str in
let t = Grammar.Entry.parse lambda_eoi cs in
convert [] t
;;
Quotation.add "term" (Quotation.ExStr lam_exp);;
Quotation.default := "term";;
This source code, holding an Objective Caml syntax extension (keyword
``EXTEND
'') for grammars, must be preprocessed by Camlp4:
ocamlc -pp "camlp4o pa_extend.cmo" -c -I `camlp4 -where` foo.ml
and files holding term quotations can be compiled using the command:
ocamlc -pp "camlp4o ./foo.cmo" -c -I `camlp4 -where` bar.ml