+let domain_of_term ~context ast =
+ let rec aux loc context = function
+ | Ast.LocatedTerm (_, term) -> aux loc context term
+ | Ast.Appl terms ->
+ List.fold_left (fun dom term -> Domain.union dom (aux loc context term))
+ Domain.empty terms
+ | Ast.Appl_symbol (symb, i, args) ->
+ List.fold_left (fun dom term -> Domain.union dom (aux loc context term))
+ (Domain.singleton (Symbol (symb, i))) args
+ | Ast.Binder (_, var, typ, body) ->
+ let type_dom = aux_option loc context typ in
+ let body_dom = aux loc (var :: context) body in
+ Domain.union type_dom body_dom
+ | Ast.Case (term, indty_ident, outtype, branches) ->
+ let term_dom = aux loc context term in
+ let outtype_dom = aux_option loc context outtype in
+ let do_branch (pat, term) =
+ match pat with
+ | _ :: tl ->
+ aux loc
+ (List.fold_left (fun acc var -> (Cic.Name var) :: acc)
+ context tl)
+ term
+ | [] -> assert false
+ in
+ let branches_dom =
+ List.fold_left (fun dom branch -> Domain.union dom (do_branch branch))
+ Domain.empty branches
+ in
+ Domain.add (Id indty_ident)
+ (Domain.union outtype_dom (Domain.union term_dom branches_dom))
+ | Ast.LetIn (var, body, where) ->
+ let body_dom = aux loc context body in
+ let where_dom = aux loc (Cic.Name var :: context) where in
+ Domain.union body_dom where_dom
+ | Ast.LetRec (kind, defs, where) ->
+ let context' =
+ List.fold_left (fun acc (var, _, _, _) -> Cic.Name var :: acc)
+ context defs
+ in
+ let where_dom = aux loc context' where in
+ let defs_dom =
+ List.fold_left
+ (fun dom (_, body, typ, _) ->
+ Domain.union (aux loc context' body) (aux_option loc context typ))
+ Domain.empty defs
+ in
+ Domain.union where_dom defs_dom
+ | Ast.Ident (name, subst) ->
+ (* TODO hanlde explicit substitutions *)
+ (try
+ let index = find_in_environment name context in
+ if subst <> [] then
+ Parser.fail loc "Explicit substitutions not allowed here";
+ Domain.empty
+ with Not_found -> Domain.singleton (Id name))
+ | Ast.Num (num, i) -> Domain.singleton (Num i)
+ | Ast.Meta (index, local_context) ->
+ List.fold_left
+ (fun dom term -> Domain.union dom (aux_option loc context term))
+ Domain.empty local_context
+ | Ast.Sort _ -> Domain.empty
+ and aux_option loc context = function
+ | None -> Domain.empty
+ | Some t -> aux loc context t
+ in
+ match ast with
+ | Ast.LocatedTerm (loc, term) -> aux loc context term
+ | _ -> assert false
+
+module Make (C: Callbacks) =
+ struct
+ let choices_of_id mqi_handle id =
+ let query = MQueryGenerator.locate id in
+ let result = MQueryInterpreter.execute mqi_handle query in
+ let uris =
+ List.map
+ (function uri,_ ->
+ MQueryMisc.wrong_xpointer_format_from_wrong_xpointer_format' uri
+ ) result in
+ C.output_html (`Msg (`T "Locate query:"));
+ MQueryUtil.text_of_query
+ (fun s -> C.output_html ~append_NL:false (`Msg (`T s)))
+ "" query;
+ C.output_html (`Msg (`T "Result:"));
+ MQueryUtil.text_of_result
+ (fun s -> C.output_html (`Msg (`T s))) "" result;
+ let uris' =
+ match uris with
+ | [] ->
+ [UriManager.string_of_uri (C.input_or_locate_uri
+ ~title:("URI matching \"" ^ id ^ "\" unknown."))]
+ | [uri] -> [uri]
+ | _ ->
+ C.interactive_user_uri_choice ~selection_mode:`MULTIPLE
+ ~ok:"Try every selection." ~enable_button_for_non_vars:true
+ ~title:"Ambiguous input." ~id
+ ~msg: ("Ambiguous input \"" ^ id ^
+ "\". Please, choose one or more interpretations:")
+ uris
+ in
+ List.map
+ (fun uri -> (uri, let term = term_of_uri uri in fun _ _ _ -> term))
+ uris'
+
+ let disambiguate_term mqi_handle context metasenv term ~aliases:current_env
+ =
+ let current_dom = (* TODO temporary, remove ASAP *)
+ Environment.fold (fun item _ dom -> Domain.add item dom)
+ current_env Domain.empty
+ in
+ debug_print "NEW DISAMBIGUATE INPUT";
+ let disambiguate_context = (* cic context -> disambiguate context *)
+ List.map
+ (function None -> Cic.Anonymous | Some (name, _) -> name)
+ context
+ in
+ let term_dom = domain_of_term ~context:disambiguate_context term in
+ debug_print (sprintf "DISAMBIGUATION DOMAIN: %s"
+ (string_of_domain term_dom));
+ let todo_dom = Domain.diff term_dom current_dom in
+ (* (2) lookup function for any item (Id/Symbol/Num) *)
+ let lookup_choices =
+ let id_choices = Hashtbl.create 1023 in
+ fun item ->
+ let choices =
+ match item with
+ | Id id ->
+ (try
+ Hashtbl.find id_choices id
+ with Not_found ->
+ let choices = choices_of_id mqi_handle id in
+ Hashtbl.add id_choices id choices;
+ choices)
+ | Symbol (symb, _) ->
+ (try Hashtbl.find symbol_choices symb with Not_found -> [])
+ | Num instance -> !num_choices
+ in
+ if choices = [] then raise (No_choices item);
+ choices
+ in
+ (* (3) test an interpretation filling with meta uninterpreted identifiers
+ *)
+ let test_env current_env todo_dom =
+ let filled_env =
+ Domain.fold
+ (fun item env ->
+ Environment.add item ("Implicit", fun _ _ _ -> Cic.Implicit) env)
+ todo_dom current_env
+ in
+ try
+ let cic_term =
+ interpretate ~context:disambiguate_context ~env:filled_env term
+ in
+ refine metasenv context cic_term
+ with
+ | Try_again -> Uncertain
+ | Invalid_choice -> Ko
+ in
+ (* (4) build all possible interpretations *)
+ let rec aux current_env todo_dom =
+ if Domain.is_empty todo_dom then
+ match test_env current_env Domain.empty with
+ | Ok (term, metasenv) -> [ current_env, term, metasenv ]
+ | Ko | Uncertain -> []
+ else
+ let item = Domain.choose todo_dom in
+ let remaining_dom = Domain.remove item todo_dom in
+ debug_print (sprintf "CHOOSED ITEM: %s" (string_of_domain_item item));
+ let choices = lookup_choices item in
+ let rec filter = function
+ | [] -> []
+ | codomain_item :: tl ->
+ let new_env = Environment.add item codomain_item current_env in
+ (match test_env new_env remaining_dom with
+ | Ok (term, metasenv) ->
+ (if Domain.is_empty remaining_dom then
+ [ new_env, term, metasenv ]
+ else
+ aux new_env remaining_dom)
+ @ filter tl
+ | Uncertain ->
+ (if Domain.is_empty remaining_dom then
+ []
+ else
+ aux new_env remaining_dom)
+ @ filter tl
+ | Ko -> filter tl)
+ in
+ filter choices
+ in
+ let (choosed_env, choosed_term, choosed_metasenv) =
+ match aux current_env todo_dom with
+ | [] -> raise NoWellTypedInterpretation
+ | [ x ] ->
+ debug_print "UNA SOLA SCELTA";
+ x
+ | l ->
+ debug_print (sprintf "PIU' SCELTE (%d)" (List.length l));
+ let choices =
+ List.map
+ (fun (env, _, _) ->
+ List.map
+ (fun domain_item ->
+ let description =
+ fst (Environment.find domain_item env)
+ in
+ (descr_of_domain_item domain_item, description))
+ (Domain.elements term_dom))
+ l
+ in
+ let choosed = C.interactive_interpretation_choice choices in
+ List.nth l choosed
+ in
+ (choosed_env, choosed_metasenv, choosed_term)
+
+ end
+