summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlain Frisch <alain@frisch.fr>2012-11-08 17:21:27 +0000
committerAlain Frisch <alain@frisch.fr>2012-11-08 17:21:27 +0000
commit5668b313524ffa61602807206d068a02976ae69b (patch)
treef1dd0330ffd783949921ddd4b6efc2017cf4e25d
parent0a96bac530313c6a09c5788b9037284551996084 (diff)
New implementation of cmt2annot, based on an OO iterator for typed trees. Mostly work for Partial_implementation (#5816).
git-svn-id: http://caml.inria.fr/svn/ocaml/trunk@13085 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02
-rw-r--r--tools/.depend64
-rw-r--r--tools/Makefile.shared3
-rw-r--r--tools/cmt2annot.ml298
-rw-r--r--tools/tast_iter.ml376
-rw-r--r--tools/tast_iter.mli80
5 files changed, 579 insertions, 242 deletions
diff --git a/tools/.depend b/tools/.depend
index ad310b457..8d07e60cf 100644
--- a/tools/.depend
+++ b/tools/.depend
@@ -1,24 +1,28 @@
depend.cmi : ../parsing/parsetree.cmi
profiling.cmi :
-typedtreeIter.cmi : ../typing/typedtree.cmi ../parsing/asttypes.cmi
+tast_iter.cmi : ../typing/typedtree.cmi ../parsing/asttypes.cmi
untypeast.cmi : ../typing/typedtree.cmi ../typing/path.cmi \
../parsing/parsetree.cmi ../parsing/longident.cmi
addlabels.cmo : ../parsing/parsetree.cmi ../parsing/parse.cmi \
../parsing/longident.cmi ../parsing/location.cmi ../parsing/asttypes.cmi
addlabels.cmx : ../parsing/parsetree.cmi ../parsing/parse.cmx \
../parsing/longident.cmx ../parsing/location.cmx ../parsing/asttypes.cmi
-cmt2annot.cmo : typedtreeIter.cmi ../typing/typedtree.cmi \
- ../typing/stypes.cmi ../typing/path.cmi ../typing/oprint.cmi \
- ../parsing/location.cmi ../typing/ident.cmi ../typing/env.cmi \
+ast_mapper.cmo : ../parsing/parsetree.cmi ../parsing/longident.cmi \
+ ../parsing/location.cmi ../utils/config.cmi ../parsing/asttypes.cmi
+ast_mapper.cmx : ../parsing/parsetree.cmi ../parsing/longident.cmx \
+ ../parsing/location.cmx ../utils/config.cmx ../parsing/asttypes.cmi
+cmt2annot.cmo : untypeast.cmi ../typing/types.cmi \
+ ../typing/typedtreeIter.cmi ../typing/typedtree.cmi tast_iter.cmi \
+ ../typing/stypes.cmi ../parsing/pprintast.cmi ../typing/path.cmi \
+ ../typing/oprint.cmi ../parsing/location.cmi ../typing/ident.cmi \
+ ../typing/envaux.cmi ../typing/env.cmi ../utils/config.cmi \
../typing/cmt_format.cmi ../parsing/asttypes.cmi ../typing/annot.cmi
-cmt2annot.cmx : typedtreeIter.cmx ../typing/typedtree.cmx \
- ../typing/stypes.cmx ../typing/path.cmx ../typing/oprint.cmx \
- ../parsing/location.cmx ../typing/ident.cmx ../typing/env.cmx \
+cmt2annot.cmx : untypeast.cmx ../typing/types.cmx \
+ ../typing/typedtreeIter.cmx ../typing/typedtree.cmx tast_iter.cmx \
+ ../typing/stypes.cmx ../parsing/pprintast.cmx ../typing/path.cmx \
+ ../typing/oprint.cmx ../parsing/location.cmx ../typing/ident.cmx \
+ ../typing/envaux.cmx ../typing/env.cmx ../utils/config.cmx \
../typing/cmt_format.cmx ../parsing/asttypes.cmi ../typing/annot.cmi
-cmt2ml.cmo : untypeast.cmi ../typing/typedtree.cmi pprintast.cmo \
- ../typing/cmt_format.cmi
-cmt2ml.cmx : untypeast.cmx ../typing/typedtree.cmx pprintast.cmx \
- ../typing/cmt_format.cmx
cvt_emit.cmo :
cvt_emit.cmx :
depend.cmo : ../parsing/parsetree.cmi ../utils/misc.cmi \
@@ -37,26 +41,32 @@ dumpobj.cmx : ../utils/tbl.cmx opnames.cmx ../bytecomp/opcodes.cmx \
../bytecomp/instruct.cmx ../typing/ident.cmx ../bytecomp/emitcode.cmx \
../utils/config.cmx ../bytecomp/cmo_format.cmi \
../bytecomp/bytesections.cmx ../parsing/asttypes.cmi
+eqparsetree.cmo : ../parsing/parsetree.cmi ../parsing/longident.cmi \
+ ../parsing/location.cmi ../parsing/asttypes.cmi
+eqparsetree.cmx : ../parsing/parsetree.cmi ../parsing/longident.cmx \
+ ../parsing/location.cmx ../parsing/asttypes.cmi
myocamlbuild_config.cmo :
myocamlbuild_config.cmx :
objinfo.cmo : ../utils/misc.cmi ../utils/config.cmi \
../asmcomp/cmx_format.cmi ../bytecomp/cmo_format.cmi \
- ../asmcomp/clambda.cmi ../bytecomp/bytesections.cmi
+ ../typing/cmi_format.cmi ../asmcomp/clambda.cmi \
+ ../bytecomp/bytesections.cmi
objinfo.cmx : ../utils/misc.cmx ../utils/config.cmx \
../asmcomp/cmx_format.cmi ../bytecomp/cmo_format.cmi \
- ../asmcomp/clambda.cmx ../bytecomp/bytesections.cmx
+ ../typing/cmi_format.cmx ../asmcomp/clambda.cmx \
+ ../bytecomp/bytesections.cmx
ocaml299to3.cmo :
ocaml299to3.cmx :
ocamlcp.cmo : ../driver/main_args.cmi
ocamlcp.cmx : ../driver/main_args.cmx
-ocamldep.cmo : ../parsing/syntaxerr.cmi ../parsing/parsetree.cmi \
- ../parsing/parse.cmi ../utils/misc.cmi ../parsing/longident.cmi \
- ../parsing/location.cmi ../parsing/lexer.cmi depend.cmi \
- ../utils/config.cmi ../utils/clflags.cmi
-ocamldep.cmx : ../parsing/syntaxerr.cmx ../parsing/parsetree.cmi \
- ../parsing/parse.cmx ../utils/misc.cmx ../parsing/longident.cmx \
- ../parsing/location.cmx ../parsing/lexer.cmx depend.cmx \
- ../utils/config.cmx ../utils/clflags.cmx
+ocamldep.cmo : ../parsing/syntaxerr.cmi ../driver/pparse.cmi \
+ ../parsing/parsetree.cmi ../parsing/parse.cmi ../utils/misc.cmi \
+ ../parsing/longident.cmi ../parsing/location.cmi ../parsing/lexer.cmi \
+ depend.cmi ../utils/config.cmi ../utils/clflags.cmi
+ocamldep.cmx : ../parsing/syntaxerr.cmx ../driver/pparse.cmx \
+ ../parsing/parsetree.cmi ../parsing/parse.cmx ../utils/misc.cmx \
+ ../parsing/longident.cmx ../parsing/location.cmx ../parsing/lexer.cmx \
+ depend.cmx ../utils/config.cmx ../utils/clflags.cmx
ocamlmklib.cmo : myocamlbuild_config.cmo
ocamlmklib.cmx : myocamlbuild_config.cmx
ocamlmktop.cmo : ../utils/ccomp.cmi
@@ -73,10 +83,6 @@ ocamlprof.cmx : ../utils/warnings.cmx ../parsing/syntaxerr.cmx \
../utils/clflags.cmx
opnames.cmo :
opnames.cmx :
-pprintast.cmo : ../parsing/parsetree.cmi ../parsing/longident.cmi \
- ../parsing/location.cmi ../parsing/asttypes.cmi
-pprintast.cmx : ../parsing/parsetree.cmi ../parsing/longident.cmx \
- ../parsing/location.cmx ../parsing/asttypes.cmi
primreq.cmo : ../utils/config.cmi ../bytecomp/cmo_format.cmi
primreq.cmx : ../utils/config.cmx ../bytecomp/cmo_format.cmi
profiling.cmo : profiling.cmi
@@ -85,10 +91,10 @@ read_cmt.cmo : ../typing/cmt_format.cmi cmt2annot.cmo ../utils/clflags.cmi
read_cmt.cmx : ../typing/cmt_format.cmx cmt2annot.cmx ../utils/clflags.cmx
scrapelabels.cmo :
scrapelabels.cmx :
-typedtreeIter.cmo : ../typing/typedtree.cmi ../utils/misc.cmi \
- ../parsing/asttypes.cmi typedtreeIter.cmi
-typedtreeIter.cmx : ../typing/typedtree.cmx ../utils/misc.cmx \
- ../parsing/asttypes.cmi typedtreeIter.cmi
+tast_iter.cmo : ../typing/typedtree.cmi ../parsing/asttypes.cmi \
+ tast_iter.cmi
+tast_iter.cmx : ../typing/typedtree.cmx ../parsing/asttypes.cmi \
+ tast_iter.cmi
untypeast.cmo : ../typing/typedtree.cmi ../typing/path.cmi \
../parsing/parsetree.cmi ../utils/misc.cmi ../parsing/longident.cmi \
../typing/ident.cmi ../parsing/asttypes.cmi untypeast.cmi
diff --git a/tools/Makefile.shared b/tools/Makefile.shared
index f55734147..503960593 100644
--- a/tools/Makefile.shared
+++ b/tools/Makefile.shared
@@ -24,7 +24,7 @@ LINKFLAGS=$(INCLUDES)
all: ocamldep ocamlprof ocamlcp ocamloptp ocamlmktop ocamlmklib dumpobj \
objinfo read_cmt
-all: ast_mapper.cmo
+all: ast_mapper.cmo tast_iter.cmo
# scrapelabels addlabels
@@ -233,6 +233,7 @@ READ_CMT= \
../typing/stypes.cmo \
\
untypeast.cmo \
+ tast_iter.cmo \
cmt2annot.cmo read_cmt.cmo
read_cmt: $(READ_CMT)
diff --git a/tools/cmt2annot.ml b/tools/cmt2annot.ml
index 31a5468f6..9632e48b5 100644
--- a/tools/cmt2annot.ml
+++ b/tools/cmt2annot.ml
@@ -12,112 +12,48 @@
(* Generate an .annot file from a .cmt file. *)
+open Asttypes
open Typedtree
-open TypedtreeIter
-let pattern_scopes = ref []
+let bind_variables scope =
+ object
+ inherit Tast_iter.iter as super
-let push_None () =
- pattern_scopes := None :: !pattern_scopes
-let push_Some annot =
- pattern_scopes := (Some annot) :: !pattern_scopes
-let pop_scope () =
- match !pattern_scopes with
- [] -> assert false
- | _ :: scopes -> pattern_scopes := scopes
-
-let rebuild_env = ref false
-
-module ForIterator = struct
- open Asttypes
-
- include DefaultIteratorArgument
-
- let structure_begin_scopes = ref []
- let structure_end_scopes = ref []
+ method! pattern pat =
+ super # pattern pat;
+ match pat.pat_desc with
+ | Tpat_var (id, _) | Tpat_alias (_, id, _) ->
+ Stypes.record (Stypes.An_ident (pat.pat_loc, Ident.name id, Annot.Idef scope))
+ | _ -> ()
+ end
- let rec find_last list =
- match list with
- [] -> assert false
- | [x] -> x
- | _ :: tail -> find_last tail
+let bind_bindings scope bindings =
+ let o = bind_variables scope in
+ List.iter (fun (p, _) -> o # pattern p) bindings
- let enter_structure str =
- match str.str_items with
- [] -> ()
- | _ ->
- let loc =
- match !structure_end_scopes with
- [] -> Location.none
- | _ ->
- let s = find_last str.str_items in
- s.str_loc
- in
- structure_end_scopes := loc :: !structure_end_scopes;
+let bind_cases l =
+ List.iter (fun (p, e) -> (bind_variables e.exp_loc) # pattern p) l
- let rec iter list =
- match list with
- [] -> assert false
- | [ { str_desc = Tstr_value (Nonrecursive, _); str_loc = loc } ] ->
- structure_begin_scopes := loc.Location.loc_end
- :: !structure_begin_scopes
- | [ _ ] -> ()
- | item :: tail ->
- iter tail;
- match item, tail with
- { str_desc = Tstr_value (Nonrecursive,_) },
- { str_loc = loc } :: _ ->
- structure_begin_scopes := loc.Location.loc_start
- :: !structure_begin_scopes
- | _ -> ()
- in
- iter str.str_items
+let iterator rebuild_env =
+ object(this)
+ val scope = Location.none (* scope of the surrounding structure *)
- let leave_structure str =
- match str.str_items with
- [] -> ()
- | _ ->
- match !structure_end_scopes with
- [] -> assert false
- | _ :: scopes -> structure_end_scopes := scopes
+ inherit Tast_iter.iter as super
- let enter_class_expr node =
- Stypes.record (Stypes.Ti_class node)
- let enter_module_expr node =
- Stypes.record (Stypes.Ti_mod node)
+ method! class_expr node =
+ Stypes.record (Stypes.Ti_class node);
+ super # class_expr node
- let add_variable pat id =
- match !pattern_scopes with
- | [] -> assert false
- | None :: _ -> ()
- | (Some s) :: _ ->
- Stypes.record (Stypes.An_ident (pat.pat_loc, Ident.name id, s))
+ method! module_expr node =
+ Stypes.record (Stypes.Ti_mod node);
+ Tast_iter.module_expr {< scope = node.mod_loc >} node
- let enter_pattern pat =
- match pat.pat_desc with
- | Tpat_var (id, _)
- | Tpat_alias (_, id,_)
- -> add_variable pat id
- | Tpat_any -> ()
- | Tpat_constant _
- | Tpat_tuple _
- | Tpat_construct _
- | Tpat_lazy _
- | Tpat_or _
- | Tpat_array _
- | Tpat_record _
- | Tpat_variant _
- -> ()
-
- let leave_pattern pat =
- Stypes.record (Stypes.Ti_pat pat)
-
- let enter_expression exp =
- match exp.exp_desc with
- Texp_ident (path, _, _) ->
+ method! expression exp =
+ begin match exp.exp_desc with
+ | Texp_ident (path, _, _) ->
let full_name = Path.name ~paren:Oprint.parenthesized_ident path in
let env =
- if !rebuild_env then
+ if rebuild_env then
try
Env.env_of_only_summary Envaux.env_from_summary exp.exp_env
with Envaux.Error err ->
@@ -137,152 +73,90 @@ module ForIterator = struct
in
Stypes.record
(Stypes.An_ident (exp.exp_loc, full_name , annot))
-
- | Texp_let (rec_flag, _, body) ->
- begin
- match rec_flag with
- | Recursive -> push_Some (Annot.Idef exp.exp_loc)
- | Nonrecursive -> push_Some (Annot.Idef body.exp_loc)
- | Default -> push_None ()
- end
- | Texp_function _ -> push_None ()
- | Texp_match _ -> push_None ()
- | Texp_try _ -> push_None ()
- | _ -> ()
-
- let leave_expression exp =
- if not exp.exp_loc.Location.loc_ghost then
- Stypes.record (Stypes.Ti_expr exp);
- match exp.exp_desc with
- | Texp_let _
- | Texp_function _
- | Texp_match _
- | Texp_try _
- -> pop_scope ()
+ | Texp_let (Recursive, bindings, _) ->
+ bind_bindings exp.exp_loc bindings
+ | Texp_let (Nonrecursive, bindings, body) ->
+ bind_bindings body.exp_loc bindings
+ | Texp_function (_, f, _)
+ | Texp_match (_, f, _)
+ | Texp_try (_, f) ->
+ bind_cases f
| _ -> ()
+ end;
+ Stypes.record (Stypes.Ti_expr exp);
+ super # expression exp
- let enter_binding pat exp =
- let scope =
- match !pattern_scopes with
- | [] -> assert false
- | None :: _ -> Some (Annot.Idef exp.exp_loc)
- | scope :: _ -> scope
- in
- pattern_scopes := scope :: !pattern_scopes
-
- let leave_binding _ _ =
- pop_scope ()
-
- let enter_class_expr exp =
- match exp.cl_desc with
- | Tcl_fun _ -> push_None ()
- | Tcl_let _ -> push_None ()
- | _ -> ()
-
- let leave_class_expr exp =
- match exp.cl_desc with
- | Tcl_fun _
- | Tcl_let _ -> pop_scope ()
- | _ -> ()
-
- let enter_class_structure _ =
- push_None ()
-
- let leave_class_structure _ =
- pop_scope ()
-
-(*
- let enter_class_field cf =
- match cf.cf_desc with
- Tcf_let _ -> push_None ()
- | _ -> ()
-
- let leave_class_field cf =
- match cf.cf_desc with
- Tcf_let _ -> pop_scope ()
- | _ -> ()
-*)
+ method! pattern pat =
+ super # pattern pat;
+ Stypes.record (Stypes.Ti_pat pat)
- let enter_structure_item s =
- Stypes.record_phrase s.str_loc;
- match s.str_desc with
- Tstr_value (rec_flag, _) ->
- begin
- let loc = s.str_loc in
- let scope = match !structure_end_scopes with
- [] -> assert false
- | scope :: _ -> scope
- in
- match rec_flag with
- | Recursive -> push_Some
- (Annot.Idef { scope with
- Location.loc_start = loc.Location.loc_start})
- | Nonrecursive ->
-(* TODO: do it lazily, when we start the next element ! *)
-(*
- let start = match srem with
- | [] -> loc.Location.loc_end
- | {pstr_loc = loc2} :: _ -> loc2.Location.loc_start
-in *)
- let start =
- match !structure_begin_scopes with
- [] -> assert false
- | loc :: tail ->
- structure_begin_scopes := tail;
- loc
- in
- push_Some (Annot.Idef {scope with Location.loc_start = start})
- | Default -> push_None ()
+ method private structure_item_rem s rem =
+ begin match s with
+ | {str_desc = Tstr_value (rec_flag, bindings); str_loc = loc} ->
+ let open Location in
+ let doit loc_start = bind_bindings {scope with loc_start} bindings in
+ begin match rec_flag, rem with
+ | Default, _ -> ()
+ | Recursive, _ -> doit loc.loc_start
+ | Nonrecursive, [] -> doit loc.loc_end
+ | Nonrecursive, {str_loc = loc2} :: _ -> doit loc2.loc_start
end
- | _ -> ()
-
- let leave_structure_item s =
- match s.str_desc with
- Tstr_value _ -> pop_scope ()
- | _ -> ()
-
+ | _ ->
+ ()
+ end;
+ Stypes.record_phrase s.str_loc;
+ super # structure_item s
+
+ method! structure_item s =
+ (* This will be used for Partial_structure_item.
+ We don't have here the location of the "next" item,
+ this will give a slightly different scope for the non-recursive
+ binding case. *)
+ this # structure_item_rem s []
+
+ method! structure l =
+ let rec loop = function
+ | str :: rem -> this # structure_item_rem str rem; loop rem
+ | [] -> ()
+ in
+ loop l.str_items
+(* TODO: support binding for Tcl_fun, Tcl_let, etc *)
end
-module Iterator = MakeIterator(ForIterator)
-
-let binary_part x =
- let open Iterator in
+let binary_part iter x =
let open Cmt_format in
match x with
- | Partial_structure x -> iter_structure x
- | Partial_structure_item x -> iter_structure_item x
- | Partial_expression x -> iter_expression x
- | Partial_pattern x -> iter_pattern x
- | Partial_class_expr x -> iter_class_expr x
- | Partial_signature x -> iter_signature x
- | Partial_signature_item x -> iter_signature_item x
- | Partial_module_type x -> iter_module_type x
+ | Partial_structure x -> iter # structure x
+ | Partial_structure_item x -> iter # structure_item x
+ | Partial_expression x -> iter # expression x
+ | Partial_pattern x -> iter # pattern x
+ | Partial_class_expr x -> iter # class_expr x
+ | Partial_signature x -> iter # signature x
+ | Partial_signature_item x -> iter # signature_item x
+ | Partial_module_type x -> iter # module_type x
let gen_annot target_filename filename {Cmt_format.cmt_loadpath; cmt_annots; cmt_use_summaries; _} =
let open Cmt_format in
Envaux.reset_cache ();
Config.load_path := cmt_loadpath;
- rebuild_env := cmt_use_summaries;
let target_filename =
match target_filename with
| None -> Some (filename ^ ".annot")
| Some "-" -> None
| Some filename -> target_filename
in
+ let iterator = iterator cmt_use_summaries in
match cmt_annots with
| Implementation typedtree ->
- Iterator.iter_structure typedtree;
+ iterator # structure typedtree;
Stypes.dump target_filename
| Interface _ ->
Printf.fprintf stderr "Cannot generate annotations for interface file\n%!";
exit 2
-(* this does not work, probably because of the crazy imperative implementation of the traversal *)
-(*
| Partial_implementation parts ->
- Array.iter binary_part parts;
+ Array.iter (binary_part iterator) parts;
Stypes.dump target_filename
-*)
| _ ->
Printf.fprintf stderr "File was generated with an error\n%!";
exit 2
diff --git a/tools/tast_iter.ml b/tools/tast_iter.ml
new file mode 100644
index 000000000..d36520e82
--- /dev/null
+++ b/tools/tast_iter.ml
@@ -0,0 +1,376 @@
+(***********************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Alain Frisch, LexiFi *)
+(* *)
+(* Copyright 2012 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+open Asttypes
+open Typedtree
+
+let opt f = function None -> () | Some x -> f x
+
+let structure sub str =
+ List.iter (sub # structure_item) str.str_items
+
+let structure_item sub x =
+ match x.str_desc with
+ | Tstr_eval exp -> sub # expression exp
+ | Tstr_value (rec_flag, list) -> sub # bindings (rec_flag, list)
+ | Tstr_primitive (id, _, v) -> sub # value_description v
+ | Tstr_type list ->
+ List.iter (fun (id, _, decl) -> sub # type_declaration decl) list
+ | Tstr_exception (id, _, decl) -> sub # exception_declaration decl
+ | Tstr_exn_rebind (id, _, p, _) -> ()
+ | Tstr_module (id, _, mexpr) -> sub # module_expr mexpr
+ | Tstr_recmodule list ->
+ List.iter
+ (fun (id, _, mtype, mexpr) ->
+ sub # module_type mtype;
+ sub # module_expr mexpr
+ )
+ list
+ | Tstr_modtype (id, _, mtype) -> sub # module_type mtype
+ | Tstr_open _ -> ()
+ | Tstr_class list ->
+ List.iter (fun (ci, _, _) -> sub # class_expr ci.ci_expr) list
+ | Tstr_class_type list ->
+ List.iter (fun (id, _, ct) -> sub # class_type ct.ci_expr) list
+ | Tstr_include (mexpr, _) -> sub # module_expr mexpr
+
+let value_description sub x =
+ sub # core_type x.val_desc
+
+let type_declaration sub decl =
+ List.iter
+ (fun (ct1, ct2, loc) -> sub # core_type ct1; sub # core_type ct2)
+ decl.typ_cstrs;
+ begin match decl.typ_kind with
+ | Ttype_abstract -> ()
+ | Ttype_variant list ->
+ List.iter (fun (s, _, cts, loc) -> List.iter (sub # core_type) cts) list
+ | Ttype_record list ->
+ List.iter (fun (s, _, mut, ct, loc) -> sub # core_type ct) list
+ end;
+ opt (sub # core_type) decl.typ_manifest
+
+let exception_declaration sub decl =
+ List.iter (sub # core_type) decl.exn_params
+
+let pattern sub pat =
+ let extra = function
+ | Tpat_type _
+ | Tpat_unpack -> ()
+ | Tpat_constraint ct -> sub # core_type ct
+ in
+ List.iter (fun (c, _) -> extra c) pat.pat_extra;
+ match pat.pat_desc with
+ | Tpat_any
+ | Tpat_var _
+ | Tpat_constant _ -> ()
+ | Tpat_tuple l
+ | Tpat_construct (_, _, l, _) -> List.iter (sub # pattern) l
+ | Tpat_variant (_, po, _) -> opt (sub # pattern) po
+ | Tpat_record (l, _) -> List.iter (fun (_, _, pat) -> sub # pattern pat) l
+ | Tpat_array l -> List.iter (sub # pattern) l
+ | Tpat_or (p1, p2, _) -> sub # pattern p1; sub # pattern p2
+ | Tpat_alias (p, _, _)
+ | Tpat_lazy p -> sub # pattern p
+
+let expression sub exp =
+ let extra = function
+ | Texp_constraint (cty1, cty2) ->
+ opt (sub # core_type) cty1; opt (sub # core_type) cty2
+ | Texp_open _
+ | Texp_newtype _ -> ()
+ | Texp_poly cto -> opt (sub # core_type) cto
+ in
+ List.iter (function (c, _) -> extra c) exp.exp_extra;
+ match exp.exp_desc with
+ | Texp_ident _
+ | Texp_constant _ -> ()
+ | Texp_let (rec_flag, list, exp) ->
+ sub # bindings (rec_flag, list);
+ sub # expression exp
+ | Texp_function (_, cases, _) ->
+ sub # bindings (Nonrecursive, cases)
+ | Texp_apply (exp, list) ->
+ sub # expression exp;
+ List.iter (fun (_, expo, _) -> opt (sub # expression) expo) list
+ | Texp_match (exp, list, _) ->
+ sub # expression exp;
+ sub # bindings (Nonrecursive, list)
+ | Texp_try (exp, list) ->
+ sub # expression exp;
+ sub # bindings (Nonrecursive, list)
+ | Texp_tuple list ->
+ List.iter (sub # expression) list
+ | Texp_construct (_, _, args, _) ->
+ List.iter (sub # expression) args
+ | Texp_variant (_, expo) ->
+ opt (sub # expression) expo
+ | Texp_record (list, expo) ->
+ List.iter (fun (_, _, exp) -> sub # expression exp) list;
+ opt (sub # expression) expo
+ | Texp_field (exp, _, label) ->
+ sub # expression exp
+ | Texp_setfield (exp1, _, label, exp2) ->
+ sub # expression exp1;
+ sub # expression exp2
+ | Texp_array list ->
+ List.iter (sub # expression) list
+ | Texp_ifthenelse (exp1, exp2, expo) ->
+ sub # expression exp1;
+ sub # expression exp2;
+ opt (sub # expression) expo
+ | Texp_sequence (exp1, exp2) ->
+ sub # expression exp1;
+ sub # expression exp2
+ | Texp_while (exp1, exp2) ->
+ sub # expression exp1;
+ sub # expression exp2
+ | Texp_for (id, _, exp1, exp2, dir, exp3) ->
+ sub # expression exp1;
+ sub # expression exp2;
+ sub # expression exp3
+ | Texp_when (exp1, exp2) ->
+ sub # expression exp1;
+ sub # expression exp2
+ | Texp_send (exp, meth, expo) ->
+ sub # expression exp;
+ opt (sub # expression) expo
+ | Texp_new (path, _, _) -> ()
+ | Texp_instvar (_, path, _) -> ()
+ | Texp_setinstvar (_, _, _, exp) ->
+ sub # expression exp
+ | Texp_override (_, list) ->
+ List.iter (fun (path, _, exp) -> sub # expression exp) list
+ | Texp_letmodule (id, _, mexpr, exp) ->
+ sub # module_expr mexpr;
+ sub # expression exp
+ | Texp_assert exp -> sub # expression exp
+ | Texp_assertfalse -> ()
+ | Texp_lazy exp -> sub # expression exp
+ | Texp_object (cl, _) ->
+ sub # class_structure cl
+ | Texp_pack (mexpr) ->
+ sub # module_expr mexpr
+
+
+let package_type sub pack =
+ List.iter (fun (s, ct) -> sub # core_type ct) pack.pack_fields
+
+let signature sub sg =
+ List.iter (sub # signature_item) sg.sig_items
+
+let signature_item sub item =
+ match item.sig_desc with
+ | Tsig_value (id, _, v) ->
+ sub # value_description v
+ | Tsig_type list ->
+ List.iter (fun (id, _, decl) -> sub # type_declaration decl) list
+ | Tsig_exception (id, _, decl) ->
+ sub # exception_declaration decl
+ | Tsig_module (id, _, mtype) ->
+ sub # module_type mtype
+ | Tsig_recmodule list ->
+ List.iter (fun (id, _, mtype) -> sub # module_type mtype) list
+ | Tsig_modtype (id, _, mdecl) ->
+ sub # modtype_declaration mdecl
+ | Tsig_open _ -> ()
+ | Tsig_include (mty,_) -> sub # module_type mty
+ | Tsig_class list ->
+ List.iter (sub # class_description) list
+ | Tsig_class_type list ->
+ List.iter (sub # class_type_declaration) list
+
+let modtype_declaration sub mdecl =
+ match mdecl with
+ | Tmodtype_abstract -> ()
+ | Tmodtype_manifest mtype -> sub # module_type mtype
+
+let class_description sub cd =
+ sub # class_type cd.ci_expr
+
+let class_type_declaration sub cd =
+ sub # class_type cd.ci_expr
+
+let module_type sub mty =
+ match mty.mty_desc with
+ | Tmty_ident (path, _) -> ()
+ | Tmty_signature sg -> sub # signature sg
+ | Tmty_functor (id, _, mtype1, mtype2) ->
+ sub # module_type mtype1; sub # module_type mtype2
+ | Tmty_with (mtype, list) ->
+ sub # module_type mtype;
+ List.iter (fun (_, _, withc) -> sub # with_constraint withc) list
+ | Tmty_typeof mexpr ->
+ sub # module_expr mexpr
+
+let with_constraint sub cstr =
+ match cstr with
+ | Twith_type decl -> sub # type_declaration decl
+ | Twith_module _ -> ()
+ | Twith_typesubst decl -> sub # type_declaration decl
+ | Twith_modsubst _ -> ()
+
+let module_expr sub mexpr =
+ match mexpr.mod_desc with
+ | Tmod_ident (p, _) -> ()
+ | Tmod_structure st -> sub # structure st
+ | Tmod_functor (id, _, mtype, mexpr) ->
+ sub # module_type mtype;
+ sub # module_expr mexpr
+ | Tmod_apply (mexp1, mexp2, _) ->
+ sub # module_expr mexp1;
+ sub # module_expr mexp2
+ | Tmod_constraint (mexpr, _, Tmodtype_implicit, _ ) ->
+ sub # module_expr mexpr
+ | Tmod_constraint (mexpr, _, Tmodtype_explicit mtype, _) ->
+ sub # module_expr mexpr;
+ sub # module_type mtype
+ | Tmod_unpack (exp, mty) ->
+ sub # expression exp
+(* sub # module_type mty *)
+
+let class_expr sub cexpr =
+ match cexpr.cl_desc with
+ | Tcl_constraint (cl, None, _, _, _ ) ->
+ sub # class_expr cl;
+ | Tcl_structure clstr -> sub # class_structure clstr
+ | Tcl_fun (label, pat, priv, cl, partial) ->
+ sub # pattern pat;
+ List.iter (fun (id, _, exp) -> sub # expression exp) priv;
+ sub # class_expr cl
+ | Tcl_apply (cl, args) ->
+ sub # class_expr cl;
+ List.iter (fun (label, expo, _) -> opt (sub # expression) expo) args
+ | Tcl_let (rec_flat, bindings, ivars, cl) ->
+ sub # bindings (rec_flat, bindings);
+ List.iter (fun (id, _, exp) -> sub # expression exp) ivars;
+ sub # class_expr cl
+ | Tcl_constraint (cl, Some clty, vals, meths, concrs) ->
+ sub # class_expr cl;
+ sub # class_type clty
+ | Tcl_ident (_, _, tyl) ->
+ List.iter (sub # core_type) tyl
+
+let class_type sub ct =
+ match ct.cltyp_desc with
+ | Tcty_signature csg -> sub # class_signature csg
+ | Tcty_constr (path, _, list) -> List.iter (sub # core_type) list
+ | Tcty_fun (label, ct, cl) ->
+ sub # core_type ct;
+ sub # class_type cl
+
+let class_signature sub cs =
+ sub # core_type cs.csig_self;
+ List.iter (sub # class_type_field) cs.csig_fields
+
+let class_type_field sub ctf =
+ match ctf.ctf_desc with
+ | Tctf_inher ct -> sub # class_type ct
+ | Tctf_val (s, mut, virt, ct) ->
+ sub # core_type ct
+ | Tctf_virt (s, priv, ct) ->
+ sub # core_type ct
+ | Tctf_meth (s, priv, ct) ->
+ sub # core_type ct
+ | Tctf_cstr (ct1, ct2) ->
+ sub # core_type ct1;
+ sub # core_type ct2
+
+let core_type sub ct =
+ match ct.ctyp_desc with
+ | Ttyp_any -> ()
+ | Ttyp_var s -> ()
+ | Ttyp_arrow (label, ct1, ct2) ->
+ sub # core_type ct1;
+ sub # core_type ct2
+ | Ttyp_tuple list -> List.iter (sub # core_type) list
+ | Ttyp_constr (path, _, list) ->
+ List.iter (sub # core_type) list
+ | Ttyp_object list ->
+ List.iter (sub # core_field_type) list
+ | Ttyp_class (path, _, list, labels) ->
+ List.iter (sub # core_type) list
+ | Ttyp_alias (ct, s) ->
+ sub # core_type ct
+ | Ttyp_variant (list, bool, labels) ->
+ List.iter (sub # row_field) list
+ | Ttyp_poly (list, ct) -> sub # core_type ct
+ | Ttyp_package pack -> sub # package_type pack
+
+let core_field_type sub cft =
+ match cft.field_desc with
+ | Tcfield_var -> ()
+ | Tcfield (s, ct) -> sub # core_type ct
+
+let class_structure sub cs =
+ sub # pattern cs.cstr_pat;
+ List.iter (sub # class_field) cs.cstr_fields
+
+let row_field sub rf =
+ match rf with
+ | Ttag (label, bool, list) -> List.iter (sub # core_type) list
+ | Tinherit ct -> sub # core_type ct
+
+let class_field sub cf =
+ match cf.cf_desc with
+ | Tcf_inher (ovf, cl, super, _vals, _meths) ->
+ sub # class_expr cl
+ | Tcf_constr (cty, cty') ->
+ sub # core_type cty;
+ sub # core_type cty'
+ | Tcf_val (lab, _, _, mut, Tcfk_virtual cty, override) ->
+ sub # core_type cty
+ | Tcf_val (lab, _, _, mut, Tcfk_concrete exp, override) ->
+ sub # expression exp
+ | Tcf_meth (lab, _, priv, Tcfk_virtual cty, override) ->
+ sub # core_type cty
+ | Tcf_meth (lab, _, priv, Tcfk_concrete exp, override) ->
+ sub # expression exp
+ | Tcf_init exp ->
+ sub # expression exp
+
+let bindings sub (rec_flag, list) =
+ List.iter (sub # binding) list
+
+let binding sub (pat, exp) =
+ sub # pattern pat;
+ sub # expression exp
+
+class iter = object(this)
+ method binding = binding this
+ method bindings = bindings this
+ method class_description = class_description this
+ method class_expr = class_expr this
+ method class_field = class_field this
+ method class_signature = class_signature this
+ method class_structure = class_structure this
+ method class_type = class_type this
+ method class_type_declaration = class_type_declaration this
+ method class_type_field = class_type_field this
+ method core_field_type = core_field_type this
+ method core_type = core_type this
+ method exception_declaration = exception_declaration this
+ method expression = expression this
+ method modtype_declaration = modtype_declaration this
+ method module_expr = module_expr this
+ method module_type = module_type this
+ method package_type = package_type this
+ method pattern = pattern this
+ method row_field = row_field this
+ method signature = signature this
+ method signature_item = signature_item this
+ method structure = structure this
+ method structure_item = structure_item this
+ method type_declaration = type_declaration this
+ method value_description = value_description this
+ method with_constraint = with_constraint this
+end
diff --git a/tools/tast_iter.mli b/tools/tast_iter.mli
new file mode 100644
index 000000000..cc9bbcae4
--- /dev/null
+++ b/tools/tast_iter.mli
@@ -0,0 +1,80 @@
+(***********************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Alain Frisch, LexiFi *)
+(* *)
+(* Copyright 2012 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+open Asttypes
+open Typedtree
+
+class iter: object
+ method binding: (pattern * expression) -> unit
+ method bindings: (rec_flag * (pattern * expression) list) -> unit
+ method class_description: class_description -> unit
+ method class_expr: class_expr -> unit
+ method class_field: class_field -> unit
+ method class_signature: class_signature -> unit
+ method class_structure: class_structure -> unit
+ method class_type: class_type -> unit
+ method class_type_declaration: class_type_declaration -> unit
+ method class_type_field: class_type_field -> unit
+ method core_field_type: core_field_type -> unit
+ method core_type: core_type -> unit
+ method exception_declaration: exception_declaration -> unit
+ method expression: expression -> unit
+ method modtype_declaration: modtype_declaration -> unit
+ method module_expr: module_expr -> unit
+ method module_type: module_type -> unit
+ method package_type: package_type -> unit
+ method pattern: pattern -> unit
+ method row_field: row_field -> unit
+ method signature: signature -> unit
+ method signature_item: signature_item -> unit
+ method structure: structure -> unit
+ method structure_item: structure_item -> unit
+ method type_declaration: type_declaration -> unit
+ method value_description: value_description -> unit
+ method with_constraint: with_constraint -> unit
+end
+(** Recursive iterator class. By inheriting from it and
+ overriding selected methods, it is possible to implement
+ custom behavior for specific kinds of nodes. *)
+
+(** {2 One-level iterators} *)
+
+(** The following functions apply the provided iterator to each
+ sub-component of the argument. *)
+
+val binding: iter -> (pattern * expression) -> unit
+val bindings: iter -> (rec_flag * (pattern * expression) list) -> unit
+val class_description: iter -> class_description -> unit
+val class_expr: iter -> class_expr -> unit
+val class_field: iter -> class_field -> unit
+val class_signature: iter -> class_signature -> unit
+val class_structure: iter -> class_structure -> unit
+val class_type: iter -> class_type -> unit
+val class_type_declaration: iter -> class_type_declaration -> unit
+val class_type_field: iter -> class_type_field -> unit
+val core_field_type: iter -> core_field_type -> unit
+val core_type: iter -> core_type -> unit
+val exception_declaration: iter -> exception_declaration -> unit
+val expression: iter -> expression -> unit
+val modtype_declaration: iter -> modtype_declaration -> unit
+val module_expr: iter -> module_expr -> unit
+val module_type: iter -> module_type -> unit
+val package_type: iter -> package_type -> unit
+val pattern: iter -> pattern -> unit
+val row_field: iter -> row_field -> unit
+val signature: iter -> signature -> unit
+val signature_item: iter -> signature_item -> unit
+val structure: iter -> structure -> unit
+val structure_item: iter -> structure_item -> unit
+val type_declaration: iter -> type_declaration -> unit
+val value_description: iter -> value_description -> unit
+val with_constraint: iter -> with_constraint -> unit