Commits

camlspotter  committed b5d5711

merge with custom-3.11.2

  • Participants
  • Parent commits b2b5eb1
  • Branches ocamlspot

Comments (0)

Files changed (22)

File ocamlspot/.depend

 command.cmi:
 pathreparse.cmi: spotapi.cmi ../typing/path.cmi
-sourceloc.cmi:
 spotapi.cmi: ../typing/types.cmi ../typing/typedtree.cmi ../typing/spot.cmi \
     ../typing/path.cmi ../typing/ident.cmi
 spotconfig.cmi: spotapi.cmi
 spoteval.cmi: utils.cmi ../typing/types.cmi spotapi.cmi ../typing/path.cmi \
     ../typing/ident.cmi
 spotfile.cmi: spoteval.cmi spotconfig.cmi spotapi.cmi ../typing/spot.cmi \
-    ../typing/ident.cmi ../typing/annot.cmi
+    ../typing/path.cmi ../typing/ident.cmi ../typing/env.cmi \
+    ../typing/annot.cmi
 treeset.cmi: xset.cmi
 utils.cmi:
-with_pos.cmi:
 xmain.cmi:
 xset.cmi:
-xspot.cmi:
 command.cmo: command.cmi
 command.cmx: command.cmi
 dotfile.cmo:
 dotfile.cmx:
 ocamlspot.cmo: xmain.cmi utils.cmi spotfile.cmi spoteval.cmi spotconfig.cmi \
-    spotapi.cmi ../typing/printtyp.cmi pathreparse.cmi ../typing/ident.cmi \
-    ../typing/env.cmi command.cmi ../typing/annot.cmi
+    spotapi.cmi ../typing/printtyp.cmi pathreparse.cmi ../typing/path.cmi \
+    ../typing/ident.cmi ../typing/env.cmi command.cmi ../typing/annot.cmi
 ocamlspot.cmx: xmain.cmx utils.cmx spotfile.cmx spoteval.cmx spotconfig.cmx \
-    spotapi.cmx ../typing/printtyp.cmx pathreparse.cmx ../typing/ident.cmx \
-    ../typing/env.cmx command.cmx ../typing/annot.cmi
+    spotapi.cmx ../typing/printtyp.cmx pathreparse.cmx ../typing/path.cmx \
+    ../typing/ident.cmx ../typing/env.cmx command.cmx ../typing/annot.cmi
 pathreparse.cmo: utils.cmi spotapi.cmi ../typing/path.cmi ../typing/ident.cmi \
     pathreparse.cmi
 pathreparse.cmx: utils.cmx spotapi.cmx ../typing/path.cmx ../typing/ident.cmx \
     pathreparse.cmi
-sourceloc.cmo: with_pos.cmi sourceloc.cmi
-sourceloc.cmx: with_pos.cmx sourceloc.cmi
 spotapi.cmo: utils.cmi ../typing/types.cmi treeset.cmi ../typing/spot.cmi \
-    sourceloc.cmi ../typing/printtyp.cmi ../typing/predef.cmi \
-    ../typing/path.cmi ../typing/ident.cmi ../typing/btype.cmi \
-    ../typing/annot.cmi spotapi.cmi
+    ../typing/printtyp.cmi ../typing/predef.cmi ../typing/path.cmi \
+    ../typing/ident.cmi ../typing/btype.cmi ../typing/annot.cmi spotapi.cmi
 spotapi.cmx: utils.cmx ../typing/types.cmx treeset.cmx ../typing/spot.cmx \
-    sourceloc.cmx ../typing/printtyp.cmx ../typing/predef.cmx \
-    ../typing/path.cmx ../typing/ident.cmx ../typing/btype.cmx \
-    ../typing/annot.cmi spotapi.cmi
+    ../typing/printtyp.cmx ../typing/predef.cmx ../typing/path.cmx \
+    ../typing/ident.cmx ../typing/btype.cmx ../typing/annot.cmi spotapi.cmi
 spotconfig.cmo: utils.cmi spoteval.cmi spotapi.cmi ../typing/spot.cmi \
     ../typing/path.cmi spotconfig.cmi
 spotconfig.cmx: utils.cmx spoteval.cmx spotapi.cmx ../typing/spot.cmx \
 treeset.cmx: xset.cmx treeset.cmi
 utils.cmo: utils.cmi
 utils.cmx: utils.cmi
-with_pos.cmo: with_pos.cmi
-with_pos.cmx: with_pos.cmi
 xmain.cmo: ../typing/spot.cmi xmain.cmi
 xmain.cmx: ../typing/spot.cmx xmain.cmi
 xset.cmo: xset.cmi
 xset.cmx: xset.cmi
-xspot.cmo: xspot.cmi
-xspot.cmx: xspot.cmi

File ocamlspot/BRAIN_DEAD_INSTALL.sh

File contents unchanged.

File ocamlspot/Makefile

 COMPFLAGS= $(INCLUDES_DEP) -I $(OTHERS)/unix
 
 MODULES= utils dotfile xset treeset command \
-	spotapi spoteval spotconfig spotfile pathreparse xmain ocamlspot
+	spotapi spoteval spotconfig_intf spotconfig spotfile pathreparse xmain ocamlspot
 
 UTILS=utils/misc utils/tbl utils/config \
   utils/clflags utils/terminfo utils/ccomp utils/warnings \

File ocamlspot/VERIFY.sh

File contents unchanged.

File ocamlspot/ocamlspot.el

 ;         '(lambda ()
 ;            (local-set-key "\C-c;" 'ocamlspot-query)
 ; 	     (local-set-key "\C-c:" 'ocamlspot-query-interface)
+;            (local-set-key "\C-c'" 'ocamlspot-query-uses)
 ;            (local-set-key "\C-c\C-t" 'ocamlspot-type)
 ;            (local-set-key "\C-c\C-i" 'ocamlspot-xtype)
 ;            (local-set-key "\C-c\C-y" 'ocamlspot-type-and-copy)
         (insert "\n"))
     (insert mes)))
 
-; display message in the echo area if it is enough short, then return the string
-; if too large, pop a buffer of the message if may-pop is t and return the buffer 
-; otherwise, returns nil
+; Display message in the echo area if it is enough short, then return the string.
+; If too large, pop a buffer of the message if may-pop is t and return the buffer.
+; Otherwise, returns nil
 (defun ocamlspot-message-display (&optional may-pop)
   (with-current-buffer (get-buffer-create ocamlspot-message-buffer)
     (let ((lines ; how many lines in minibuffer-window ? 
 
 (defun ocamlspot-run-query (args &optional chdir)
   (with-current-buffer (get-buffer-create ocamlspot-process-buffer)
+    (ocamlspot-process-mode t)
     (erase-buffer)
-    ;; chdir is required
-    (if chdir (cd chdir))
-    (let ((args (if ocamlspot-debug (concat "-debug " args) args)))
-      (call-process shell-file-name nil t nil shell-command-switch
-		    (concat (ocamlspot-get-command) " " args)))))
+    (let ((command (concat (ocamlspot-get-command) " " args)))
+      (insert command)
+      (insert "\n")
+      ;; chdir is required
+      (if chdir (cd chdir))
+      (let ((args (if ocamlspot-debug (concat "-debug " args) args)))
+	(call-process shell-file-name nil t nil shell-command-switch
+		      command)))))
+
+(defun ocamlspot-query-string-at-cursor ()
+  (format "%s:l%dc%d"
+	  (buffer-file-name)
+	  (ocamlspot-lines-of-point)
+	  (ocamlspot-bytes-of-line-to-point)))
 
 ; launch ocamlspot, using the position of the cursor
 ; result is stored in the buffer "ocamlspot-process-buffer"
 ; the current buffer is stored in source-buffer
-(defun ocamlspot-query-at-cursor (extra_args)
+(defun ocamlspot-query-at-cursor (pre_extra_args &optional post_extra_args)
   ;; arguments
   (let ((file-name (buffer-file-name))
-	(arg (format "%s:l%dc%d"
-		     (buffer-file-name)
-		     (ocamlspot-lines-of-point)
-		     (ocamlspot-bytes-of-line-to-point))))
-    (ocamlspot-run-query (concat extra_args " " arg) 
+	(arg (ocamlspot-query-string-at-cursor))
+	(post_sep (if post_extra_args " " "")))
+    (ocamlspot-run-query (concat pre_extra_args " " arg post_sep post_extra_args) 
 			 (file-name-directory file-name))))
 
+;;; Search ocamlspot-process-buffer and return the first line which matches with ^<pattern>: "
 (defun ocamlspot-find-query-result (pattern &optional to-kill)
   (set-buffer (get-buffer-create ocamlspot-process-buffer))
   (goto-char (point-min))
      (ocamlspot-find-file-existing filename)
      position ocamlspot-spot-overlay)))
 
+(defun ocamlspot-jump-to-path-range (path-range)
+  (if (string-match "^<?\\(.*\\):\\(l[\-0-9]+c[\-0-9]+b[\-0-9]+:l[\-0-9]+c[\-0-9]+b[\-0-9]+\\|[0-9]+:[0-9]+\\|all\\|-1:-1\\)>?$" path-range)
+      (let ((filename (match-string 1 path-range))
+	    (position (match-string 2 path-range)))
+	;; display the result
+	(ocamlspot-jump-to-spot filename position)
+	(let ((type (ocamlspot-find-val-or-type)))
+	  ;; (if type (ocamlspot-message-add (format "Type: %s" type)))
+	  ))
+    ;; failed to get the normal result
+    ;; CR jfuruse: this is an error message. Should be decolated?
+    (ocamlspot-message-add path-range)))
+
 (defun ocamlspot-find-type (&optional to-kill)
   (let ((type (ocamlspot-find-query-result "Type" to-kill)))
     (if type 
 
 (defun ocamlspot-find-spot ()
   (let ((spot (ocamlspot-find-query-result "Spot")))
-    (if spot
-	(if (string-match "^\\(.*\\):\\(l[\-0-9]+c[\-0-9]+b[\-0-9]+:l[\-0-9]+c[\-0-9]+b[\-0-9]+\\|[0-9]+:[0-9]+\\|all\\|-1:-1\\)$" spot)
-	    (let ((filename (match-string 1 spot))
-		  (position (match-string 2 spot)))
-	      ;; display the result
-	      (ocamlspot-jump-to-spot filename position)
-	      (let ((type (ocamlspot-find-val-or-type)))
-		;; (if type (ocamlspot-message-add (format "Type: %s" type)))
-		))
-	  ;; failed to get the normal result
-	  (ocamlspot-message-add spot))
+    (if spot (ocamlspot-jump-to-path-range spot)
       ;; no Spot:
       (let ((err (ocamlspot-find-query-result "Error")))
 	(if err
 	    (ocamlspot-message-add (concat "Error: " err))
 	  ;; display debug info
-	  (ocamlspot-message-add "No spot found there")
+	  (ocamlspot-message-add "No definition info found")
 	  (ocamlspot-find-val-or-type)
 	)))))
 
         (ocamlspot-find-use)))
   (ocamlspot-wait t))
 
+; CR can be shared with ocamlspot-type
+(defun ocamlspot-query-uses ()
+  (interactive)
+  (let ((dir (read-directory-name "Search directory: "
+				  (file-name-directory (buffer-file-name)))))
+    (ocamlspot-message-init (buffer-file-name))
+    (ocamlspot-type-init)
+    (ocamlspot-delete-overlays-now)
+    (ocamlspot-query-at-cursor "use" dir)
+    (if (ocamlspot-find-tree)
+	(progn
+	 (ocamlspot-find-spot)
+	 (display-buffer ocamlspot-process-buffer)
+	 (ocamlspot-find-use)))
+    (ocamlspot-wait t)))
+
+;; Browsing of path-range <file:lxcxbx:lxcxbx>
+(defun ocamlspot-beginning-of-path-range ()
+  (search-backward "<"
+		   (save-excursion (beginning-of-line) (point))))
+(defun ocamlspot-end-of-path-range ()
+  (search-forward ">"
+		  (save-excursion (end-of-line) (point))))
+(put 'ocamlspot-path-range 'beginning-op 'ocamlspot-beginning-of-path-range)
+(put 'ocamlspot-path-range 'end-op 'ocamlspot-end-of-path-range)
+
+(defun ocamlspot-path-range-at-point ()
+  (interactive)
+  (let ((bounds (bounds-of-thing-at-point 'ocamlspot-path-range)))
+      (if bounds
+	  (progn
+	    (move-overlay ocamlspot-tree-overlay (car bounds) (cdr bounds))
+	    (buffer-substring (car bounds) (cdr bounds))))))
+
+(defun ocamlspot-browse-path-range-at-point ()
+  (interactive)
+  (let ((path-range (ocamlspot-path-range-at-point)))
+    (if path-range
+	(ocamlspot-jump-to-path-range path-range)
+	(message "no path-range at point")
+	)))
+
 ;; build query string for the cursor point
 (defun ocamlspot-xtype-build-query-at-cursor ()
   (let ((path-name 
 		 (progn
 		   (move-overlay ocamlspot-tree-overlay start end)
 		   (buffer-substring-no-properties start end)))))))
-    (message "gagaga")
     (message (concat "path-name " path-name))
     (let ((file-name 
 	   (save-excursion
     (define-key keymap "\C-c;" 'ocamlspot-xtype-query)
     keymap))
 
+(defun ocamlspot-process-mode-map ()
+  (let ((keymap (make-sparse-keymap)))
+    (define-key keymap "\C-c;" 'ocamlspot-browse-path-range-at-point)
+    keymap))
+
 (define-minor-mode ocamlspot-xtype-mode
   "OCamlSpot XType mode."
   :lighter " OCamlSpot-XType"
   :keymap (ocamlspot-xtype-mode-map))
 
+(define-minor-mode ocamlspot-process-mode
+  "OCamlSpot Process mode."
+  :lighter " OCamlSpot-Process"
+  :keymap (ocamlspot-process-mode-map))
+
 (provide 'ocamlspot)

File ocamlspot/ocamlspot.ml

 open Spotapi
 open Spoteval
 
-module File = Spotfile.Make(Spotconfig)
+module C = Spotconfig
+
+module File = Spotfile.Make(C)
     
 module Dump = struct
   (* mainly debugging purpose *)
     let str = 
       Eval.structure (File.empty_env file) file.File.top
     in
-    if Spotconfig.eager_dump then begin
+    if C.eager_dump then begin
       let module Enforcer = Value.Enforcer(struct end) in
       Enforcer.structure str;
     end;
       Binding.set env.Env.binding str; (* dirty hack (dup code) *)
       str
     in
-    if Spotconfig.eager_dump then begin
+    if C.eager_dump then begin
       let module Enforcer = Value.Enforcer(struct end) in
       Enforcer.structure str;
     end;
 
     let file = File.load ~load_paths: ["."] path in
     
-    if Spotconfig.dump_file then Dump.file file;
-    if Spotconfig.dump_rannots then Dump.rannots file;
-    if Spotconfig.dump_tree then Dump.tree file;
-    if Spotconfig.dump_top then Dump.top file;
-    if Spotconfig.dump_flat then Dump.flat file;
+    if C.dump_file then Dump.file file;
+    if C.dump_rannots then Dump.rannots file;
+    if C.dump_tree then Dump.tree file;
+    if C.dump_top then Dump.top file;
+    if C.dump_flat then Dump.flat file;
 
-    if Spotconfig.print_file_info then
+    if C.print_file_info then
       Format.printf "Compile: %s@."
         (String.concat " " 
             (List.map Command.escaped_for_shell 
                 (Array.to_list file.File.argv)));
 
-    if Spotconfig.print_file_info then
+    if C.print_file_info then
       Format.printf "@[<v2>Included_dirs:@ %a@]@."
         (Format.list "" Format.pp_print_string)
         file.File.load_paths;
 
-    if Spotconfig.dump_any then bye 0;
-    
     file
   ;;
 
     | None -> Format.printf "Spot: no spot@."
     | Some (pident, res) -> match res with
 	| File.File_itself ->
-            Format.printf "Spot: %s:all@." pident.PIdent.path
+            Format.printf "Spot: <%s:all>@." pident.PIdent.path
 	| File.Found_at region ->
-            Format.printf "Spot: %s:%s@."
+            Format.printf "Spot: <%s:%s>@."
               pident.PIdent.path
               (Region.to_string region)
 	| File.Predefined ->
 	    List.find_map_opt (function
 	      | Annot.Use (_kind, path) -> 
 		  (* Find subpath *)
-		  begin match Pathreparse.get Spotconfig.mlpath r pos path with    
+		  begin match Pathreparse.get file.File.path r pos path with    
 		  | None -> None
-
 		  | Some (path', r) -> 
 		      if path = path' then None (* as original *)
 		      else Some ([Annot.Use (Kind.Module, path')], r)
         List.iter (fun annot -> 
 	  Format.printf "%a@." Annot.format annot) annots;
 
+	(* Tree is an older format. XTree is a newer which is the same as one for Spot *)
         Format.printf "Tree: %s@." (Region.to_string r);
+        Format.printf "XTree: <%s:%s>@." file.File.path (Region.to_string r);
 
 	(* Find the innermost module *)
         let rec find_module_path = function
           | Some typ, Some id ->
               Format.printf "Val: val %s : @[%a@]@."
                 (Ident0.name id)
-                (Printtyp.type_sch ~with_pos:false) typ
+                (Printtyp.type_scheme ~with_pos:false) typ
           | _ -> ()
         in
         print_sig_entry annots;
 	annots
   ;;
 
-  let query () = 
+  let query path spec = 
     (* CR jfuruse: dup *)
-    Debug.format "ocamlspot %s%s@." 
-      Spotconfig.mlpath (Spotconfig.Spec.to_string Spotconfig.spec);
+    Debug.format "ocamlspot %s%s@." path (C.SearchSpec.to_string spec);
     Debug.format "cwd: %s@." (Sys.getcwd ());
-    let path = File.spot_of_file Spotconfig.mlpath in
+    let path = File.spot_of_file path in
     let file = load path in
 
-    begin match Spotconfig.spec with
-    | Spotconfig.Spec.Dump -> ()
-    | Spotconfig.Spec.Kind (k,path) -> print_query_result k (query_by_kind_path file k path)
-    | Spotconfig.Spec.Pos pos -> 
+    begin match spec with
+    | C.SearchSpec.Kind (k,path) -> 
+        print_query_result k (query_by_kind_path file k path)
+    | C.SearchSpec.Pos pos -> 
 	let annots = query_by_pos file pos in
-        if not Spotconfig.no_definition_analysis then begin
+        if not C.no_definition_analysis then begin
           List.iter (function
             | Annot.Use (kind, path) -> 
 		print_query_result kind (query_by_kind_path file kind path)
 
     bye 0
 
-  let query () =
-    try query () with
+  let query file spec =
+    try query file spec with
     | Failure s ->
         Format.eprintf "Error: %s@." s;
         bye 1
         Format.eprintf "uncaught exception: %s@." (Printexc.to_string e);
         bye 1
 
-  let use () =
+  let use path spec targets =
+    let targets = if targets = [] then ["."] else targets in
     (* CR jfuruse: dup *)
-    Debug.format "ocamlspot %s%s@." 
-      Spotconfig.mlpath (Spotconfig.Spec.to_string Spotconfig.spec);
+    Debug.format "ocamlspot %s%s@." path (C.SearchSpec.to_string spec);
     Debug.format "cwd: %s@." (Sys.getcwd ());
-    let path = File.spot_of_file Spotconfig.mlpath in
+    let path = File.spot_of_file path in
     let file = load path in
 
+    let find_by_kind_path k path found =
+      Unix.find targets ~f:(fun pathname ->
+	match Filename.split_extension pathname.Unix.base with
+	| _body, (".spit" | ".spot") ->
+	  let file = load pathname.Unix.path in
+	  Debug.format "Searching %s@." pathname.Unix.path;
+	  let base_ident = function
+	    | Path.Pident id -> Ident0.name id
+	    | Path.Pdot (_, name, _) -> name
+	    | Path.Papply _ -> assert false
+	  in
+	  let base = base_ident path in
+	  List.iter (function
+	    | { Regioned.region= region; value= Annot.Use (k', path'); } when k = k' && base = base_ident path' ->
+	      begin match query_by_kind_path file k' path' with
+	      | Some found' when found = found' ->
+		  Format.printf "<%s:%s>: %s@." 
+		    file.File.path
+		    (Region.to_string region)
+		    (Path.name path)
+	      | None | Some _ -> ()
+	      end
+	    | _ -> ()) file.File.rannots
+	| _ -> ());
+    in
+
     let by_kind_path file k path =
-      Format.eprintf "Searching %s:%s:%s ...@." file.File.path (Kind.to_string k) (Path.name path); 
+      Debug.format "Searching %s:%s:%s ...@." 
+	file.File.path 
+	(Kind.to_string k) 
+	(Path.name path); 
       let res = query_by_kind_path file k path in
       print_query_result k res;
       match res with
-      | None -> ()
-      | Some found_path ->
-	  Unix.find "." ~f:(fun pathname ->
-	    match Filename.split_extension pathname.Unix.base with
-	    | _body, (".spit" | ".spot") ->
-	    let file = load pathname.Unix.path in
-	    prerr_endline pathname.Unix.path;
-	    let base_ident = function
-	      | Path.Pident id -> Ident0.name id
-	      | Path.Pdot (_, name, _) -> name
-	      | Path.Papply _ -> assert false
-	    in
-	    let base = base_ident path in
-	    List.iter (function
-	      | { Regioned.region; value= Annot.Use (k', path'); _; } when k = k' && base = base_ident path' ->
-		  begin match query_by_kind_path file k' path' with
-		  | Some found_path' when found_path = found_path' ->
-		      Format.eprintf "%s:%a@." 
-			pathname.Unix.path
-			(Regioned.format (fun ppf path -> Format.pp_print_string ppf (Path.name path)))
-			  { Regioned.region; value= path' }
-		  | None | Some _ -> ()
-		  end
-	      | _ -> ()) file.File.rannots
-	| _ -> ());
+      | None -> Format.printf "No query result found.@.";
+      | Some found -> find_by_kind_path k path found
     in
 
     let by_pos file pos = 
-      Format.eprintf "Searching %s:%s ...@." file.File.path (Position.to_string pos);
+      Format.eprintf "Searching %s:%s ...@." 
+	file.File.path 
+	(Position.to_string pos);
       match List.find_map_opt (function 
-	  | Annot.Str str_item -> 
-	      begin match Abstraction.ident_of_structure_item str_item with
-	      | Some v -> Some v
-	      | None -> None
-	      end
-	  | _ -> None) (query_by_pos file pos)
+	| Annot.Str str_item -> 
+	    begin match Abstraction.ident_of_structure_item str_item with
+	    | Some v -> Some (`Def v)
+	    | None -> None
+	    end
+	| Annot.Use (kind, path) -> Some (`Use (kind, path))
+	| _ -> None) (query_by_pos file pos)
       with
+      | Some (`Def (k, id)) -> by_kind_path file k (Path.Pident id)
+      | Some (`Use (k, path)) -> by_kind_path file k path
       | None -> ()
-      | Some (k, id) -> by_kind_path file k (Path.Pident id)
     in
 
-    begin match Spotconfig.spec with
-    | Spotconfig.Spec.Dump -> ()
-    | Spotconfig.Spec.Kind (k,path) -> by_kind_path file k path
-    | Spotconfig.Spec.Pos pos -> by_pos file pos
-    end
+    begin match spec with
+    | C.SearchSpec.Kind (k,path) -> by_kind_path file k path
+    | C.SearchSpec.Pos pos -> by_pos file pos
+    end;
+    bye 0
   ;;
 
-  let typecheck () =
-    let command = Sys.argv.(0) :: Spotconfig.rest_args in
+  let typecheck args =
+    let command = Sys.argv.(0) :: args in
     prerr_endline (String.concat " " command);
     Xmain.main (Array.of_list command)
   ;;
 
-  let recheck () =
-    let files = Spotconfig.rest_args in
+  let recheck files =
     let recheck mlpath =
       Debug.format "cwd: %s@." (Sys.getcwd ());
       let path = File.spot_of_file mlpath in
   ;;
 
   let main () = 
-    match Spotconfig.mode with
-    | `Query -> query ()
-    | `Typecheck -> typecheck ()
-    | `Recheck -> recheck ()
-    | `Use -> use ()
+    match C.mode with
+    | `Dump path -> ignore (load path)
+    | `Query (path, spec) -> query path spec
+    | `Typecheck args -> typecheck args
+    | `Recheck args -> recheck args
+    | `Use ((path, spec), targets)-> use path spec targets
 end
 
 let _ = Main.main ()

File ocamlspot/spotapi.ml

   let type_expr =
     let cache = TypeTable.create 107 in
     let rec f t =
-      let default t =
-        try TypeTable.find cache t with Not_found ->
-          let desc =
-            let desc = Btype.copy_type_desc f t.desc in
-            match desc with
-            | Tconstr (p, args, abbrev_memo_ref) ->
-                (* abbrev_memo_ref is ignored *)
-                Tconstr (path p, args, abbrev_memo_ref)
-            | Tobject (_, { contents = None } ) -> desc
-            | Tobject (t, { contents = Some (p, ts) }) ->
-                Tobject (t, ref (Some (path p, ts)))
-	    | Tpackage (p, strs, tys) -> 
-		Tpackage (path p, strs, tys) (* CR strs should be renamed too ? *)
-            | Tvar | Tarrow _ | Ttuple _ | Tfield _ | Tnil 
-	    | Tlink _ | Tsubst _
-	    | Tvariant _ (* row desc contains path but they are positionless *)
-            | Tpoly _ | Tunivar -> desc
-          in
-          { t with desc }
-      in
-      (* exception: printer of optional argument is bit special.
-         we cannot rename the option type *)
       let t = repr t in
-      match t.desc with
-      | Tarrow(l, ty1, ty2, comm) when Btype.is_optional l ->
-          begin match (repr ty1).desc with
-          | Tconstr(path, [ty], abbrev) when Path.same path Predef.path_option ->
-              (* we do not copy abbrev but it is ok *)
-              { t with desc =
-                  Tarrow (l, 
-		  { ty1 with desc = Tconstr(path, [f ty], abbrev) },
-                  f ty2,
-                  comm) }
-          | _ -> (* not option ? *) default t
-          end
-      | Tvariant row_desc -> (* we cannot use copy_type_desc *)
-          (* not sure ... *)
-          { t with desc = 
-	      Tvariant (Btype.copy_row f true row_desc true 
-		(f row_desc.row_more)) }
-      | _ -> default t
+      try TypeTable.find cache t with Not_found ->
+	(* We need to create the cache entry first *)
+	let t_dest = { t with desc = Tnil (* to be replaced *) } in
+	TypeTable.add cache t t_dest;
+	let default t =
+	  let desc = Btype.copy_type_desc f t.desc in
+          match desc with
+          | Tconstr (p, args, abbrev_memo_ref) ->
+              (* abbrev_memo_ref is ignored *)
+              Tconstr (path p, args, abbrev_memo_ref)
+          | Tobject (_, { contents = None } ) -> desc
+          | Tobject (t, { contents = Some (p, ts) }) ->
+              Tobject (t, ref (Some (path p, ts)))
+	  | Tpackage (p, strs, tys) -> Tpackage (path p, strs, tys) (* CR: strs should be renamed too ? *)
+          | Tvar | Tarrow _ | Ttuple _ | Tfield _ | Tnil 
+	  | Tsubst _ | Tvariant _ 
+          | Tlink _ | Tpoly _ | Tunivar -> desc
+        in
+        (* Exception: printer of optional argument is bit special.
+           We cannot rename the option type *)
+	let desc = 
+  	  match t.desc with
+  	  | Tarrow(l, ty1, ty2, comm) when Btype.is_optional l ->
+              begin match (repr ty1).desc with
+              | Tconstr(path, [ty], abbrev) when Path.same path Predef.path_option ->
+                  (* we do not copy abbrev but it is ok *)
+		  Tarrow (l, 
+  	  		  { ty1 with desc = Tconstr(path, [f ty], abbrev) },
+  	  		  f ty2,
+  	  		  comm)
+              | _ -> (* not option ? *) default t
+              end
+  	  | Tvariant row_desc -> (* we cannot use copy_type_desc *)
+              (* not sure ... *)
+  	      Tvariant (Btype.copy_row f true row_desc true 
+  			  (f row_desc.row_more))
+  	  | _ -> default t
+	in
+	t_dest.desc <- desc;
+	t_dest
     in
     f
+  ;;
 
   let value_description vdesc = 
     { vdesc with val_type = type_expr vdesc.val_type }
 module Printtyp = struct
   include Printtyp
 
-  let make_type f ?(with_pos=false) ty =
+  let make_type ppf f ?(with_pos=false) ty =
     let ty = if with_pos then TypeFix.type_expr ty else ty in
-    f ty
+    f ppf ty
 
-  let type_expr ?with_pos ppf = make_type (type_expr ppf) ?with_pos
-  let type_sch ?with_pos ppf = make_type (type_sch ppf) ?with_pos
-  let type_scheme ?with_pos ppf = make_type (type_scheme ppf) ?with_pos
+  let type_expr ?with_pos ppf = make_type ppf type_expr ?with_pos
+  let type_sch ?with_pos ppf = make_type ppf type_sch ?with_pos
+  let type_scheme ?with_pos ppf = make_type ppf type_scheme ?with_pos
   let modtype ?(with_pos=false) ppf mty = 
     let mty = if with_pos then TypeFix.module_type mty else mty in
     modtype ppf mty
     { line_column = Some (pos.pos_lnum, pos.pos_cnum - pos.pos_bol);
       bytes = Some pos.pos_cnum }
 
-  let compare p1 p2 =
-    match p1, p2 with
+  let compare p1 p2 = match p1, p2 with
     | { bytes = Some b1; _ }, { bytes = Some b2; _ } -> compare b1 b2
-    | { line_column = Some (l1,c1); _ }, { line_column = Some (l2,c2); _} ->
+    | { line_column = Some (l1,c1); _ }, { line_column = Some (l2,c2); _ } ->
 	begin match compare l1 l2 with
 	| 0 -> compare c1 c2
 	| n -> n
 
   let next = function
     | { bytes = Some b; _ } -> { bytes = Some (b + 1); line_column = None }
-    | { line_column = Some (l,c); bytes = None } ->
+    | { line_column = Some (l,c); bytes = None; } ->
         { line_column = Some (l, c+1); bytes = None }
     | _ -> assert false
 
       { region = r12; value = v }) 
 
   let format f ppf { region = r; value = v } =
-    Format.fprintf ppf "@[<2>%s:@ %a@]" 
+    Format.fprintf ppf "@[<2>%s: %a@]" 
       (Region.to_string r) 
       f v
 end

File ocamlspot/spotapi.mli

 
   (* functions from the original *)
   val flatten : t -> string list
-  val last : t -> string
+  (* val last : t -> string 3.12 *)
   val parse : string -> t
 
 end
 end
 
 module Ident : sig
-  include module type of Ident with type t = Ident.t
+  type t = Ident.t
   val name : t -> Name.t
   val unsafe_create_with_stamp : ?flags:int -> string -> int -> t
     (** create an ident with given flags and stamp *)
   val parse : Name.t -> t
+
+  (* from the original *)    
+  val global: t -> bool
 end
 
 module Path : sig
 
   val reset : unit -> unit
   val mark_loops : Types.type_expr -> unit
-  val type_expr : formatter -> Types.type_expr -> unit
-  val type_scheme : formatter -> Types.type_expr -> unit
   val reset_names : unit -> unit
   val type_expr :
     ?with_pos:bool -> formatter -> Types.type_expr -> unit

File ocamlspot/spotconfig.ml

 (*                                                                     *)
 (***********************************************************************)
 
+(* Versions and command line options *)
+
 open Format
 open Utils
 
 let print_version () =
   Format.eprintf "ocamlspot %s@." version
     
-let spec = ref None
+let rev_anonargs = ref []
 let dump_file = ref false
 let dump_rannots = ref false
 let dump_tree = ref false
 let strict_time_stamp = ref false
 let print_file_info = ref false
 let print_interface = ref false
-let mode = ref `Query
 let rest_args_rev = ref []
 
 let _ = 
       "--interface", Arg.Set print_interface, 
       "\t: show the interface rather than the definition (experimental)";
 
-      (* CR: --compile and no arg after does not turn mode = `Typecheck *) 
-      "--typecheck", 
-      Arg.Rest (fun s -> 
-	  mode := `Typecheck;
-	  rest_args_rev := s :: !rest_args_rev), 
-      "<ocamlc options and arguments> \t: type check mode (experimental)";
-
-      "--recheck", 
-      Arg.Rest (fun s -> 
-	  mode := `Recheck;
-	  rest_args_rev := s :: !rest_args_rev), 
-      "<files> \t: re-type check mode (experimental)";
-
-      "--use", Arg.Unit (fun () -> mode := `Use), "\t: search uses";
-
       "--debug", Arg.Set Debug.on, "\t: print debug information";
       "-debug", Arg.Set Debug.on, "\t: (deprecated)";
       "--dump-file", Arg.Set dump_file, "\t: dump spot file"; 
       "--dump-flat", Arg.Set dump_flat, "\t: dump flat"; 
       "--eager-dump", Arg.Set eager_dump, "\t: eager evaluation at dump";
     ]
-    (fun s -> 
-      match !spec with
-      | Some _ -> failwith "you can specify only one search"
-      | None -> spec := Some s)
+    (fun s -> rev_anonargs := s :: !rev_anonargs)
     (Printf.sprintf 
-        "ocamlspot search\nversion %s\n\
-search ::= file | file:pos | file:kind:path\n\
-pos ::= l<line>c<column> | b<bytes>\n\
-kind ::= v|t|e|m|mt|c|ct"
+        "ocamlspot version %s\n\
+\n\
+Synopsis:\n\
+\tDefinition query:\n\
+\t\tocamlspot <search>\n\
+\t\tocamlspot query <search>\n\
+\n\
+\tUse query:\n\
+\t\tocamlspot use <search> <targets>\n\
+\n\
+\tType check and spot creation:\n\
+\t\tocamlspot typecheck <args>\n\
+\n\
+\tRetype check and spot recreation:\n\
+\t\tocamlspot recheck <targets>\n\
+\n\
+\t<search> ::= <file> | <file>:<pos> | <file>:<kind>:<path>\n\
+\t<pos> ::= l<line>c<column> | b<bytes>\n\
+\t<kind> ::= v|t|e|m|mt|c|ct\n\
+\n\
+Options:"
         version)
 
 let dump_file = !dump_file
 let strict_time_stamp = !strict_time_stamp
 let print_file_info = !print_file_info
 let print_interface = !print_interface
-let mode = !mode
-let rest_args = List.rev !rest_args_rev
 
 let dump_any = 
   dump_file || dump_rannots || dump_tree || dump_top || dump_flat
 
-module Spec = struct
+module SearchSpec = struct
   type t = 
       | Pos of Position.t
       | Kind of Kind.t * Path.t
-      | Dump
 
-  let parse s =
+  let parse s : string * t =
     try
       let at = String.rindex s ':' in
       try
         String.sub s 0 at2,
         Kind 
           (Kind.from_string (String.sub s (at2+1) (at-at2-1)),
-         let s = String.sub s (at+1) (String.length s - at - 1) in 
-         try Path.parse s with
-         | _ -> failwith ("illegal path: " ^ s))
+           let s = String.sub s (at+1) (String.length s - at - 1) in 
+           try Path.parse s with
+           | _ -> failwith ("illegal path: " ^ s))
       with
       | Invalid_argument _ | Not_found -> 
           String.sub s 0 at,
           Pos 
-            (Position.parse 
-                (String.sub s (at+1) (String.length s - at - 1)))
+		  (Position.parse 
+                     (String.sub s (at+1) (String.length s - at - 1)))
     with
     | Failure s -> failwith s
     | Position.Parse_failure s -> failwith ("illegal file:pos: " ^ s)
-    | Not_found -> s, Dump
+    | Not_found -> failwith ("strange search spec: " ^ s)
 
   let to_string = function
     | Pos pos -> ":" ^ Position.to_string pos
         Printf.sprintf ":%s:%s"
           (String.capitalize (Kind.to_string k))
           (Path.name path)
-    | Dump -> ""
 end
 
-let mlpath, spec =
-  match mode with
-  | `Typecheck | `Recheck -> "", Spec.Dump (* CR: dummy value *)
-  | `Query | `Use -> 
-	match !spec with
-	| None -> exit 0
-	| Some s when dump_any -> s, Spec.Dump
-	| Some s -> Spec.parse s
+let rest_args = List.rev !rest_args_rev
+let anonargs = List.rev !rev_anonargs
+
+let mode = 
+  if dump_any then begin 
+    match anonargs with
+    | [ spec ] -> `Dump spec
+    | _ -> failwith "You cannot specify mode with --dump"
+  end else begin
+    Debug.format "anonargs = [%a]@." 
+      (Format.list " " Format.pp_print_string) 
+      anonargs;
+    match anonargs with
+    | [ "query"; spec ] -> `Query (SearchSpec.parse spec)
+    | "use" :: spec :: targets -> `Use (SearchSpec.parse spec, targets)
+    | "typecheck" :: rest -> `Typecheck rest
+    | "recheck" :: rest -> `Recheck rest
+    | [ spec ] -> `Query (SearchSpec.parse spec)
+    | _ -> failwith "At most one search spec is allowed"
+  end

File ocamlspot/spotconfig.mli

+include Spotconfig_intf.S
+(*
 val app_version : string
 
 val version : string
 
 val print_file_info : bool
 val print_interface : bool
-val mode : [ `Query | `Recheck | `Typecheck | `Use ]
-val rest_args : string list
 
-module Spec : sig
+module SearchSpec : sig
   type t =
     | Pos of Spotapi.Position.t
     | Kind of Spotapi.Kind.t * Spotapi.Path.t
-    | Dump
   val parse : string -> string * t
   val to_string : t -> string
 end
 
-(* Search criteria *)
-val mlpath : string
-val spec : Spec.t
-
+val mode : [ `Dump of string
+           | `Query of string * SearchSpec.t
+	   | `Use of (string * SearchSpec.t) * string list
+	   | `Recheck of string list
+	   | `Typecheck of string list ]
+*)

File ocamlspot/spotconfig_intf.ml

+module type S = sig
+  val app_version : string
+  
+  val version : string
+  val print_version : unit -> unit
+  
+  val dump_file : bool
+  val dump_rannots : bool
+  val dump_tree : bool
+  val dump_top : bool
+  val dump_flat : bool
+  val dump_any : bool
+  val eager_dump : bool
+  
+  val no_definition_analysis : bool
+  
+  val strict_time_stamp : bool
+  
+  val print_file_info : bool
+  val print_interface : bool
+  
+  module SearchSpec : sig
+    type t =
+      | Pos of Spotapi.Position.t
+      | Kind of Spotapi.Kind.t * Spotapi.Path.t
+    val parse : string -> string * t
+    val to_string : t -> string
+  end
+  
+  val mode : [ `Dump of string
+             | `Query of string * SearchSpec.t
+  	   | `Use of (string * SearchSpec.t) * string list
+  	   | `Recheck of string list
+  	   | `Typecheck of string list ]
+end
+

File ocamlspot/spoteval.ml

 open Format
 open Utils
 
+(* To avoid name collisions *)
+module OCaml = struct
+  module Format = Format
+end
+
 (* Keep the original modules *)
 module Ident0 = Ident
 
   end
 
   module Format : sig
-    include module type of Format
+    (* include module type of Format 3.12 *)
     val t : formatter -> t -> unit
     val env : formatter -> env -> unit
     val binding : formatter -> binding -> unit
     load_paths : string list;
     binding : Binding.t;
   } 
-  let format = Format.env
+  let format = Value.Format.env
   let domain t = Binding.domain t.binding
   let find t id = Binding.find t.binding id
   let override t v = { t with binding = Binding.override t.binding v }
 
   open Abstraction
   open Value
+  module Format = OCaml.Format
 
   let str_of_global_ident = ref (fun ~load_paths:_ _ -> assert false : load_paths: string list -> Ident.t -> string * Value.structure)
   let packed = ref (fun _ _ -> assert false : Env.t -> string -> Value.t)
             in
             Debug.format "@[<2>LOAD SUCCESS %s =@ %a@]@."
               (Ident.name id)
-              Format.t str;
+              Value.Format.t str;
             str
           with
           | e -> 

File ocamlspot/spotfile.ml

 open Spotapi
 open Spoteval
     
-module Make(Spotconfig : module type of Spotconfig) = struct
+module Make(Spotconfig : Spotconfig_intf.S) = struct
   include Spot.File
 
   type file = {
       (match file.path with 
       | "" -> "NONE"
       | s -> s)
-        file.cwd
-        (Format.list "; " (fun ppf s -> Format.fprintf ppf "%S" s)) file.load_paths
+      file.cwd
+      (Format.list "; " (fun ppf s -> Format.fprintf ppf "%S" s)) file.load_paths
       (fst file.version) (snd file.version)
-        (Format.list "; " (fun ppf s -> Format.fprintf ppf "%S" s)) (Array.to_list file.argv)
+      (Format.list "; " (fun ppf s -> Format.fprintf ppf "%S" s)) (Array.to_list file.argv)
 
   (* xxx.{ml,cmo,cmx,spot} => xxx.spot 
      xxx.{mli,cmi,spit} => xxx.spit

File ocamlspot/spotfile.mli

 open Spotapi
 open Spoteval
 
-module Make( Spotconfig : module type of Spotconfig ) : sig
+module Make( Spotconfig : Spotconfig_intf.S ) : sig
 
-  type elem = Spot.File.elem =
-		| Argv of string array
-		| Source_path of string option
-		| Cwd of string
-		| Load_paths of string list
-		| Top of Abstraction.structure option
-		| Annots of (Location.t * Annot.t) list
+  type elem = 
+      Spot.File.elem =
+    | Argv of string array
+    | Source_path of string option
+    | Cwd of string
+    | Load_paths of string list
+    | Top of Abstraction.structure option
+    | Annots of (Location.t * Annot.t) list
 
   val dump : source: string option -> string -> unit
   val dump_package : prefix: string -> source: string -> string list -> unit

File ocamlspot/tests/.depend

 bigmodtest.cmi: target.cmo
+class.cmi:
+class2.cmi:
 open_in_mli.cmi: target.cmo
 siginclude.cmi:
 siginclude2.cmi:
 module_alias_ext.cmx: module_alias.cmx
 module_and_modtype.cmo:
 module_and_modtype.cmx:
+module_and_modtype2.cmo: module_and_modtype.cmo
+module_and_modtype2.cmx: module_and_modtype.cmx
 module_type.cmo:
 module_type.cmx:
 module_use.cmo:
 module_use.cmx:
 multiple_definition.cmo:
 multiple_definition.cmx:
+object.cmo:
+object.cmx:
+ocaml312.cmo:
+ocaml312.cmx:
 open.cmo: target.cmo
 open.cmx: target.cmx
 open_pack.cmo: packed.cmo
 packed.cmx:
 packed_alias.cmo:
 packed_alias.cmx:
+pathname.cmo:
+pathname.cmx:
 perv.cmo:
 perv.cmx:
 primitive.cmo:
 set_field.cmx:
 signature.cmo:
 signature.cmx:
+subpath.cmo:
+subpath.cmx:
 target.cmo:
 target.cmx:
 test.cmo:

File ocamlspot/tests/Makefile.targets

 module_alias.cmo \
 module_alias_ext.cmo \
 module_and_modtype.cmo \
+module_and_modtype2.cmo \
 module_type.cmo \
 module_use.cmo \
 multiple_definition.cmo \

File ocamlspot/tests/auto-test.pl

 
 	while(<IN>){
             my $result;
-            if( /^Spot: (.*):all/ ){ # whole file
+            if( /^Spot: <(.*):all>/ ){ # whole file
                 $tested = 1;
                 $message = "$message$&\n";
                 $result = check_file_head($1);
             }
-	    if( /^Spot: (.*):l[0-9]+c[0-9]+b([0-9]+):l[0-9]+c[0-9]+b([0-9]+)$/ ){
+	    if( /^Spot: <(.*):l[0-9]+c[0-9]+b([0-9]+):l[0-9]+c[0-9]+b([0-9]+)>$/ ){
 		$tested = 1;
 		$message = "$message$&\n";
 		$result = check_result($1, $2, $3);

File ocamlspot/tests/module_and_modtype2.ml

+module F(O : Module_and_modtype.O.M (* ? O.M *) ) = struct
+end

File ocamlspot/tests/ocamlspot.sh

File contents unchanged.

File ocamlspot/tests_use/Makefile

+include ../../config/Makefile
+
+# Various commands and dir
+##########################
+CAMLRUN=../../boot/ocamlrun
+OCAMLC   = ../../ocamlcomp.sh -annot
+OCAMLOPT = ../../ocamlcompopt.sh
+OCAMLDEP = $(CAMLRUN) ../../tools/ocamldep
+OCAMLLEX = $(CAMLRUN) ../../boot/ocamllex
+OCAMLYACC= ../../boot/ocamlyacc
+OCAMLLIB = $(LIBDIR)
+OCAMLBIN = $(BINDIR)
+
+# Compilation
+#############
+OCAMLSRCDIR=..
+INCLUDES_DEP=-I $(OCAMLSRCDIR)/parsing \
+	-I $(OCAMLSRCDIR)/utils \
+	-I $(OCAMLSRCDIR)/typing \
+	-I $(OCAMLSRCDIR)/driver \
+	-I $(OCAMLSRCDIR)/bytecomp \
+	-I $(OCAMLSRCDIR)/tools \
+	-I $(OCAMLSRCDIR)/toplevel/ \
+	-I dir1 -I dir2
+
+OTHERS=../../otherlibs
+
+# Requires unix!
+COMPFLAGS= $(INCLUDES_DEP) -I $(OTHERS)/unix
+
+include Makefile.targets
+
+all: $(TARGETS) 
+
+clean:
+	rm -f *.cm* *.o *.annot *.sp*t  */*.cm* */*.annot */*.sp*t
+
+# generic rules :
+#################
+
+.SUFFIXES: .mll .mly .ml .mli .cmo .cmi .cmx
+
+.ml.cmo:
+	$(OCAMLC) $(OCAMLPP) $(COMPFLAGS) -c $<
+
+.mli.cmi:
+	$(OCAMLC) $(OCAMLPP) $(COMPFLAGS) -c $<
+
+.ml.cmx:
+	$(OCAMLOPT) $(OCAMLPP) $(COMPFLAGS) -c $<
+
+.mll.ml:
+	$(OCAMLLEX) $<
+
+.mly.ml:
+	$(OCAMLYACC) -v $<
+
+.mly.mli:
+	$(OCAMLYACC) -v $<
+
+beforedepend::
+
+depend: beforedepend
+	$(CAMLRUN) ../../tools/ocamldep $(INCLUDES) -I dir1 -I dir2 *.mli *.ml */*.mli */*.ml > .depend
+
+Makefile.targets: *.ml *.mli
+	echo TARGETS= \\ > $@
+	ls *.ml *.mli | sed -e 's/mli$$/cmi/' -e 's/ml$$/cmo/' -e 's/$$/ \\/'	 >> $@
+
+.PHONY: clean install installopt beforedepend depend
+
+include .depend

File ocamlspot/tests_use/Makefile.targets

+TARGETS= \
+dummy.cmi \
+test1.cmo \
+test2.cmo \

File ocamlspot/utils.ml

 
   let prune () = raise Prune
 
-  let find ~f fname =
+  let find ~f fnames =
 
     (* visited cache *)
     let visited = ref Inodes.empty in
     and find_non_dir path = try f path with Prune -> ()
     in
 
-    let path = 
-      path ~depth: 0 ~dir:(Filename.dirname fname) (Filename.basename fname)
-    in
-    if is_dir path then find_dir path
-    else find_non_dir path
+    List.iter (fun fname ->
+      let path = 
+	path ~depth: 0 ~dir:(Filename.dirname fname) (Filename.basename fname)
+      in
+      if is_dir path then find_dir path
+      else find_non_dir path) fnames
   ;;
 end