1 (* Copyright (C) 2004-2005, HELM Team.
3 * This file is part of HELM, an Hypertextual, Electronic
4 * Library of Mathematics, developed at the Computer Science
5 * Department, University of Bologna, Italy.
7 * HELM is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * HELM is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with HELM; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
22 * For details, see the HELM World-Wide-Web page,
23 * http://helm.cs.unibo.it/
29 type interpretation_id = pattern_id
30 type pretty_printer_id = pattern_id
33 { sort: (Cic.id, CicNotationPt.sort_kind) Hashtbl.t;
34 uri: (Cic.id, string) Hashtbl.t;
37 let warning s = prerr_endline ("CicNotation WARNING: " ^ s)
41 type pattern_t = CicNotationPt.cic_appl_pattern
42 let compatible ap1 ap2 =
44 | CicNotationPt.UriPattern _, CicNotationPt.UriPattern _
45 | CicNotationPt.ArgPattern _, CicNotationPt.ArgPattern _
46 | CicNotationPt.ApplPattern _, CicNotationPt.ApplPattern _ -> true
50 module Patterns32 = Patterns (Pattern32) *)
52 (* acic -> ast auxiliary function s *)
55 let o,_ = CicEnvironment.get_obj CicUniv.empty_ugraph uri in
57 | Cic.InductiveDefinition (l,_,_,_) -> l
60 let name_of_inductive_type uri i =
61 let types = get_types uri in
62 let (name, _, _, _) = try List.nth types i with Not_found -> assert false in
65 (* returns <name, type> pairs *)
66 let constructors_of_inductive_type uri i =
67 let types = get_types uri in
68 let (_, _, _, constructors) =
69 try List.nth types i with Not_found -> assert false
73 (* returns name only *)
74 let constructor_of_inductive_type uri i j =
76 fst (List.nth (constructors_of_inductive_type uri i) (j-1))
77 with Not_found -> assert false)
79 module Ast = CicNotationPt
81 let string_of_name = function
83 | Cic.Anonymous -> "_"
85 let ident_of_name n = Ast.Ident (string_of_name n, None)
87 let idref id t = Ast.AttributedTerm (`IdRef id, t)
90 prerr_endline "pp_ast0";
91 let rec aux t = CicNotationUtil.visit_ast ~special_k k t
92 and special_k = function
93 | Ast.AttributedTerm (attrs, t) -> Ast.AttributedTerm (attrs, aux t)
98 let ast_of_acic0 term_info acic k =
99 (* prerr_endline "ast_of_acic0"; *)
100 let k = k term_info in
101 let register_uri id uri = Hashtbl.add term_info.uri id uri in
104 Hashtbl.find term_info.sort id
105 with Not_found -> assert false
107 let aux_substs substs =
110 (fun (uri, annterm) -> (UriManager.name_of_uri uri, k annterm))
113 let aux_context context =
117 | Some annterm -> Some (k annterm))
121 | Cic.ARel (id,_,_,b) -> idref id (Ast.Ident (b, None))
122 | Cic.AVar (id,uri,substs) ->
123 register_uri id (UriManager.string_of_uri uri);
124 idref id (Ast.Ident (UriManager.name_of_uri uri, aux_substs substs))
125 | Cic.AMeta (id,n,l) -> idref id (Ast.Meta (n, aux_context l))
126 | Cic.ASort (id,Cic.Prop) -> idref id (Ast.Sort `Prop)
127 | Cic.ASort (id,Cic.Set) -> idref id (Ast.Sort `Set)
128 | Cic.ASort (id,Cic.Type _) -> idref id (Ast.Sort `Type)
129 | Cic.ASort (id,Cic.CProp) -> idref id (Ast.Sort `CProp)
130 | Cic.AImplicit _ -> assert false
131 | Cic.AProd (id,n,s,t) ->
133 match sort_of_id id with
134 | `Set | `Type -> `Pi
135 | `Prop | `CProp -> `Forall
137 idref id (Ast.Binder (binder_kind, (ident_of_name n, Some (k s)), k t))
138 | Cic.ACast (id,v,t) ->
139 idref id (Ast.Appl [idref id (Ast.Symbol ("cast", 0)); k v; k t])
140 | Cic.ALambda (id,n,s,t) ->
141 idref id (Ast.Binder (`Lambda, (ident_of_name n, Some (k s)), k t))
142 | Cic.ALetIn (id,n,s,t) ->
143 idref id (Ast.LetIn ((ident_of_name n, None), k s, k t))
144 | Cic.AAppl (aid,args) -> idref aid (Ast.Appl (List.map k args))
145 | Cic.AConst (id,uri,substs) ->
146 register_uri id (UriManager.string_of_uri uri);
147 idref id (Ast.Ident (UriManager.name_of_uri uri, aux_substs substs))
148 | Cic.AMutInd (id,uri,i,substs) as t ->
149 let name = name_of_inductive_type uri i in
150 let uri_str = UriManager.string_of_uri uri in
152 uri_str ^ "#xpointer(1/" ^ (string_of_int (i + 1)) ^ ")"
154 register_uri id puri_str;
155 idref id (Ast.Ident (name, aux_substs substs))
156 | Cic.AMutConstruct (id,uri,i,j,substs) ->
157 let name = constructor_of_inductive_type uri i j in
158 let uri_str = UriManager.string_of_uri uri in
159 let puri_str = sprintf "%s#xpointer(1/%d/%d)" uri_str (i + 1) j in
160 register_uri id puri_str;
161 idref id (Ast.Ident (name, aux_substs substs))
162 | Cic.AMutCase (id,uri,typeno,ty,te,patterns) ->
163 let name = name_of_inductive_type uri typeno in
164 let constructors = constructors_of_inductive_type uri typeno in
165 let rec eat_branch ty pat =
167 | Cic.Prod (_, _, t), Cic.ALambda (_, name, s, t') ->
168 let (cv, rhs) = eat_branch t t' in
169 (ident_of_name name, Some (k s)) :: cv, rhs
174 (fun (name, ty) pat ->
175 let (capture_variables, rhs) = eat_branch ty pat in
176 ((name, capture_variables), rhs))
177 constructors patterns
179 idref id (Ast.Case (k te, Some name, Some (k ty), patterns))
180 | Cic.AFix (id, no, funs) ->
183 (fun (_, n, decr_idx, ty, bo) ->
184 ((Ast.Ident (n, None), Some (k ty)), k bo, decr_idx))
189 (match List.nth defs no with
190 | (Ast.Ident (n, _), _), _, _ when n <> "_" -> n
192 with Not_found -> assert false
194 idref id (Ast.LetRec (`Inductive, defs, Ast.Ident (name, None)))
195 | Cic.ACoFix (id, no, funs) ->
198 (fun (_, n, ty, bo) -> ((Ast.Ident (n, None), Some (k ty)), k bo, 0))
203 (match List.nth defs no with
204 | (Ast.Ident (n, _), _), _, _ when n <> "_" -> n
206 with Not_found -> assert false
208 idref id (Ast.LetRec (`CoInductive, defs, Ast.Ident (name, None)))
212 (* persistent state *)
214 let level1_patterns21 = Hashtbl.create 211
215 (* let level2_patterns32 = Hashtbl.create 211 *)
217 let (compiled21: (CicNotationPt.term -> (CicNotationEnv.t * pattern_id) option)
220 (* let (compiled32: (term_info -> Cic.annterm -> CicNotationPt.term) option ref) =
223 let pattern21_matrix = ref []
224 (* let pattern32_matrix = ref Patterns32.empty *)
226 let get_compiled21 () =
227 match !compiled21 with
228 | None -> assert false
230 (* let get_compiled32 () =
231 match !compiled32 with
232 | None -> assert false
235 let set_compiled21 f = compiled21 := Some f
236 (* let set_compiled32 f = compiled32 := Some f *)
238 (* "envl" is a list of triples:
239 * <name environment, term environment, pattern id>, where
240 * name environment: (string * string) list
241 * term environment: (string * Cic.annterm) list *)
242 let return_closure success_k =
243 (fun term_info terms envl ->
244 (* prerr_endline "return_closure"; *)
248 success_k term_info (List.hd envl)
249 with Failure _ -> assert false)
252 let variable_closure names k =
253 (fun term_info terms envl ->
254 (* prerr_endline "variable_closure"; *)
259 (fun arg (name_env, term_env, pid) ->
260 let rec aux name_env term_env pid arg term =
262 Ast.IdentArg name, _ ->
263 (name_env, (name, term) :: term_env, pid)
264 | Ast.EtaArg (Some name, arg'),
265 Cic.ALambda (id, name', ty, body) ->
267 ((name, (string_of_name name', Some (ty, id))) :: name_env)
268 term_env pid arg' body
269 | Ast.EtaArg (Some name, arg'), _ ->
270 let name' = CicNotationUtil.fresh_name () in
271 aux ((name, (name', None)) :: name_env)
272 term_env pid arg' term
273 | Ast.EtaArg (None, arg'), Cic.ALambda (id, name, ty, body) ->
275 | Ast.EtaArg (None, arg'), _ ->
278 aux name_env term_env pid arg hd)
284 let appl_closure ks k =
285 (fun term_info terms envl ->
286 (* prerr_endline "appl_closure"; *)
288 | Cic.AAppl (_, args) :: tl ->
290 let k' = List.assoc (List.length args) ks in
291 k' term_info (args @ tl) envl
292 with Not_found -> k term_info terms envl)
294 | _ -> k term_info terms envl))
296 let uri_of_term t = CicUtil.uri_of_term (Deannotate.deannotate_term t)
298 let uri_closure ks k =
299 (fun term_info terms envl ->
300 (* prerr_endline "uri_closure"; *)
304 (* prerr_endline (sprintf "uri_of_term = %s" (uri_of_term hd)); *)
307 let k' = List.assoc (uri_of_term hd) ks in
310 | Invalid_argument _ (* raised by uri_of_term *)
311 | Not_found -> k term_info terms envl
314 (* compiler from level 3 to level 2 *)
315 (* let compiler32 (t: Patterns32.t) success_k fail_k =
316 let rec aux t k = |+ k is a continuation +|
319 else if Patterns32.are_empty t then begin
322 |+ XXX optimization possible here: throw away all except one of the
323 * rules which lead to ambiguity +|
324 warning "ambiguous interpretation"
326 return_closure success_k
328 match Patterns32.horizontal_split t with
332 | ([], _) :: _ -> assert false
333 | (Ast.ArgPattern (Ast.IdentArg _) :: _, _) :: _
334 | (Ast.ArgPattern (Ast.EtaArg _) :: _, _) :: _ ->
335 let first_column, t'' = Patterns32.vertical_split t' in
339 | Ast.ArgPattern arg -> arg
343 variable_closure names (aux t'' k)
344 | (Ast.ApplPattern _ :: _, _) :: _ ->
348 | (Ast.ApplPattern args) :: _, _ -> List.length args
352 |+ arity partitioning +|
353 let clusters = Patterns32.partition t' pidl in
354 let ks = |+ k continuation list +|
356 (fun (len, cluster) ->
358 List.map |+ add args as patterns heads +|
360 | (Ast.ApplPattern args) :: tl, pid ->
361 |+ let's throw away "teste di cluster" +|
370 | (Ast.UriPattern _ :: _, _) :: _ ->
372 let urimap = ref [] in
373 let uidmap = ref [] in
376 List.assoc uri !urimap
379 let uid = List.length !urimap in
380 urimap := (uri, uid) :: !urimap ;
381 uidmap := (uid, uri) :: !uidmap ;
387 | (Ast.UriPattern uri) :: _, _ -> get_uri_id uri
393 let clusters = Patterns32.partition t' pidl in
396 (fun (uid, cluster) ->
400 | (Ast.UriPattern uri) :: tl, pid -> tl, pid
404 List.assoc uid uidmap, aux cluster' k)
408 | t', tl -> aux t' (aux tl k)
410 let matcher = aux t (fun _ _ -> raise No_match) in
411 (fun term_info annterm ->
413 matcher term_info [annterm] (List.map (fun (_, pid) -> [], [], pid) t)
414 with No_match -> fail_k term_info annterm)
416 let ast_of_acic1 term_info annterm = (get_compiled32 ()) term_info annterm *)
418 let instantiate21 env pid =
419 prerr_endline "instantiate21";
420 let precedence, associativity, l1 =
422 Hashtbl.find level1_patterns21 pid
423 with Not_found -> assert false
425 let rec subst = function
426 | Ast.AttributedTerm (_, t) -> subst t
427 | Ast.Variable var ->
428 let name, expected_ty = CicNotationEnv.declaration_of_var var in
432 with Not_found -> assert false
434 assert (CicNotationEnv.well_typed ty value); (* INVARIANT *)
435 (* following assertion should be a conditional that makes this
436 * instantiation fail *)
437 assert (CicNotationEnv.well_typed expected_ty value);
438 CicNotationEnv.term_of_value value
439 | Ast.Magic _ -> assert false (* TO BE IMPLEMENTED *)
440 | Ast.Literal _ as t -> t
441 | Ast.Layout l -> Ast.Layout (subst_layout l)
442 | t -> CicNotationUtil.visit_ast subst t
443 and subst_layout l = CicNotationUtil.visit_layout subst l in
446 let rec pp_ast1 term =
447 let rec pp_value = function
448 | CicNotationEnv.NumValue _ as v -> v
449 | CicNotationEnv.StringValue _ as v -> v
450 | CicNotationEnv.TermValue t -> CicNotationEnv.TermValue (pp_ast1 t)
451 | CicNotationEnv.OptValue None as v -> v
452 | CicNotationEnv.OptValue (Some v) ->
453 CicNotationEnv.OptValue (Some (pp_value v))
454 | CicNotationEnv.ListValue vl ->
455 CicNotationEnv.ListValue (List.map pp_value vl)
457 let ast_env_of_env env =
458 List.map (fun (var, (ty, value)) -> (var, (ty, pp_value value))) env
460 match (get_compiled21 ()) term with
461 | None -> pp_ast0 term pp_ast1
462 | Some (env, pid) -> instantiate21 (ast_env_of_env env) pid
464 (* let instantiate32 term_info name_env term_env pid =
467 Hashtbl.find level2_patterns32 pid
468 with Not_found -> assert false
470 let rec instantiate_arg = function
471 | Ast.IdentArg name ->
472 (try List.assoc name term_env with Not_found -> assert false)
473 | Ast.EtaArg (None, _) -> assert false |+ TODO +|
474 | Ast.EtaArg (Some name, arg) ->
475 let (name', ty_opt) =
476 try List.assoc name name_env with Not_found -> assert false
478 let body = instantiate_arg arg in
479 let name' = Ast.Ident (name', None) in
481 | None -> Ast.Binder (`Lambda, (name', None), body)
483 idref id (Ast.Binder (`Lambda, (name', Some ty), body))
485 let args' = List.map instantiate_arg args in
486 Ast.Appl (Ast.Symbol (symbol, 0) :: args')
488 let load_patterns32 t =
489 let ast_env_of_name_env term_info name_env =
491 (fun (name, (name', ty_opt)) ->
495 | Some (annterm, id) -> Some (ast_of_acic1 term_info annterm, id)
497 (name, (name', ast_ty_opt)))
500 let ast_env_of_term_env term_info =
501 List.map (fun (name, term) -> (name, ast_of_acic1 term_info term))
503 let fail_k term_info annterm = ast_of_acic0 term_info annterm ast_of_acic1 in
504 let success_k term_info (name_env, term_env, pid) =
507 (ast_env_of_name_env term_info name_env)
508 (ast_env_of_term_env term_info term_env)
511 let compiled32 = compiler32 t success_k fail_k in
512 set_compiled32 compiled32 *)
514 let load_patterns21 t =
515 set_compiled21 (CicNotationMatcher.T21.compiler t)
517 (* let ast_of_acic id_to_sort annterm =
518 let term_info = { sort = id_to_sort; uri = Hashtbl.create 211 } in
519 let ast = ast_of_acic1 term_info annterm in
520 ast, term_info.uri *)
522 let pp_ast term = pp_ast1 term
525 let counter = ref ~-1 in
530 (* let add_interpretation (symbol, args) appl_pattern =
531 let id = fresh_id () in
532 Hashtbl.add level2_patterns32 id (symbol, args);
533 pattern32_matrix := ([appl_pattern], id) :: !pattern32_matrix;
534 load_patterns32 !pattern32_matrix;
537 let add_pretty_printer ?precedence ?associativity l2 l1 =
538 let id = fresh_id () in
539 let l2' = CicNotationUtil.strip_attributes l2 in
540 Hashtbl.add level1_patterns21 id (precedence, associativity, l1);
541 pattern21_matrix := (l2', id) :: !pattern21_matrix;
542 load_patterns21 !pattern21_matrix;
545 exception Interpretation_not_found
546 exception Pretty_printer_not_found
548 (* let remove_interpretation id =
550 Hashtbl.remove level2_patterns32 id;
551 with Not_found -> raise Interpretation_not_found);
552 pattern32_matrix := List.filter (fun (_, id') -> id <> id') !pattern32_matrix;
553 load_patterns32 !pattern32_matrix *)
555 let remove_pretty_printer id =
557 Hashtbl.remove level1_patterns21 id;
558 with Not_found -> raise Pretty_printer_not_found);
559 pattern21_matrix := List.filter (fun (_, id') -> id <> id') !pattern21_matrix;
560 load_patterns21 !pattern21_matrix
564 (* load_patterns32 [] *)