]> matita.cs.unibo.it Git - helm.git/blob - helm/software/components/ng_disambiguation/nGrafiteDisambiguator.ml
328856a0f0565bcb3d71d2863e37af60826228fe
[helm.git] / helm / software / components / ng_disambiguation / nGrafiteDisambiguator.ml
1 (*
2     ||M||  This file is part of HELM, an Hypertextual, Electronic        
3     ||A||  Library of Mathematics, developed at the Computer Science     
4     ||T||  Department, University of Bologna, Italy.                     
5     ||I||                                                                
6     ||T||  HELM is free software; you can redistribute it and/or         
7     ||A||  modify it under the terms of the GNU General Public License   
8     \   /  version 2 or (at your option) any later version.      
9      \ /   This software is distributed as is, NO WARRANTY.     
10       V_______________________________________________________________ *)
11
12 (* $Id$ *)
13
14 exception Ambiguous_input
15 exception DisambiguationError of
16  int *
17  ((Stdpp.location list * string * string) list *
18   (DisambiguateTypes.domain_item * DisambiguateTypes.codomain_item) list *
19   (Stdpp.location * string) Lazy.t * bool) list list
20   (** parameters are: option name, error message *)
21 type choose_uris_callback = id:string -> NUri.uri list -> NUri.uri list
22 type choose_interp_callback = 
23   string -> int -> (Stdpp.location list * string * string) list list -> 
24     int list
25
26 open Printf
27
28 let debug = false;;
29 let debug_print s =
30  if debug then prerr_endline (Lazy.force s);;
31
32 let mono_uris_callback ~id =
33  if Helm_registry.get_opt_default Helm_registry.get_bool ~default:true
34       "matita.auto_disambiguation"
35  then function l -> l
36  else raise Ambiguous_input
37
38 let mono_interp_callback _ _ _ = raise Ambiguous_input
39
40 let _choose_uris_callback = ref mono_uris_callback
41 let _choose_interp_callback = ref mono_interp_callback
42 let set_choose_uris_callback f = _choose_uris_callback := f
43 let set_choose_interp_callback f = _choose_interp_callback := f
44
45 module Callbacks =
46   struct
47     let interactive_user_uri_choice ~selection_mode ?ok
48           ?(enable_button_for_non_vars = true) ~title ~msg ~id uris =
49               !_choose_uris_callback ~id uris
50
51     let interactive_interpretation_choice interp =
52       !_choose_interp_callback interp
53
54     let input_or_locate_uri ~(title:string) ?id () = None
55       (* Zack: I try to avoid using this callback. I therefore assume that
56       * the presence of an identifier that can't be resolved via "locate"
57       * query is a syntax error *)
58   end
59   
60 module Disambiguator = NDisambiguate.Make (Callbacks)
61
62 let only_one_pass = ref false;;
63
64 let disambiguate_thing ~aliases ~universe
65   ~(f:?fresh_instances:bool ->
66       aliases:DisambiguateTypes.environment ->
67       universe:DisambiguateTypes.multiple_environment option ->
68       'a -> 'b)
69   ~(drop_aliases: ?minimize_instances:bool -> 'b -> 'b)
70   ~(drop_aliases_and_clear_diff: 'b -> 'b)
71   (thing: 'a)
72 =
73   assert (universe <> None);
74   let library = false, DisambiguateTypes.Environment.empty, None in
75   let multi_aliases = false, DisambiguateTypes.Environment.empty, universe in
76   let mono_aliases = true, aliases, Some DisambiguateTypes.Environment.empty in
77   let passes = (* <fresh_instances?, aliases, coercions?> *)
78    if !only_one_pass then
79     [ (true, mono_aliases, false) ]
80    else
81     [ (true, mono_aliases, false);
82       (true, multi_aliases, false);
83       (true, mono_aliases, true);
84       (true, multi_aliases, true);
85       (true, library, false); 
86         (* for demo to reduce the number of interpretations *)
87       (true, library, true);
88     ]
89   in
90   let try_pass (fresh_instances, (_, aliases, universe), insert_coercions) =
91     CicRefine.insert_coercions := insert_coercions;
92     f ~fresh_instances ~aliases ~universe thing
93   in
94   let set_aliases (instances,(use_mono_aliases,_,_),_) (_, user_asked as res) =
95    if use_mono_aliases then
96     drop_aliases ~minimize_instances:true res (* one shot aliases *)
97    else if user_asked then
98     drop_aliases ~minimize_instances:true res (* one shot aliases *)
99    else
100     drop_aliases_and_clear_diff res
101   in
102   let rec aux i errors passes =
103   debug_print (lazy ("Pass: " ^ string_of_int i));
104    match passes with
105       [ pass ] ->
106         (try
107           set_aliases pass (try_pass pass)
108          with Disambiguate.NoWellTypedInterpretation (offset,newerrors) ->
109           raise (DisambiguationError (offset, errors @ [newerrors])))
110     | hd :: tl ->
111         (try
112           set_aliases hd (try_pass hd)
113         with Disambiguate.NoWellTypedInterpretation (_offset,newerrors) ->
114          aux (i+1) (errors @ [newerrors]) tl)
115     | [] -> assert false
116   in
117   let saved_insert_coercions = !CicRefine.insert_coercions in
118   try
119     let res = aux 1 [] passes in
120     CicRefine.insert_coercions := saved_insert_coercions;
121     res
122   with exn ->
123     CicRefine.insert_coercions := saved_insert_coercions;
124     raise exn
125
126 type disambiguator_thing =
127  { do_it :
128     'a 'b.
129     aliases:DisambiguateTypes.environment ->
130     universe:DisambiguateTypes.multiple_environment option ->
131     f:(?fresh_instances:bool ->
132        aliases:DisambiguateTypes.environment ->
133        universe:DisambiguateTypes.multiple_environment option ->
134        'a -> 'b * bool) ->
135     drop_aliases:(?minimize_instances:bool -> 'b * bool -> 'b * bool) ->
136     drop_aliases_and_clear_diff:('b * bool -> 'b * bool) -> 'a -> 'b * bool
137  }
138
139 let disambiguate_thing =
140  let profiler = HExtlib.profile "disambiguate_thing" in
141   { do_it =
142      fun ~aliases ~universe ~f ~drop_aliases ~drop_aliases_and_clear_diff thing
143      -> profiler.HExtlib.profile
144          (disambiguate_thing ~aliases ~universe ~f ~drop_aliases
145            ~drop_aliases_and_clear_diff) thing
146   }
147
148 let drop_aliases ?(minimize_instances=false) (choices, user_asked) =
149  let module D = DisambiguateTypes in
150  let minimize d =
151   if not minimize_instances then
152    d
153   else
154    let rec aux =
155     function
156        [] -> []
157      | (D.Symbol (s,n),((descr,_) as ci)) as he::tl when n > 0 ->
158          if
159           List.for_all
160            (function
161                (D.Symbol (s2,_),(descr2,_)) -> s2 <> s || descr = descr2
162              | _ -> true
163            ) d
164          then
165           (D.Symbol (s,0),ci)::(aux tl)
166          else
167           he::(aux tl)
168      | (D.Num n,((descr,_) as ci)) as he::tl when n > 0 ->
169          if
170           List.for_all
171            (function (D.Num _,(descr2,_)) -> descr = descr2 | _ -> true) d
172          then
173           (D.Num 0,ci)::(aux tl)
174          else
175           he::(aux tl)
176       | he::tl -> he::(aux tl)
177    in
178     aux d
179  in
180   (List.map (fun (d, a, b, c, e) -> minimize d, a, b, c, e) choices),
181   user_asked
182
183 let drop_aliases_and_clear_diff (choices, user_asked) =
184   (List.map (fun (_, a, b, c, d) -> [], a, b, c, d) choices),
185   user_asked
186
187 let disambiguate_term ?fresh_instances ~dbd ~context ~metasenv ~subst ?goal ?initial_ugraph
188   ~aliases ~universe term
189  =
190   assert (fresh_instances = None);
191   let f =
192     Disambiguator.disambiguate_term ~dbd ~context ~metasenv ~subst ?goal ?initial_ugraph
193   in
194   disambiguate_thing.do_it ~aliases ~universe ~f ~drop_aliases
195    ~drop_aliases_and_clear_diff term
196
197 let disambiguate_obj ?fresh_instances ~dbd ~aliases ~universe ~uri obj =
198   assert (fresh_instances = None);
199   let f = Disambiguator.disambiguate_obj ~dbd ~uri in
200   disambiguate_thing.do_it ~aliases ~universe ~f ~drop_aliases
201    ~drop_aliases_and_clear_diff obj
202
203 let disambiguate_thing ~dbd = assert false