Blame camlp4/Camlp4/Struct/FreeVars.ml

Packit 1f8b6b
(* camlp4r *)
Packit 1f8b6b
(****************************************************************************)
Packit 1f8b6b
(*                                                                          *)
Packit 1f8b6b
(*                                   OCaml                                  *)
Packit 1f8b6b
(*                                                                          *)
Packit 1f8b6b
(*                            INRIA Rocquencourt                            *)
Packit 1f8b6b
(*                                                                          *)
Packit 1f8b6b
(*  Copyright   2006    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
(* Authors:
Packit 1f8b6b
 * - Nicolas Pouillard: initial version
Packit 1f8b6b
 *)
Packit 1f8b6b
Packit 1f8b6b
module Make (Ast : Sig.Camlp4Ast) = struct
Packit 1f8b6b
Packit 1f8b6b
  module S = Set.Make String;
Packit 1f8b6b
Packit 1f8b6b
  class c_fold_pattern_vars ['accu] f init =
Packit 1f8b6b
    object
Packit 1f8b6b
      inherit Ast.fold as super;
Packit 1f8b6b
      value acc = init;
Packit 1f8b6b
      method acc : 'accu = acc;
Packit 1f8b6b
      method patt =
Packit 1f8b6b
        fun
Packit 1f8b6b
        [ <:patt< $lid:s$ >> | <:patt< ~ $s$ >> | <:patt< ? $s$ >> ->
Packit 1f8b6b
              {< acc = f s acc >}
Packit 1f8b6b
        | p -> super#patt p ];
Packit 1f8b6b
    end;
Packit 1f8b6b
Packit 1f8b6b
  value fold_pattern_vars f p init = ((new c_fold_pattern_vars f init)#patt p)#acc;
Packit 1f8b6b
Packit 1f8b6b
  value rec fold_binding_vars f bi acc =
Packit 1f8b6b
    match bi with
Packit 1f8b6b
    [ <:binding< $bi1$ and $bi2$ >> ->
Packit 1f8b6b
        fold_binding_vars f bi1 (fold_binding_vars f bi2 acc)
Packit 1f8b6b
    | <:binding< $p$ = $_$ >> -> fold_pattern_vars f p acc
Packit 1f8b6b
    | <:binding<>> -> acc
Packit 1f8b6b
    | <:binding< $anti:_$ >> -> assert False ];
Packit 1f8b6b
Packit 1f8b6b
  class fold_free_vars ['accu] (f : string -> 'accu -> 'accu) ?(env_init = S.empty) free_init =
Packit 1f8b6b
    object (o)
Packit 1f8b6b
      inherit Ast.fold as super;
Packit 1f8b6b
      value free : 'accu = free_init;
Packit 1f8b6b
      value env : S.t = env_init;
Packit 1f8b6b
Packit 1f8b6b
      method free = free;
Packit 1f8b6b
      method set_env env = {< env = env >};
Packit 1f8b6b
      method add_atom s = {< env = S.add s env >};
Packit 1f8b6b
      method add_patt p = {< env = fold_pattern_vars S.add p env >};
Packit 1f8b6b
      method add_binding bi = {< env = fold_binding_vars S.add bi env >};
Packit 1f8b6b
Packit 1f8b6b
      method expr =
Packit 1f8b6b
        fun
Packit 1f8b6b
        [ <:expr< $lid:s$ >> | <:expr< ~ $s$ >> | <:expr< ? $s$ >> ->
Packit 1f8b6b
            if S.mem s env then o else {< free = f s free >}
Packit 1f8b6b
Packit 1f8b6b
        | <:expr< let $bi$ in $e$ >> ->
Packit 1f8b6b
            (((o#add_binding bi)#expr e)#set_env env)#binding bi
Packit 1f8b6b
Packit 1f8b6b
        | <:expr< let rec $bi$ in $e$ >> ->
Packit 1f8b6b
            (((o#add_binding bi)#expr e)#binding bi)#set_env env
Packit 1f8b6b
Packit 1f8b6b
        | <:expr< for $p$ = $e1$ $to:_$ $e2$ do { $e3$ } >> ->
Packit 1f8b6b
            ((((o#expr e1)#expr e2)#patt p)#expr e3)#set_env env
Packit 1f8b6b
Packit 1f8b6b
        | <:expr< $id:_$ >> | <:expr< new $_$ >> -> o
Packit 1f8b6b
Packit 1f8b6b
        | <:expr< object ($p$) $cst$ end >> ->
Packit 1f8b6b
            ((o#add_patt p)#class_str_item cst)#set_env env
Packit 1f8b6b
Packit 1f8b6b
        | e -> super#expr e ];
Packit 1f8b6b
Packit 1f8b6b
      method match_case =
Packit 1f8b6b
        fun
Packit 1f8b6b
        [ <:match_case< $p$ when $e1$ -> $e2$ >> ->
Packit 1f8b6b
            (((o#add_patt p)#expr e1)#expr e2)#set_env env
Packit 1f8b6b
        | m -> super#match_case m ];
Packit 1f8b6b
Packit 1f8b6b
      method str_item =
Packit 1f8b6b
        fun
Packit 1f8b6b
        [ <:str_item< external $s$ : $t$ = $_$ >> ->
Packit 1f8b6b
            (o#ctyp t)#add_atom s
Packit 1f8b6b
        | <:str_item< value $bi$ >> ->
Packit 1f8b6b
            (o#binding bi)#add_binding bi
Packit 1f8b6b
        | <:str_item< value rec $bi$ >> ->
Packit 1f8b6b
            (o#add_binding bi)#binding bi
Packit 1f8b6b
        | st -> super#str_item st ];
Packit 1f8b6b
Packit 1f8b6b
      method class_expr =
Packit 1f8b6b
        fun
Packit 1f8b6b
        [ <:class_expr< fun $p$ -> $ce$ >> ->
Packit 1f8b6b
            ((o#add_patt p)#class_expr ce)#set_env env
Packit 1f8b6b
        | <:class_expr< let $bi$ in $ce$ >> ->
Packit 1f8b6b
            (((o#binding bi)#add_binding bi)#class_expr ce)#set_env env
Packit 1f8b6b
        | <:class_expr< let rec $bi$ in $ce$ >> ->
Packit 1f8b6b
            (((o#add_binding bi)#binding bi)#class_expr ce)#set_env env
Packit 1f8b6b
        | <:class_expr< object ($p$) $cst$ end >> ->
Packit 1f8b6b
            ((o#add_patt p)#class_str_item cst)#set_env env
Packit 1f8b6b
        | ce -> super#class_expr ce ];
Packit 1f8b6b
Packit 1f8b6b
      method class_str_item =
Packit 1f8b6b
        fun
Packit 1f8b6b
        [ <:class_str_item< inherit $override:_$ $_$ >> as cst -> super#class_str_item cst
Packit 1f8b6b
        | <:class_str_item< inherit $override:_$ $ce$ as $s$ >> ->
Packit 1f8b6b
            (o#class_expr ce)#add_atom s
Packit 1f8b6b
        | <:class_str_item< value $override:_$ $mutable:_$ $s$ = $e$ >> ->
Packit 1f8b6b
            (o#expr e)#add_atom s
Packit 1f8b6b
        | <:class_str_item< value virtual $mutable:_$ $s$ : $t$ >> ->
Packit 1f8b6b
            (o#ctyp t)#add_atom s
Packit 1f8b6b
        | cst -> super#class_str_item cst ];
Packit 1f8b6b
Packit 1f8b6b
      method module_expr = fun
Packit 1f8b6b
      [ <:module_expr< struct $st$ end >> ->
Packit 1f8b6b
          (o#str_item st)#set_env env
Packit 1f8b6b
      | me -> super#module_expr me ];
Packit 1f8b6b
Packit 1f8b6b
    end;
Packit 1f8b6b
Packit 1f8b6b
  value free_vars env_init e =
Packit 1f8b6b
    let fold = new fold_free_vars S.add ~env_init S.empty in (fold#expr e)#free;
Packit 1f8b6b
end;