Blame camlp4/examples/syb_fold.ml

Packit 1f8b6b
(****************************************************************************)
Packit 1f8b6b
(*                                                                          *)
Packit 1f8b6b
(*                                   OCaml                                  *)
Packit 1f8b6b
(*                                                                          *)
Packit 1f8b6b
(*                            INRIA Rocquencourt                            *)
Packit 1f8b6b
(*                                                                          *)
Packit 1f8b6b
(*  Copyright  2007  Institut  National  de  Recherche en Informatique et   *)
Packit 1f8b6b
(*  en Automatique.  All rights reserved.  This file is distributed under   *)
Packit 1f8b6b
(*  the terms of the GNU Library General Public License, with the special   *)
Packit 1f8b6b
(*  exception on linking described in LICENSE at the top of the Camlp4      *)
Packit 1f8b6b
(*  source tree.                                                            *)
Packit 1f8b6b
(*                                                                          *)
Packit 1f8b6b
(****************************************************************************)
Packit 1f8b6b
Packit 1f8b6b
type variable = string
Packit 1f8b6b
 and term =
Packit 1f8b6b
  | Var   of variable
Packit 1f8b6b
  | Lam   of variable * term
Packit 1f8b6b
  | App   of term * term
Packit 1f8b6b
  | Const of constant
Packit 1f8b6b
 and constant =
Packit 1f8b6b
  | CInt    of int
Packit 1f8b6b
  | CString of string
Packit 1f8b6b
;;
Packit 1f8b6b
Packit 1f8b6b
class fold = Camlp4Filters.GenerateFold.generated;;
Packit 1f8b6b
(* class fold = Camlp4FoldGenerator.generated;; *)
Packit 1f8b6b
Packit 1f8b6b
module VarSet = Set.Make(String);;
Packit 1f8b6b
Packit 1f8b6b
(* Compute free variables with the fold class *)
Packit 1f8b6b
let free_variables_v1 =
Packit 1f8b6b
  let o =
Packit 1f8b6b
    object (self)
Packit 1f8b6b
      inherit fold as super
Packit 1f8b6b
      val fv = VarSet.empty
Packit 1f8b6b
      method fv = fv
Packit 1f8b6b
      method empty_fv = {< fv = VarSet.empty >}
Packit 1f8b6b
      method term t =
Packit 1f8b6b
        match t with
Packit 1f8b6b
        | Var(v) -> {< fv = VarSet.add v fv >}
Packit 1f8b6b
        | Lam(v, t) ->
Packit 1f8b6b
            let fv1 = VarSet.remove v (self#empty_fv#term t)#fv in
Packit 1f8b6b
            {< fv = VarSet.union fv fv1 >}
Packit 1f8b6b
        | _ -> super#term t
Packit 1f8b6b
    end
Packit 1f8b6b
  in fun t -> VarSet.elements (o#term t)#fv
Packit 1f8b6b
;;
Packit 1f8b6b
Packit 1f8b6b
(* Let's try to abstract that a little *)
Packit 1f8b6b
Packit 1f8b6b
let fold_term f t init =
Packit 1f8b6b
  let o =
Packit 1f8b6b
    object (self)
Packit 1f8b6b
      inherit fold as super
Packit 1f8b6b
      val acc = init
Packit 1f8b6b
      method get = acc
Packit 1f8b6b
      method reset = {< acc = init >}
Packit 1f8b6b
      method term t =
Packit 1f8b6b
        {< acc = f t acc (fun t -> (self#reset#term t)#get)
Packit 1f8b6b
                         (fun t -> (super#term t)#get) >}
Packit 1f8b6b
    end
Packit 1f8b6b
  in
Packit 1f8b6b
  (o#term t)#get
Packit 1f8b6b
;;
Packit 1f8b6b
Packit 1f8b6b
(* A nicer version of free_variables *)
Packit 1f8b6b
let free_variables_v2 t =
Packit 1f8b6b
  VarSet.elements begin
Packit 1f8b6b
    fold_term begin fun t fv self next ->
Packit 1f8b6b
      match t with
Packit 1f8b6b
      | Var(v)    -> VarSet.add v fv
Packit 1f8b6b
      | Lam(v, t) -> VarSet.union fv (VarSet.remove v (self t))
Packit 1f8b6b
      | _         -> next t
Packit 1f8b6b
    end t VarSet.empty
Packit 1f8b6b
  end
Packit 1f8b6b
;;
Packit 1f8b6b
Packit 1f8b6b
let term1 =
Packit 1f8b6b
  App(
Packit 1f8b6b
    App(Var"x1",
Packit 1f8b6b
      Lam("x",
Packit 1f8b6b
        App(Var"x", App(Var"y", (Lam("y", Lam("z", (App(Var"y", App(Var"x4",Var"z")))))))))),
Packit 1f8b6b
    Var"x3")
Packit 1f8b6b
Packit 1f8b6b
;;
Packit 1f8b6b
Packit 1f8b6b
let fv1 = free_variables_v1 term1;;
Packit 1f8b6b
let fv2 = free_variables_v2 term1;;
Packit 1f8b6b
Packit 1f8b6b
(* Low cost syntax *)
Packit 1f8b6b
let ( ^-> ) v t = Lam(v, t)
Packit 1f8b6b
let ( @ ) t1 t2 = App(t1, t2)
Packit 1f8b6b
let ( ! ) s = Var s
Packit 1f8b6b
Packit 1f8b6b
let term2 =
Packit 1f8b6b
  !"x1" @
Packit 1f8b6b
  ("x" ^-> !"x" @ !"y" @ ("y" ^-> ("z" ^-> !"y" @ !"x4" @ !"z"))) @
Packit 1f8b6b
  !"x3"
Packit 1f8b6b
Packit 1f8b6b
;;
Packit 1f8b6b
Packit 1f8b6b
let fv1' = free_variables_v1 term2;;
Packit 1f8b6b
let fv2' = free_variables_v2 term2;;