]> matita.cs.unibo.it Git - helm.git/blob - components/content_pres/termContentPres.ml
Content level representation of LetRec changed.
[helm.git] / components / content_pres / termContentPres.ml
1 (* Copyright (C) 2004-2005, HELM Team.
2  * 
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.
6  * 
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.
11  * 
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.
16  *
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,
20  * MA  02111-1307, USA.
21  * 
22  * For details, see the HELM World-Wide-Web page,
23  * http://helm.cs.unibo.it/
24  *)
25
26 (* $Id$ *)
27
28 open Printf
29
30 module Ast = CicNotationPt
31 module Env = CicNotationEnv
32
33 let debug = false
34 let debug_print s = if debug then prerr_endline (Lazy.force s) else ()
35
36 type pattern_id = int
37 type pretty_printer_id = pattern_id
38
39 let resolve_binder = function
40   | `Lambda -> "\\lambda"
41   | `Pi -> "\\Pi"
42   | `Forall -> "\\forall"
43   | `Exists -> "\\exists"
44
45 let add_level_info prec assoc t = Ast.AttributedTerm (`Level (prec, assoc), t)
46 let add_pos_info pos t = Ast.AttributedTerm (`ChildPos pos, t)
47 let left_pos = add_pos_info `Left
48 let right_pos = add_pos_info `Right
49 let inner_pos = add_pos_info `Inner
50
51 let rec top_pos t = add_level_info ~-1 Gramext.NonA (inner_pos t)
52 (*   function
53   | Ast.AttributedTerm (`Level _, t) ->
54       add_level_info ~-1 Gramext.NonA (inner_pos t)
55   | Ast.AttributedTerm (attr, t) -> Ast.AttributedTerm (attr, top_pos t)
56   | t -> add_level_info ~-1 Gramext.NonA (inner_pos t) *)
57
58 let rec remove_level_info =
59   function
60   | Ast.AttributedTerm (`Level _, t) -> remove_level_info t
61   | Ast.AttributedTerm (a, t) -> Ast.AttributedTerm (a, remove_level_info t)
62   | t -> t
63
64 let add_xml_attrs attrs t =
65   if attrs = [] then t else Ast.AttributedTerm (`XmlAttrs attrs, t)
66
67 let add_keyword_attrs =
68   add_xml_attrs (RenderingAttrs.keyword_attributes `MathML)
69
70 let box kind spacing indent content =
71   Ast.Layout (Ast.Box ((kind, spacing, indent), content))
72
73 let hbox = box Ast.H
74 let vbox = box Ast.V
75 let hvbox = box Ast.HV
76 let hovbox = box Ast.HOV
77 let break = Ast.Layout Ast.Break
78 let builtin_symbol s = Ast.Literal (`Symbol s)
79 let keyword k = add_keyword_attrs (Ast.Literal (`Keyword k))
80
81 let number s =
82   add_xml_attrs (RenderingAttrs.number_attributes `MathML)
83     (Ast.Literal (`Number s))
84
85 let ident i =
86   add_xml_attrs (RenderingAttrs.ident_attributes `MathML) (Ast.Ident (i, None))
87
88 let ident_w_href href i =
89   match href with
90   | None -> ident i
91   | Some href ->
92       let href = UriManager.string_of_uri href in
93       add_xml_attrs [Some "xlink", "href", href] (ident i)
94
95 let binder_symbol s =
96   add_xml_attrs (RenderingAttrs.builtin_symbol_attributes `MathML)
97     (builtin_symbol s)
98
99 let string_of_sort_kind = function
100   | `Prop -> "Prop"
101   | `Set -> "Set"
102   | `CProp -> "CProp"
103   | `Type _ -> "Type"
104
105 let pp_ast0 t k =
106   let rec aux =
107     function
108     | Ast.Appl ts ->
109         let rec aux_args pos =
110           function
111           | [] -> []
112           | [ last ] ->
113               let last = k last in
114               if pos = `Left then [ left_pos last ] else [ right_pos last ]
115           | hd :: tl ->
116               (add_pos_info pos (k hd)) :: aux_args `Inner tl
117         in
118         add_level_info Ast.apply_prec Ast.apply_assoc
119           (hovbox true true (CicNotationUtil.dress break (aux_args `Left ts)))
120     | Ast.Binder (binder_kind, (id, ty), body) ->
121         add_level_info Ast.binder_prec Ast.binder_assoc
122           (hvbox false true
123             [ binder_symbol (resolve_binder binder_kind);
124               k id; builtin_symbol ":"; aux_ty ty; break;
125               builtin_symbol "."; right_pos (k body) ])
126     | Ast.Case (what, indty_opt, outty_opt, patterns) ->
127         let outty_box =
128           match outty_opt with
129           | None -> []
130           | Some outty ->
131               [ keyword "return"; break; remove_level_info (k outty)]
132         in
133         let indty_box =
134           match indty_opt with
135           | None -> []
136           | Some (indty, href) -> [ keyword "in"; break; ident_w_href href indty ]
137         in
138         let match_box =
139           hvbox false false [
140            hvbox false true [
141             hvbox false true [ keyword "match"; break; top_pos (k what) ];
142             break;
143             hvbox false true indty_box;
144             break;
145             hvbox false true outty_box
146            ];
147            break;
148            keyword "with"
149          ]
150         in
151         let mk_case_pattern (head, href, vars) =
152           hbox true false (ident_w_href href head :: List.map aux_var vars)
153         in
154         let patterns' =
155           List.map
156             (fun (lhs, rhs) ->
157               remove_level_info
158                 (hvbox false true [
159                   hbox false true [
160                     mk_case_pattern lhs; builtin_symbol "\\Rightarrow" ];
161                   break; top_pos (k rhs) ]))
162             patterns
163         in
164         let patterns'' =
165           let rec aux_patterns = function
166             | [] -> assert false
167             | [ last ] ->
168                 [ break; 
169                   hbox false false [
170                     builtin_symbol "|";
171                     last; builtin_symbol "]" ] ]
172             | hd :: tl ->
173                 [ break; hbox false false [ builtin_symbol "|"; hd ] ]
174                 @ aux_patterns tl
175           in
176           match patterns' with
177           | [] ->
178               [ hbox false false [ builtin_symbol "["; builtin_symbol "]" ] ]
179           | [ one ] ->
180               [ hbox false false [
181                 builtin_symbol "["; one; builtin_symbol "]" ] ]
182           | hd :: tl ->
183               hbox false false [ builtin_symbol "["; hd ]
184               :: aux_patterns tl
185         in
186         add_level_info Ast.simple_prec Ast.simple_assoc
187           (hvbox false false [
188             hvbox false false ([match_box]); break;
189             hbox false false [ hvbox false false patterns'' ] ])
190     | Ast.Cast (bo, ty) ->
191         add_level_info Ast.simple_prec Ast.simple_assoc
192           (hvbox false true [
193             builtin_symbol "("; top_pos (k bo); break; builtin_symbol ":";
194             top_pos (k ty); builtin_symbol ")"])
195     | Ast.LetIn (var, s, t) ->
196         add_level_info Ast.let_in_prec Ast.let_in_assoc
197           (hvbox false true [
198             hvbox false true [
199               keyword "let";
200               hvbox false true [
201                 aux_var var; builtin_symbol "\\def"; break; top_pos (k s) ];
202               break; keyword "in" ];
203             break;
204             k t ])
205     | Ast.LetRec (rec_kind, funs, where) ->
206         let rec_op =
207           match rec_kind with `Inductive -> "rec" | `CoInductive -> "corec"
208         in
209         let mk_fun (args, (name,ty), body, _) =
210          List.map aux_var args ,k name, HExtlib.map_option k ty, k body in
211         let mk_funs = List.map mk_fun in
212         let fst_fun, tl_funs =
213           match mk_funs funs with hd :: tl -> hd, tl | [] -> assert false
214         in
215         let fst_row =
216           let (params, name, ty, body) = fst_fun in
217           hvbox false true ([
218             keyword "let";
219             keyword rec_op;
220             name] @
221             params @
222             (match ty with None -> [] | Some ty -> [builtin_symbol ":"; ty]) @
223             [ builtin_symbol "\\def";
224             break;
225             top_pos body ])
226         in
227         let tl_rows =
228           List.map
229             (fun (params, name, ty, body) ->
230               [ break;
231                 hvbox false true ([
232                   keyword "and";
233                   name] @
234                   params @
235                   (match ty with
236                       None -> []
237                     | Some ty -> [builtin_symbol ":"; ty]) @
238                   [ builtin_symbol "\\def"; break; body ])])
239             tl_funs
240         in
241         add_level_info Ast.let_in_prec Ast.let_in_assoc
242           ((hvbox false false
243             (fst_row :: List.flatten tl_rows
244              @ [ break; keyword "in"; break; k where ])))
245     | Ast.Implicit -> builtin_symbol "?"
246     | Ast.Meta (n, l) ->
247         let local_context l =
248             List.map (function None -> None | Some t -> Some (k t)) l
249         in
250         Ast.Meta(n, local_context l)
251     | Ast.Sort sort -> aux_sort sort
252     | Ast.Num _
253     | Ast.Symbol _
254     | Ast.Ident (_, None) | Ast.Ident (_, Some [])
255     | Ast.Uri (_, None) | Ast.Uri (_, Some [])
256     | Ast.Literal _
257     | Ast.UserInput as leaf -> leaf
258     | t -> CicNotationUtil.visit_ast ~special_k k t
259   and aux_sort sort_kind =
260     add_xml_attrs (RenderingAttrs.keyword_attributes `MathML)
261       (Ast.Ident (string_of_sort_kind sort_kind, None))
262   and aux_ty = function
263     | None -> builtin_symbol "?"
264     | Some ty -> k ty
265   and aux_var = function
266     | name, Some ty ->
267         hvbox false true [
268           builtin_symbol "("; name; builtin_symbol ":"; break; k ty;
269           builtin_symbol ")" ]
270     | name, None -> name
271   and special_k = function
272     | Ast.AttributedTerm (attrs, t) -> Ast.AttributedTerm (attrs, k t)
273     | t ->
274         prerr_endline ("unexpected special: " ^ CicNotationPp.pp_term t);
275         assert false
276   in
277   aux t
278
279   (* persistent state *)
280
281 let level1_patterns21 = Hashtbl.create 211
282
283 let compiled21 = ref None
284
285 let pattern21_matrix = ref []
286
287 let get_compiled21 () =
288   match !compiled21 with
289   | None -> assert false
290   | Some f -> Lazy.force f
291
292 let set_compiled21 f = compiled21 := Some f
293
294 let add_idrefs =
295   List.fold_right (fun idref t -> Ast.AttributedTerm (`IdRef idref, t))
296
297 let instantiate21 idrefs env l1 =
298   let rec subst_singleton pos env =
299     function
300       Ast.AttributedTerm (attr, t) ->
301         Ast.AttributedTerm (attr, subst_singleton pos env t)
302     | t -> CicNotationUtil.group (subst pos env t)
303   and subst pos env = function
304     | Ast.AttributedTerm (attr, t) ->
305 (*         prerr_endline ("loosing attribute " ^ CicNotationPp.pp_attribute attr); *)
306         subst pos env t
307     | Ast.Variable var ->
308         let name, expected_ty = CicNotationEnv.declaration_of_var var in
309         let ty, value =
310           try
311             List.assoc name env
312           with Not_found ->
313             prerr_endline ("name " ^ name ^ " not found in environment");
314             assert false
315         in
316         assert (CicNotationEnv.well_typed ty value); (* INVARIANT *)
317         (* following assertion should be a conditional that makes this
318          * instantiation fail *)
319         assert (CicNotationEnv.well_typed expected_ty value);
320         [ add_pos_info pos (CicNotationEnv.term_of_value value) ]
321     | Ast.Magic m -> subst_magic pos env m
322     | Ast.Literal l as t ->
323         let t = add_idrefs idrefs t in
324         (match l with
325         | `Keyword k -> [ add_keyword_attrs t ]
326         | _ -> [ t ])
327     | Ast.Layout l -> [ Ast.Layout (subst_layout pos env l) ]
328     | t -> [ CicNotationUtil.visit_ast (subst_singleton pos env) t ]
329   and subst_magic pos env = function
330     | Ast.List0 (p, sep_opt)
331     | Ast.List1 (p, sep_opt) ->
332         let rec_decls = CicNotationEnv.declarations_of_term p in
333         let rec_values =
334           List.map (fun (n, _) -> CicNotationEnv.lookup_list env n) rec_decls
335         in
336         let values = CicNotationUtil.ncombine rec_values in
337         let sep =
338           match sep_opt with
339             | None -> []
340             | Some l -> [ Ast.Literal l ]
341         in
342         let rec instantiate_list acc = function
343           | [] -> List.rev acc
344           | value_set :: [] ->
345               let env = CicNotationEnv.combine rec_decls value_set in
346               instantiate_list (CicNotationUtil.group (subst pos env p) :: acc)
347                 []
348           | value_set :: tl ->
349               let env = CicNotationEnv.combine rec_decls value_set in
350               let terms = subst pos env p in
351               instantiate_list (CicNotationUtil.group (terms @ sep) :: acc) tl
352         in
353         instantiate_list [] values
354     | Ast.Opt p ->
355         let opt_decls = CicNotationEnv.declarations_of_term p in
356         let env =
357           let rec build_env = function
358             | [] -> []
359             | (name, ty) :: tl ->
360                   (* assumption: if one of the value is None then all are *)
361                 (match CicNotationEnv.lookup_opt env name with
362                 | None -> raise Exit
363                 | Some v -> (name, (ty, v)) :: build_env tl)
364           in
365           try build_env opt_decls with Exit -> []
366         in
367           begin
368             match env with
369               | [] -> []
370               | _ -> subst pos env p
371           end
372     | _ -> assert false (* impossible *)
373   and subst_layout pos env = function
374     | Ast.Box (kind, tl) ->
375         let tl' = subst_children pos env tl in
376         Ast.Box (kind, List.concat tl')
377     | l -> CicNotationUtil.visit_layout (subst_singleton pos env) l
378   and subst_children pos env =
379     function
380     | [] -> []
381     | [ child ] ->
382         let pos' =
383           match pos with
384           | `Inner -> `Right
385           | `Left -> `Left
386 (*           | `None -> assert false *)
387           | `Right -> `Right
388         in
389         [ subst pos' env child ]
390     | hd :: tl ->
391         let pos' =
392           match pos with
393           | `Inner -> `Inner
394           | `Left -> `Inner
395 (*           | `None -> assert false *)
396           | `Right -> `Right
397         in
398         (subst pos env hd) :: subst_children pos' env tl
399   in
400     subst_singleton `Left env l1
401
402 let rec pp_ast1 term = 
403   let rec pp_value = function
404     | CicNotationEnv.NumValue _ as v -> v
405     | CicNotationEnv.StringValue _ as v -> v
406 (*     | CicNotationEnv.TermValue t when t == term -> CicNotationEnv.TermValue (pp_ast0 t pp_ast1) *)
407     | CicNotationEnv.TermValue t -> CicNotationEnv.TermValue (pp_ast1 t)
408     | CicNotationEnv.OptValue None as v -> v
409     | CicNotationEnv.OptValue (Some v) -> 
410         CicNotationEnv.OptValue (Some (pp_value v))
411     | CicNotationEnv.ListValue vl ->
412         CicNotationEnv.ListValue (List.map pp_value vl)
413   in
414   let ast_env_of_env env =
415     List.map (fun (var, (ty, value)) -> (var, (ty, pp_value value))) env
416   in
417 (* prerr_endline ("pattern matching from 2 to 1 on term " ^ CicNotationPp.pp_term term); *)
418   match term with
419   | Ast.AttributedTerm (attrs, term') ->
420       Ast.AttributedTerm (attrs, pp_ast1 term')
421   | _ ->
422       (match (get_compiled21 ()) term with
423       | None -> pp_ast0 term pp_ast1
424       | Some (env, ctors, pid) ->
425           let idrefs =
426             List.flatten (List.map CicNotationUtil.get_idrefs ctors)
427           in
428           let l1 =
429             try
430               Hashtbl.find level1_patterns21 pid
431             with Not_found -> assert false
432           in
433           instantiate21 idrefs (ast_env_of_env env) l1)
434
435 let load_patterns21 t =
436   set_compiled21 (lazy (Content2presMatcher.Matcher21.compiler t))
437
438 let pp_ast ast =
439   debug_print (lazy "pp_ast <-");
440   let ast' = pp_ast1 ast in
441   debug_print (lazy ("pp_ast -> " ^ CicNotationPp.pp_term ast'));
442   ast'
443
444 exception Pretty_printer_not_found
445
446 let fill_pos_info l1_pattern = l1_pattern
447 (*   let rec aux toplevel pos =
448     function
449     | Ast.Layout l ->
450         (match l 
451
452     | Ast.Magic m ->
453         Ast.Box (
454     | Ast.Variable _ as t -> add_pos_info pos t
455     | t -> t
456   in
457   aux true l1_pattern *)
458
459 let fresh_id =
460   let counter = ref ~-1 in
461   fun () ->
462     incr counter;
463     !counter
464
465 let add_pretty_printer ~precedence ~associativity l2 l1 =
466   let id = fresh_id () in
467   let l1' = add_level_info precedence associativity (fill_pos_info l1) in
468   let l2' = CicNotationUtil.strip_attributes l2 in
469   Hashtbl.add level1_patterns21 id l1';
470   pattern21_matrix := (l2', id) :: !pattern21_matrix;
471   load_patterns21 !pattern21_matrix;
472   id
473
474 let remove_pretty_printer id =
475   (try
476     Hashtbl.remove level1_patterns21 id;
477   with Not_found -> raise Pretty_printer_not_found);
478   pattern21_matrix := List.filter (fun (_, id') -> id <> id') !pattern21_matrix;
479   load_patterns21 !pattern21_matrix
480
481   (* presentation -> content *)
482
483 let unopt_names names env =
484   let rec aux acc = function
485     | (name, (ty, v)) :: tl when List.mem name names ->
486         (match ty, v with
487         | Env.OptType ty, Env.OptValue (Some v) ->
488             aux ((name, (ty, v)) :: acc) tl
489         | _ -> assert false)
490     | hd :: tl -> aux (hd :: acc) tl
491     | [] -> acc
492   in
493   aux [] env
494
495 let head_names names env =
496   let rec aux acc = function
497     | (name, (ty, v)) :: tl when List.mem name names ->
498         (match ty, v with
499         | Env.ListType ty, Env.ListValue (v :: _) ->
500             aux ((name, (ty, v)) :: acc) tl
501         | _ -> assert false)
502     | _ :: tl -> aux acc tl
503       (* base pattern may contain only meta names, thus we trash all others *)
504     | [] -> acc
505   in
506   aux [] env
507
508 let tail_names names env =
509   let rec aux acc = function
510     | (name, (ty, v)) :: tl when List.mem name names ->
511         (match ty, v with
512         | Env.ListType ty, Env.ListValue (_ :: vtl) ->
513             aux ((name, (Env.ListType ty, Env.ListValue vtl)) :: acc) tl
514         | _ -> assert false)
515     | binding :: tl -> aux (binding :: acc) tl
516     | [] -> acc
517   in
518   aux [] env
519
520 let instantiate_level2 env term =
521   let fresh_env = ref [] in
522   let lookup_fresh_name n =
523     try
524       List.assoc n !fresh_env
525     with Not_found ->
526       let new_name = CicNotationUtil.fresh_name () in
527       fresh_env := (n, new_name) :: !fresh_env;
528       new_name
529   in
530   let rec aux env term =
531 (*     prerr_endline ("ENV " ^ CicNotationPp.pp_env env); *)
532     match term with
533     | Ast.AttributedTerm (_, term) -> aux env term
534     | Ast.Appl terms -> Ast.Appl (List.map (aux env) terms)
535     | Ast.Binder (binder, var, body) ->
536         Ast.Binder (binder, aux_capture_var env var, aux env body)
537     | Ast.Case (term, indty, outty_opt, patterns) ->
538         Ast.Case (aux env term, indty, aux_opt env outty_opt,
539           List.map (aux_branch env) patterns)
540     | Ast.LetIn (var, t1, t2) ->
541         Ast.LetIn (aux_capture_var env var, aux env t1, aux env t2)
542     | Ast.LetRec (kind, definitions, body) ->
543         Ast.LetRec (kind, List.map (aux_definition env) definitions,
544           aux env body)
545     | Ast.Uri (name, None) -> Ast.Uri (name, None)
546     | Ast.Uri (name, Some substs) ->
547         Ast.Uri (name, Some (aux_substs env substs))
548     | Ast.Ident (name, Some substs) ->
549         Ast.Ident (name, Some (aux_substs env substs))
550     | Ast.Meta (index, substs) -> Ast.Meta (index, aux_meta_substs env substs)
551
552     | Ast.Implicit
553     | Ast.Ident _
554     | Ast.Num _
555     | Ast.Sort _
556     | Ast.Symbol _
557     | Ast.UserInput -> term
558
559     | Ast.Magic magic -> aux_magic env magic
560     | Ast.Variable var -> aux_variable env var
561
562     | _ -> assert false
563   and aux_opt env = function
564     | Some term -> Some (aux env term)
565     | None -> None
566   and aux_capture_var env (name, ty_opt) = (aux env name, aux_opt env ty_opt)
567   and aux_branch env (pattern, term) =
568     (aux_pattern env pattern, aux env term)
569   and aux_pattern env (head, hrefs, vars) =
570     (head, hrefs, List.map (aux_capture_var env) vars)
571   and aux_definition env (params, var, term, i) =
572     (List.map (aux_capture_var env) params, aux_capture_var env var, aux env term, i)
573   and aux_substs env substs =
574     List.map (fun (name, term) -> (name, aux env term)) substs
575   and aux_meta_substs env meta_substs = List.map (aux_opt env) meta_substs
576   and aux_variable env = function
577     | Ast.NumVar name -> Ast.Num (Env.lookup_num env name, 0)
578     | Ast.IdentVar name -> Ast.Ident (Env.lookup_string env name, None)
579     | Ast.TermVar name -> Env.lookup_term env name
580     | Ast.FreshVar name -> Ast.Ident (lookup_fresh_name name, None)
581     | Ast.Ascription (term, name) -> assert false
582   and aux_magic env = function
583     | Ast.Default (some_pattern, none_pattern) ->
584         let some_pattern_names = CicNotationUtil.names_of_term some_pattern in
585         let none_pattern_names = CicNotationUtil.names_of_term none_pattern in
586         let opt_names =
587           List.filter
588             (fun name -> not (List.mem name none_pattern_names))
589             some_pattern_names
590         in
591         (match opt_names with
592         | [] -> assert false (* some pattern must contain at least 1 name *)
593         | (name :: _) as names ->
594             (match Env.lookup_value env name with
595             | Env.OptValue (Some _) ->
596                 (* assumption: if "name" above is bound to Some _, then all
597                  * names returned by "meta_names_of" are bound to Some _ as well
598                  *)
599                 aux (unopt_names names env) some_pattern
600             | Env.OptValue None -> aux env none_pattern
601             | _ ->
602                 prerr_endline (sprintf
603                   "lookup of %s in env %s did not return an optional value"
604                   name (CicNotationPp.pp_env env));
605                 assert false))
606     | Ast.Fold (`Left, base_pattern, names, rec_pattern) ->
607         let acc_name = List.hd names in (* names can't be empty, cfr. parser *)
608         let meta_names =
609           List.filter ((<>) acc_name)
610             (CicNotationUtil.names_of_term rec_pattern)
611         in
612         (match meta_names with
613         | [] -> assert false (* as above *)
614         | (name :: _) as names ->
615             let rec instantiate_fold_left acc env' =
616               match Env.lookup_value env' name with
617               | Env.ListValue (_ :: _) ->
618                   instantiate_fold_left 
619                     (let acc_binding =
620                       acc_name, (Env.TermType, Env.TermValue acc)
621                      in
622                      aux (acc_binding :: head_names names env') rec_pattern)
623                     (tail_names names env')
624               | Env.ListValue [] -> acc
625               | _ -> assert false
626             in
627             instantiate_fold_left (aux env base_pattern) env)
628     | Ast.Fold (`Right, base_pattern, names, rec_pattern) ->
629         let acc_name = List.hd names in (* names can't be empty, cfr. parser *)
630         let meta_names =
631           List.filter ((<>) acc_name)
632             (CicNotationUtil.names_of_term rec_pattern)
633         in
634         (match meta_names with
635         | [] -> assert false (* as above *)
636         | (name :: _) as names ->
637             let rec instantiate_fold_right env' =
638               match Env.lookup_value env' name with
639               | Env.ListValue (_ :: _) ->
640                   let acc = instantiate_fold_right (tail_names names env') in
641                   let acc_binding =
642                     acc_name, (Env.TermType, Env.TermValue acc)
643                   in
644                   aux (acc_binding :: head_names names env') rec_pattern
645               | Env.ListValue [] -> aux env base_pattern
646               | _ -> assert false
647             in
648             instantiate_fold_right env)
649     | Ast.If (_, p_true, p_false) as t ->
650         aux env (CicNotationUtil.find_branch (Ast.Magic t))
651     | Ast.Fail -> assert false
652     | _ -> assert false
653   in
654   aux env term
655
656   (* initialization *)
657
658 let _ = load_patterns21 []
659