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 { sort: (Cic.id, CicNotationPt.sort_kind) Hashtbl.t;
30 uri: (Cic.id, string) Hashtbl.t;
38 let compare (x1:t) (x2:t) = Pervasives.compare x2 x1 (* reverse order *)
41 module IntSet = Set.Make (OrderedInt)
43 let int_set_of_int_list l =
44 List.fold_left (fun acc i -> IntSet.add i acc) IntSet.empty l
46 let (compiled32: (term_info -> Cic.annterm -> CicNotationPt.term) option ref) =
49 let get_compiled32 () =
50 match !compiled32 with
51 | None -> assert false
54 let set_compiled32 f = compiled32 := Some f
56 let warning s = prerr_endline ("CicNotation WARNING: " ^ s)
60 type row_t = CicNotationPt.cic_appl_pattern list * pattern_id
63 let first_column t = List.map (fun (patterns, _) -> List.hd patterns) t
64 let pattern_ids t = List.map snd t
66 let prepend_column t column =
68 List.map2 (fun elt (pl, pid) -> (elt :: pl), pid) column t
70 with Invalid_argument _ -> assert false
72 let prepend_columns t columns =
74 (fun column rows -> prepend_column rows column)
77 let partition t pidl =
78 let partitions = Hashtbl.create 11 in
79 let add pid row = Hashtbl.add partitions pid row in
82 with Invalid_argument _ -> assert false);
83 let pidset = int_set_of_int_list pidl in
86 match Hashtbl.find_all partitions pid with
88 | patterns -> (pid, List.rev patterns) :: acc)
91 let are_empty t = fst (List.hd t) = []
92 (* if first row has an empty list of patterns, then others will as well *)
94 (* return 2 lists of rows, first one containing homogeneous rows according
95 * to "compatible" below *)
96 let horizontal_split t =
97 let compatible ap1 ap2 =
99 | CicNotationPt.UriPattern _, CicNotationPt.UriPattern _
100 | CicNotationPt.ArgPattern _, CicNotationPt.ArgPattern _
101 | CicNotationPt.ApplPattern _, CicNotationPt.ApplPattern _ -> true
108 assert false (* are_empty should have been invoked in advance *)
109 | (hd :: _ , _) :: _ -> hd
111 let rec aux prev_t = function
112 | [] -> List.rev prev_t, []
113 | ([], _) :: _ -> assert false
114 | (((hd :: _), _) as row) :: tl when compatible ap hd ->
115 aux (row :: prev_t) tl
116 | t -> List.rev prev_t, t
120 (* return 2 lists, first one representing first column, second one
121 * representing rows stripped of the first element *)
122 let vertical_split t =
126 | (hd :: tl, pid) -> hd, (tl, pid)
134 let o,_ = CicEnvironment.get_obj CicUniv.empty_ugraph uri in
136 | Cic.InductiveDefinition (l,_,_,_) -> l
139 let name_of_inductive_type uri i =
140 let types = get_types uri in
141 let (name, _, _, _) = try List.nth types i with Not_found -> assert false in
144 (* returns <name, type> pairs *)
145 let constructors_of_inductive_type uri i =
146 let types = get_types uri in
147 let (_, _, _, constructors) =
148 try List.nth types i with Not_found -> assert false
152 (* returns name only *)
153 let constructor_of_inductive_type uri i j =
155 fst (List.nth (constructors_of_inductive_type uri i) (j-1))
156 with Not_found -> assert false)
158 module Ast = CicNotationPt
160 let string_of_name = function
162 | Cic.Anonymous -> "_"
164 let ident_of_name n = Ast.Ident (string_of_name n, None)
166 let ast_of_acic0 term_info acic k =
167 let k = k term_info in
168 let register_uri id uri = Hashtbl.add term_info.uri id uri in
171 Hashtbl.find term_info.sort id
172 with Not_found -> assert false
174 let idref id t = Ast.AttributedTerm (`IdRef id, t) in
175 let aux_substs substs =
178 (fun (uri, annterm) -> (UriManager.name_of_uri uri, k annterm))
181 let aux_context context =
185 | Some annterm -> Some (k annterm))
189 | Cic.ARel (id,_,_,b) -> idref id (Ast.Ident (b, None))
190 | Cic.AVar (id,uri,substs) ->
191 register_uri id (UriManager.string_of_uri uri);
192 idref id (Ast.Ident (UriManager.name_of_uri uri, aux_substs substs))
193 | Cic.AMeta (id,n,l) -> idref id (Ast.Meta (n, aux_context l))
194 | Cic.ASort (id,Cic.Prop) -> idref id (Ast.Sort `Prop)
195 | Cic.ASort (id,Cic.Set) -> idref id (Ast.Sort `Set)
196 | Cic.ASort (id,Cic.Type _) -> idref id (Ast.Sort `Type)
197 | Cic.ASort (id,Cic.CProp) -> idref id (Ast.Sort `CProp)
198 | Cic.AImplicit _ -> assert false
199 | Cic.AProd (id,n,s,t) ->
201 match sort_of_id id with
202 | `Set | `Type -> `Pi
203 | `Prop | `CProp -> `Forall
205 idref id (Ast.Binder (binder_kind, (ident_of_name n, Some (k s)), k t))
206 | Cic.ACast (id,v,t) ->
207 idref id (Ast.Appl [idref id (Ast.Symbol ("cast", 0)); k v; k t])
208 | Cic.ALambda (id,n,s,t) ->
209 idref id (Ast.Binder (`Lambda, (ident_of_name n, Some (k s)), k t))
210 | Cic.ALetIn (id,n,s,t) ->
211 idref id (Ast.LetIn ((ident_of_name n, None), k s, k t))
212 | Cic.AAppl (aid,args) -> idref aid (Ast.Appl (List.map k args))
213 | Cic.AConst (id,uri,substs) ->
214 idref id (Ast.Ident (UriManager.name_of_uri uri, aux_substs substs))
215 | Cic.AMutInd (id,uri,i,substs) ->
216 let name = name_of_inductive_type uri i in
217 idref id (Ast.Ident (name, aux_substs substs))
218 | Cic.AMutConstruct (id,uri,i,j,substs) ->
219 let name = constructor_of_inductive_type uri i j in
220 idref id (Ast.Ident (name, aux_substs substs))
221 | Cic.AMutCase (id,uri,typeno,ty,te,patterns) ->
222 let name = name_of_inductive_type uri typeno in
223 let constructors = constructors_of_inductive_type uri typeno in
224 let rec eat_branch ty pat =
226 | Cic.Prod (_, _, t), Cic.ALambda (_, name, s, t') ->
227 let (cv, rhs) = eat_branch t t' in
228 (ident_of_name name, Some (k s)) :: cv, rhs
233 (fun (name, ty) pat ->
234 let (capture_variables, rhs) = eat_branch ty pat in
235 ((name, capture_variables), rhs))
236 constructors patterns
238 idref id (Ast.Case (k te, Some name, Some (k ty), patterns))
239 | Cic.AFix (id, no, funs) ->
242 (fun (_, n, decr_idx, ty, bo) ->
243 ((Ast.Ident (n, None), Some (k ty)), k bo, decr_idx))
248 (match List.nth defs no with
249 | (Ast.Ident (n, _), _), _, _ when n <> "_" -> n
251 with Not_found -> assert false
253 idref id (Ast.LetRec (`Inductive, defs, Ast.Ident (name, None)))
254 | Cic.ACoFix (id, no, funs) ->
257 (fun (_, n, ty, bo) -> ((Ast.Ident (n, None), Some (k ty)), k bo, 0))
262 (match List.nth defs no with
263 | (Ast.Ident (n, _), _), _, _ when n <> "_" -> n
265 with Not_found -> assert false
267 idref id (Ast.LetRec (`CoInductive, defs, Ast.Ident (name, None)))
271 (* "envl" is a list of triples:
272 * <name environment, term environment, pattern id>, where
273 * name environment: (string * string) list
274 * term environment: (string * Cic.annterm) list *)
275 let return_closure success_k =
276 (fun term_info terms envl ->
280 success_k term_info (List.hd envl)
281 with Failure _ -> assert false)
284 let variable_closure names k =
285 (fun term_info terms envl ->
290 (fun arg (name_env, term_env, pid) ->
291 let rec aux name_env term_env pid arg term =
293 Ast.IdentArg name, _ ->
294 (name_env, (name, term) :: term_env, pid)
295 | Ast.EtaArg (Some name, arg'),
296 Cic.ALambda (_, name', ty, body) ->
297 aux ((name, (string_of_name name', Some ty)) :: name_env)
298 term_env pid arg' body
299 | Ast.EtaArg (Some name, arg'), _ ->
300 let name' = CicNotationUtil.fresh_name () in
301 aux ((name, (name', None)) :: name_env)
302 term_env pid arg' term
303 | Ast.EtaArg (None, arg'), Cic.ALambda (_, name, ty, body) ->
305 | Ast.EtaArg (None, arg'), _ ->
308 aux name_env term_env pid arg hd)
314 let appl_closure ks k =
315 (fun term_info terms envl ->
317 | Cic.AAppl (_, args) :: tl ->
319 let k' = List.assoc (List.length args) ks in
320 k' term_info (args @ tl) envl
321 with Not_found -> k term_info terms envl)
323 | _ -> k term_info terms envl))
325 let uri_of_term t = CicUtil.uri_of_term (Deannotate.deannotate_term t)
327 let uri_closure ks k =
328 (fun term_info terms envl ->
334 let k' = List.assoc (uri_of_term hd) ks in
337 | Invalid_argument _ (* raised by uri_of_term *)
338 | Not_found -> k term_info terms envl
341 (* compiler from level 3 to level 2 *)
342 let compiler32 (t: Patterns.t) success_k fail_k =
343 let rec aux t k = (* k is a continuation *)
346 else if Patterns.are_empty t then begin
348 | _::_::_ -> warning "Ambiguous patterns"
350 return_closure success_k
352 match Patterns.horizontal_split t with
356 | ([], _) :: _ -> assert false
357 | (Ast.ArgPattern (Ast.IdentArg _) :: _, _) :: _
358 | (Ast.ArgPattern (Ast.EtaArg _) :: _, _) :: _ ->
359 let first_column, t'' = Patterns.vertical_split t' in
363 | Ast.ArgPattern arg -> arg
367 variable_closure names (aux t'' k)
368 | (Ast.ApplPattern _ :: _, _) :: _ ->
372 | (Ast.ApplPattern args) :: _, _ -> List.length args
376 (* arity partitioning *)
377 let clusters = Patterns.partition t' pidl in
378 let ks = (* k continuation list *)
380 (fun (len, cluster) ->
382 List.map (* add args as patterns heads *)
384 | (Ast.ApplPattern args) :: tl, pid ->
385 (* let's throw away "teste di cluster" *)
394 | (Ast.UriPattern _ :: _, _) :: _ ->
396 let urimap = ref [] in
397 let uidmap = ref [] in
400 List.assoc uri !urimap
403 let uid = List.length !urimap in
404 urimap := (uri, uid) :: !urimap ;
405 uidmap := (uid, uri) :: !uidmap ;
411 | (Ast.UriPattern uri) :: _, _ -> get_uri_id uri
417 let clusters = Patterns.partition t' pidl in
420 (fun (uid, cluster) ->
424 | (Ast.UriPattern uri) :: tl, pid -> tl, pid
428 List.assoc uid uidmap, aux cluster' k)
432 | t', tl -> aux t' (aux tl k)
434 let matcher = aux t (fun _ _ -> raise No_match) in
435 (fun term_info annterm ->
437 matcher term_info [annterm] (List.map (fun (_, pid) -> [], [], pid) t)
438 with No_match -> fail_k term_info annterm)
440 let ast_of_acic1 term_info annterm = (get_compiled32 ()) term_info annterm
442 let load_patterns t instantiate =
443 let ast_env_of_name_env term_info name_env =
445 (fun (name, (name', ty_opt)) ->
449 | Some annterm -> Some (ast_of_acic1 term_info annterm)
451 (name, (name', ast_ty_opt)))
454 let ast_env_of_term_env term_info =
455 List.map (fun (name, term) -> (name, ast_of_acic1 term_info term))
457 let fail_k term_info annterm = ast_of_acic0 term_info annterm ast_of_acic1 in
458 let success_k term_info (name_env, term_env, pid) =
461 (ast_env_of_name_env term_info name_env)
462 (ast_env_of_term_env term_info term_env)
465 let compiled32 = compiler32 t success_k fail_k in
466 set_compiled32 compiled32
468 let ast_of_acic id_to_sort annterm =
469 let term_info = { sort = id_to_sort; uri = Hashtbl.create 211 } in
470 let ast = ast_of_acic1 term_info annterm in