Previous Next Contents

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

Previous Next Contents