### Implement a safety-check to guarantee that recursive parametric types

```remain regular. Within their recursive definitions, parametric types
must always be instantiated with their original parameters and all
types of mutually recursive definitions must have the same parameters.

We use Tarjan's strongly connected components algorithm to group type definitions accordingly.```
parent 64b01477
 ... ... @@ -113,11 +113,18 @@ and ppat' = | Arrow of ppat * ppat | Optional of ppat | Record of bool * (label * (ppat * ppat option)) list (* Record (o, (l,(p1, p2)) list ) o : true => open record l : field label p1 : pattern expression (Optional if l=?pat ) p2 : Some p3 => else p3 *) | Constant of U.t * pexpr | Regexp of regexp | Concat of ppat * ppat | Merge of ppat * ppat and regexp = | Epsilon | Elem of ppat ... ... @@ -160,3 +167,36 @@ let rec print_re fmt e = | WeakStar (e0) -> Format.fprintf fmt "WeakStar(%a)" print_re e0 | SeqCapture (_, e0) -> Format.fprintf fmt "SeqCapture(_, %a)" print_re e0 | Arg (e0) -> Format.fprintf fmt "Arg(%a)" print_re e0 let rec pat_fold f acc p = let nacc = f acc p in match p.descr with | PatVar _ | Cst _ | NsT _ | Internal _ | Constant _ -> nacc | Recurs (p0, pl) -> List.fold_left (fun acc (_,_,pi) -> pat_fold f acc pi) (pat_fold f nacc p0) pl | Or (p1, p2) | And (p1, p2) | Diff (p1, p2) | Prod (p1, p2) | XmlT (p1, p2) | Arrow (p1, p2) | Concat (p1, p2) | Merge (p1, p2) -> pat_fold f (pat_fold f nacc p1) p2 | Optional p0 -> pat_fold f nacc p0 | Record (_, pl) -> List.fold_left (fun acc (_,(p1, op2)) -> let acc1 = pat_fold f nacc p1 in match op2 with None -> acc1 | Some p2 -> pat_fold f acc1 p2) nacc pl | Regexp e -> re_fold (fun acc e -> match e with Elem p -> pat_fold f acc p | _ -> acc) nacc e and re_fold f acc e = let nacc = f acc e in match e with | Epsilon | Elem _ | Guard _ -> nacc | Seq (e1, e2) | Alt (e1, e2) -> re_fold f (re_fold f nacc e1) e2 | Star (e0) | WeakStar (e0) | SeqCapture (_, e0) | Arg (e0) -> re_fold f nacc e0 let pat_iter f p = pat_fold (fun () p -> f p) () p let re_iter f e = re_fold (fun () e -> f e) () e