X-Git-Url: http://matita.cs.unibo.it/gitweb/?a=blobdiff_plain;f=helm%2Focaml%2Fcic_notation%2FcicNotationMatcher.ml;h=7b85b96b5758845f8afff270b576e920274011ea;hb=97c2d258a5c524eb5c4b85208899d80751a2c82f;hp=8da7a483d6d4d123cfa71d8307f1926a63ce3af4;hpb=50377dde5b5b1a8e5c7b2fb48b47defde9508b50;p=helm.git diff --git a/helm/ocaml/cic_notation/cicNotationMatcher.ml b/helm/ocaml/cic_notation/cicNotationMatcher.ml index 8da7a483d..7b85b96b5 100644 --- a/helm/ocaml/cic_notation/cicNotationMatcher.ml +++ b/helm/ocaml/cic_notation/cicNotationMatcher.ml @@ -25,8 +25,9 @@ open Printf -module Pt = CicNotationPt +module Ast = CicNotationPt module Env = CicNotationEnv +module Pp = CicNotationPp module Util = CicNotationUtil type pattern_id = int @@ -34,28 +35,36 @@ type pattern_id = int exception No_match module OrderedInt = - struct +struct type t = int let compare (x1:t) (x2:t) = Pervasives.compare x2 x1 (* reverse order *) - end +end module IntSet = Set.Make (OrderedInt) let int_set_of_int_list l = List.fold_left (fun acc i -> IntSet.add i acc) IntSet.empty l +type pattern_kind = Variable | Constructor +type tag_t = int + module type PATTERN = - sig +sig type pattern_t - val compatible : pattern_t -> pattern_t -> bool - end + type term_t + val classify : pattern_t -> pattern_kind + val tag_of_pattern : pattern_t -> tag_t * pattern_t list + val tag_of_term : term_t -> tag_t * term_t list + val string_of_term: term_t -> string + val string_of_pattern: pattern_t -> string +end -module Patterns (P: PATTERN) = - struct +module Matcher (P: PATTERN) = +struct type row_t = P.pattern_t list * P.pattern_t list * pattern_id type t = row_t list - let empty = [] + let compatible p1 p2 = P.classify p1 = P.classify p2 let matched = List.map (fun (matched, _, pid) -> matched, pid) @@ -82,21 +91,22 @@ module Patterns (P: PATTERN) = (* return 2 lists of rows, first one containing homogeneous rows according * to "compatible" below *) let horizontal_split t = - let ap, first_row, t' = + let ap, first_row, t', first_row_class = match t with | [] -> assert false | (_, [], _) :: _ -> assert false (* are_empty should have been invoked in advance *) - | ((_, hd :: _ , _) as row) :: tl -> hd, row, tl + | ((_, hd :: _ , _) as row) :: tl -> hd, row, tl, P.classify hd in let rec aux prev_t = function | [] -> List.rev prev_t, [] | (_, [], _) :: _ -> assert false - | ((_, hd :: _, _) as row) :: tl when P.compatible ap hd -> + | ((_, hd :: _, _) as row) :: tl when compatible ap hd -> aux (row :: prev_t) tl | t -> List.rev prev_t, t in - aux [first_row] t' + let rows1, rows2 = aux [first_row] t' in + first_row_class, rows1, rows2 (* return 2 lists, first one representing first column, second one * representing a new pattern matrix where matched patterns have been moved @@ -107,227 +117,332 @@ module Patterns (P: PATTERN) = | decls, hd :: tl, pid -> hd :: decls, tl, pid | _ -> assert false) t - end -module T21 = + let variable_closure ksucc = + (fun matched_terms constructors terms -> +(* prerr_endline "variable_closure"; *) + match terms with + | hd :: tl -> ksucc (hd :: matched_terms) constructors tl + | _ -> assert false) + + let success_closure ksucc = + (fun matched_terms constructors terms -> +(* prerr_endline "success_closure"; *) + ksucc matched_terms constructors) + + let constructor_closure ksuccs = + (fun matched_terms constructors terms -> +(* prerr_endline "constructor_closure"; *) + match terms with + | t :: tl -> + (try + let tag, subterms = P.tag_of_term t in + let constructors' = + if subterms = [] then t :: constructors else constructors + in + let k' = List.assoc tag ksuccs in + k' matched_terms constructors' (subterms @ tl) + with Not_found -> None) + | [] -> assert false) + + let backtrack_closure ksucc kfail = + (fun matched_terms constructors terms -> +(* prerr_endline "backtrack_closure"; *) + match ksucc matched_terms constructors terms with + | Some x -> Some x + | None -> kfail matched_terms constructors terms) + + let compiler rows match_cb fail_k = + let rec aux t = + if t = [] then + (fun _ _ _ -> fail_k ()) + else if are_empty t then + success_closure (match_cb (matched t)) + else + match horizontal_split t with + | _, [], _ -> assert false + | Variable, t', [] -> variable_closure (aux (vertical_split t')) + | Constructor, t', [] -> + let tagl = + List.map + (function + | _, p :: _, _ -> fst (P.tag_of_pattern p) + | _ -> assert false) + t' + in + let clusters = partition t' tagl in + let ksuccs = + List.map + (fun (tag, cluster) -> + let cluster' = + List.map (* add args as patterns heads *) + (function + | matched_p, p :: tl, pid -> + let _, subpatterns = P.tag_of_pattern p in + matched_p, subpatterns @ tl, pid + | _ -> assert false) + cluster + in + tag, aux cluster') + clusters + in + constructor_closure ksuccs + | _, t', t'' -> backtrack_closure (aux t') (aux t'') + in + let t = List.map (fun (p, pid) -> [], [p], pid) rows in + let matcher = aux t in + (fun term -> matcher [] [] [term]) +end + +module Matcher21 = struct + module Pattern21 = + struct + type pattern_t = Ast.term + type term_t = Ast.term + let rec classify = function + | Ast.AttributedTerm (_, t) -> classify t + | Ast.Variable _ -> Variable + | Ast.Magic _ + | Ast.Layout _ + | Ast.Literal _ as t -> assert false + | _ -> Constructor + let tag_of_pattern = CicNotationTag.get_tag + let tag_of_term t = CicNotationTag.get_tag t + let string_of_term = CicNotationPp.pp_term + let string_of_pattern = CicNotationPp.pp_term + end + + module M = Matcher (Pattern21) + + let extract_magic term = + let magic_map = ref [] in + let add_magic m = + let name = Util.fresh_name () in + magic_map := (name, m) :: !magic_map; + Ast.Variable (Ast.TermVar name) + in + let rec aux = function + | Ast.AttributedTerm (_, t) -> assert false + | Ast.Literal _ + | Ast.Layout _ -> assert false + | Ast.Variable v -> Ast.Variable v + | Ast.Magic m -> add_magic m + | t -> Util.visit_ast aux t + in + let term' = aux term in + term', !magic_map -module P = Patterns (CicNotationTag) - -(* let return_closure matched = - (fun matched_terms terms -> - prerr_endline "T21.return_closure"; - match terms with - | [] -> matched_terms, matched - | _ -> assert false) *) - -let variable_closure k = - (fun matched_terms terms -> - prerr_endline "T21.variable_closure"; - match terms with - | hd :: tl -> - prerr_endline (sprintf "binding: %s" (CicNotationPp.pp_term hd)); - k (hd :: matched_terms) tl - | _ -> assert false) - -let constructor_closure ks k = - (fun matched_terms terms -> - prerr_endline "T21.constructor_closure"; - match terms with - | t :: tl -> - prerr_endline (sprintf "on term %s" (CicNotationPp.pp_term t)); - (try - let tag, subterms = CicNotationTag.get_tag t in - let k' = List.assoc tag ks in - k' matched_terms (subterms @ tl) - with Not_found -> k matched_terms terms) - | [] -> assert false) - -(* let fold_closure kind p_names names matcher success_k k = - let acc_name = try List.hd names with Failure _ -> assert false in -|+ List.iter (fun (name, _) -> Printf.printf "/// %s\n" name) p_names ; +| - (fun matched_terms terms -> - prerr_endline "T21.fold_closure"; - (match terms with - | t :: tl -> - let rec aux t = - prerr_endline "PORCA TORCIA SONO IN AUX" ; - match matcher t with - | _, [] -> None - | matched_terms, [matched_p, 0] -> Some (matched_terms, []) - | matched_terms, [matched_p, 1] -> - let acc = CicNotationEnv.lookup_term env acc_name in - let env = CicNotationEnv.remove env acc_name in - (match aux acc with - | None -> None - | Some env' -> Some (env :: env')) - | envl -> - List.iter - (fun (env, pid) -> - Printf.printf "*** %s %d\n" (CicNotationPp.pp_env env) pid) - envl ; - flush stdout ; - assert false |+ overlapping patterns, to be handled ... +| + let env_of_matched pl tl = + try + List.map2 + (fun p t -> + match p, t with + Ast.Variable (Ast.TermVar name), _ -> + name, (Env.TermType, Env.TermValue t) + | Ast.Variable (Ast.NumVar name), (Ast.Num (s, _)) -> + name, (Env.NumType, Env.NumValue s) + | Ast.Variable (Ast.IdentVar name), (Ast.Ident (s, None)) -> + name, (Env.StringType, Env.StringValue s) + | _ -> assert false) + pl tl + with Invalid_argument _ -> assert false + + let rec compiler rows = + let rows', magic_maps = + List.split + (List.map + (fun (p, pid) -> + let p', map = extract_magic p in + (p', pid), (pid, map)) + rows) + in + let magichecker map = + List.fold_left + (fun f (name, m) -> + let m_checker = compile_magic m in + (fun env ctors -> + match m_checker (Env.lookup_term env name) env ctors with + | None -> None + | Some (env, ctors) -> f env ctors)) + (fun env ctors -> Some (env, ctors)) + map + in + let magichooser candidates = + List.fold_left + (fun f (pid, pl, checker) -> + (fun matched_terms constructors -> + let env = env_of_matched pl matched_terms in + match checker env constructors with + | None -> f matched_terms constructors + | Some (env, ctors') -> + let magic_map = + try List.assoc pid magic_maps with Not_found -> assert false + in + let env' = Env.remove_names env (List.map fst magic_map) in + Some (env', ctors', pid))) + (fun _ _ -> None) + (List.rev candidates) + in + let match_cb rows = + let candidates = + List.map + (fun (pl, pid) -> + let magic_map = + try List.assoc pid magic_maps with Not_found -> assert false + in + pid, pl, magichecker magic_map) + rows + in + magichooser candidates + in + M.compiler rows' match_cb (fun _ -> None) + + and compile_magic = function + | Ast.Fold (kind, p_base, names, p_rec) -> + let p_rec_decls = Env.declarations_of_term p_rec in + (* LUCA: p_rec_decls should not contain "names" *) + let acc_name = try List.hd names with Failure _ -> assert false in + let compiled_base = compiler [p_base, 0] + and compiled_rec = compiler [p_rec, 0] in + (fun term env ctors -> + let aux_base term = + match compiled_base term with + | None -> None + | Some (env', ctors', _) -> Some (env', ctors', []) + in + let rec aux term = + match compiled_rec term with + | None -> aux_base term + | Some (env', ctors', _) -> + begin + let acc = Env.lookup_term env' acc_name in + let env'' = Env.remove_name env' acc_name in + match aux acc with + | None -> aux_base term + | Some (base_env, ctors', rec_envl) -> + let ctors'' = ctors' @ ctors in + Some (base_env, ctors'',env'' :: rec_envl) + end + in + match aux term with + | None -> None + | Some (base_env, ctors, rec_envl) -> + let env' = + base_env @ Env.coalesce_env p_rec_decls rec_envl @ env + (* @ env LUCA!!! *) + in + Some (env', ctors)) + + | Ast.Default (p_some, p_none) -> (* p_none can't bound names *) + let p_some_decls = Env.declarations_of_term p_some in + let p_none_decls = Env.declarations_of_term p_none in + let p_opt_decls = + List.filter + (fun decl -> not (List.mem decl p_none_decls)) + p_some_decls in - (match aux t with - | None -> k terms envl - | Some env -> - let magic_env = CicNotationEnv.coalesce_env p_names env in - List.map (fun (env, pid) -> magic_env @ env, pid) envl) - | [] -> assert false)) *) - -let compiler0 rows match_cb fail_k = - let rec aux t k = - if t = [] then - k - else if P.are_empty t then - match_cb (P.matched t) - else - match P.horizontal_split t with - | t', [] -> - (match t' with - | [] - | (_, [], _) :: _ -> assert false - | (_, Pt.Variable _ :: _, _) :: _ -> - variable_closure (aux (P.vertical_split t') k) - | _ -> - let tagl = - List.map - (function - | _, p :: _, _ -> fst (CicNotationTag.get_tag p) - | _ -> assert false) - t' - in - let clusters = P.partition t' tagl in - let ks = + let none_env = List.map Env.opt_binding_of_name p_opt_decls in + let compiled = compiler [p_some, 0] in + (fun term env ctors -> + match compiled term with + | None -> Some (none_env, ctors) (* LUCA: @ env ??? *) + | Some (env', ctors', 0) -> + let env' = List.map - (fun (tag, cluster) -> - let cluster' = - List.map (* add args as patterns heads *) - (function - | matched_p, p :: tl, pid -> - let _, subpatterns = CicNotationTag.get_tag p in - matched_p, subpatterns @ tl, pid - | _ -> assert false) - cluster - in - tag, aux cluster' k) - clusters + (fun (name, (ty, v)) as binding -> + if List.exists (fun (name', _) -> name = name') p_opt_decls + then Env.opt_binding_some binding + else binding) + env' in - constructor_closure ks k) - | t', tl -> aux t' (aux tl k) - in - let t = List.map (fun (p, pid) -> [], [p], pid) rows in - let matcher = aux t (fun _ _ -> fail_k ()) in - (fun term -> matcher [] [term]) - -let extract_magic term = - let magic_map = ref [] in - let add_magic m = - let name = Util.fresh_name () in - magic_map := (name, m) :: !magic_map; - Pt.Variable (Pt.TermVar name) - in - let rec aux = function - | Pt.AttributedTerm (_, t) -> aux t - | Pt.Literal _ - | Pt.Layout _ -> assert false - | Pt.Variable v -> Pt.Variable v - | Pt.Magic m -> add_magic m - | t -> Util.visit_ast aux t - in - let term' = aux term in - term', !magic_map - -let env_of_matched pl tl = - List.map2 - (fun p t -> - match p, t with - Pt.Variable (Pt.TermVar name), _ -> - name, (Env.TermType, Env.TermValue t) - | Pt.Variable (Pt.NumVar name), (Pt.Num (s, _)) -> - name, (Env.NumType, Env.NumValue s) - | Pt.Variable (Pt.IdentVar name), (Pt.Ident (s, None)) -> - name, (Env.StringType, Env.StringValue s) - | _ -> assert false) - pl tl - -let decls_of_pattern p = - List.map Env.declaration_of_var (Util.variables_of_term p) - -let rec compiler rows = - let rows', magic_maps = - List.split - (List.map - (fun (p, pid) -> - let p', map = extract_magic p in - (p', pid), (pid, map)) - rows) - in - let magichecker map = - List.fold_left - (fun f (name, m) -> - let m_checker = compile_magic m in - (fun env -> - match m_checker (Env.lookup_term env name) env with - | None -> None - | Some env' -> f env')) - (fun env -> Some env) - map - in - let magichooser candidates = - List.fold_left - (fun f (pid, pl, checker) -> - (fun matched_terms -> - let env = env_of_matched pl matched_terms in - match checker env with - | None -> f matched_terms - | Some env -> Some (env, pid))) - (fun _ -> None) - candidates - in - let match_cb rows = - prerr_endline (sprintf "match_cb on %d row(s)" (List.length rows)); - let candidates = - List.map - (fun (pl, pid) -> - let magic_map = - try List.assoc pid magic_maps with Not_found -> assert false - in - pid, pl, magichecker magic_map) - rows - in - (fun matched_terms _ -> magichooser candidates matched_terms) - in - compiler0 rows match_cb (fun _ -> None) - -and compile_magic = function - | Pt.Fold (kind, p_base, names, p_rec) -> - let p_rec_decls = decls_of_pattern p_rec in - let acc_name = try List.hd names with Failure _ -> assert false in - let t_magic = [p_base, 0; p_rec, 1] in - let compiled = compiler t_magic in - (fun term env -> - let rec aux term = - match compiled term with - | None -> None - | Some (env', 0) -> Some (env', []) - | Some (env', 1) -> - begin - let acc = Env.lookup_term env' acc_name in - let env'' = Env.remove env' acc_name in - match aux acc with - | None -> None - | Some (base_env, rec_envl) -> - Some (base_env, env'' :: rec_envl ) - end - | _ -> assert false - in - match aux term with - | None -> None - | Some (base_env, rec_envl) -> - Some (base_env @ Env.coalesce_env p_rec_decls rec_envl)) - | _ -> assert false + Some (env' @ env, ctors' @ ctors) + | _ -> assert false) + + | Ast.If (p_test, p_true, p_false) -> + let compiled_test = compiler [p_test, 0] + and compiled_true = compiler [p_true, 0] + and compiled_false = compiler [p_false, 0] in + (fun term env ctors -> + let branch = + match compiled_test term with + | None -> compiled_false + | Some _ -> compiled_true + in + match branch term with + | None -> None + | Some (env', ctors', _) -> Some (env' @ env, ctors' @ ctors)) + + | Ast.Fail -> (fun _ _ _ -> None) + + | _ -> assert false +end + +module Matcher32 = +struct + module Pattern32 = + struct + type cic_mask_t = + Blob + | Uri of UriManager.uri + | Appl of cic_mask_t list + + let uri_of_term t = CicUtil.uri_of_term (Deannotate.deannotate_term t) + + let mask_of_cic = function + | Cic.AAppl (_, tl) -> Appl (List.map (fun _ -> Blob) tl), tl + | Cic.AConst (_, _, []) + | Cic.AVar (_, _, []) + | Cic.AMutInd (_, _, _, []) + | Cic.AMutConstruct (_, _, _, _, []) as t -> Uri (uri_of_term t), [] + | _ -> Blob, [] + + let tag_of_term t = + let mask, tl = mask_of_cic t in + Hashtbl.hash mask, tl + + let mask_of_appl_pattern = function + | Ast.UriPattern uri -> Uri uri, [] + | Ast.ImplicitPattern + | Ast.VarPattern _ -> Blob, [] + | Ast.ApplPattern pl -> Appl (List.map (fun _ -> Blob) pl), pl + + let tag_of_pattern p = + let mask, pl = mask_of_appl_pattern p in + Hashtbl.hash mask, pl + type pattern_t = Ast.cic_appl_pattern + type term_t = Cic.annterm + + let string_of_pattern = GrafiteAstPp.pp_cic_appl_pattern + let string_of_term t = CicPp.ppterm (Deannotate.deannotate_term t) + + let classify = function + | Ast.ImplicitPattern + | Ast.VarPattern _ -> Variable + | Ast.UriPattern _ + | Ast.ApplPattern _ -> Constructor + end + + module M = Matcher (Pattern32) + + let compiler rows = + let match_cb rows = + let pl, pid = try List.hd rows with Not_found -> assert false in + (fun matched_terms constructors -> + let env = + try + List.map2 + (fun p t -> + match p with + | Ast.ImplicitPattern -> Util.fresh_name (), t + | Ast.VarPattern name -> name, t + | _ -> assert false) + pl matched_terms + with Invalid_argument _ -> assert false + in + Some (env, constructors, pid)) + in + M.compiler rows match_cb (fun () -> None) end