@@ -463,54 +463,55 @@ module Decls = struct
463463 MH. add name {decl = (params, body); instances = MTY. empty} ! decls
464464
465465 let body name args =
466+ let {decl = (params, body); instances} = MH. find name ! decls in
466467 try
467- let {decl = (params, body); instances} = MH. find name ! decls in
468- try
469- if compare_list params args = 0 then body
470- else MTY. find args instances
471- (* should I instantiate if not found ?? *)
472- with Not_found ->
473- let params, body = fresh_type params body in
474- (* if true || get_debug_adt () then*)
475- let sbt =
476- try
477- List. fold_left2
478- (fun sbt vty ty ->
479- let vty = shorten vty in
480- match vty with
481- | Tvar { value = Some _ ; _ } -> assert false
482- | Tvar {v ; value = None } ->
483- if equal vty ty then sbt else M. add v ty sbt
484- | _ ->
485- Printer. print_err " vty = %a and ty = %a"
486- print vty print ty;
487- assert false
488- )M. empty params args
489- with Invalid_argument _ -> assert false
490- in
491- let body = match body with
492- | Adt cases ->
493- Adt (
494- List. map
495- (fun {constr; destrs} ->
496- {constr;
497- destrs =
498- List. map (fun (d , ty ) -> d, apply_subst sbt ty) destrs }
499- ) cases
500- )
501- in
502- let params = List. map (fun ty -> apply_subst sbt ty) params in
503- add name params body;
504- body
468+ if compare_list params args = 0 then body
469+ else MTY. find args instances
470+ (* should I instantiate if not found ?? *)
505471 with Not_found ->
506- Printer. print_err " %a not found" Hstring. print name;
507- assert false
472+ let params, body = fresh_type params body in
473+ (* if true || get_debug_adt () then*)
474+ let sbt =
475+ try
476+ List. fold_left2
477+ (fun sbt vty ty ->
478+ let vty = shorten vty in
479+ match vty with
480+ | Tvar { value = Some _ ; _ } -> assert false
481+ | Tvar {v ; value = None } ->
482+ if equal vty ty then sbt else M. add v ty sbt
483+ | _ ->
484+ Printer. print_err " vty = %a and ty = %a"
485+ print vty print ty;
486+ assert false
487+ )M. empty params args
488+ with Invalid_argument _ -> assert false
489+ in
490+ let body = match body with
491+ | Adt cases ->
492+ Adt (
493+ List. map
494+ (fun {constr; destrs} ->
495+ {constr;
496+ destrs =
497+ List. map (fun (d , ty ) -> d, apply_subst sbt ty) destrs }
498+ ) cases
499+ )
500+ in
501+ let params = List. map (fun ty -> apply_subst sbt ty) params in
502+ add name params body;
503+ body
508504
509505 let reinit () = decls := MH. empty
510506
511507end
512508
513- let type_body name args = Decls. body name args
509+ let type_body name args =
510+ try
511+ Decls. body name args
512+ with Not_found ->
513+ Printer. print_err " %a not found" Hstring. print name;
514+ assert false
514515
515516
516517(* smart constructors *)
@@ -524,6 +525,56 @@ let fresh_empty_text =
524525
525526let tsum s lc = Tsum (Hstring. make s, List. map Hstring. make lc)
526527
528+ (* Count the number of occurences of the nest of [name] in the signature
529+ of payload [l]. *)
530+ let count_same_nest name l =
531+ Lists. sum
532+ (fun (_ , ty ) ->
533+ match ty with
534+ | Tadt (name' , _ ) when Hstring. equal name name' -> 1
535+ | _ -> 0
536+ ) l
537+
538+ (* Count the number of occurences of the (mutually recursive) ADT type of
539+ [name] in the signature of payload [l]. *)
540+ let count_same_adt name l =
541+ Lists. sum
542+ (fun (_ , ty ) ->
543+ match ty with
544+ | Tadt (name' , params ) ->
545+ (* TODO: this is a hackish way to check that `name'` and `name` are
546+ two nests of the same mutually recursive ADT. We should store
547+ ADT's nests in a data structure as it's done in Dolmen. *)
548+ begin try
549+ let Adt cases = Decls. body name' params in
550+ List. exists
551+ (fun { destrs; _ } ->
552+ List. exists
553+ (fun (_ , ty' ) ->
554+ match ty' with
555+ | Tadt (name'' , _ ) -> Hstring. equal name name''
556+ | _ -> false
557+ ) destrs
558+ ) cases
559+ |> Bool. to_int
560+ with Not_found ->
561+ (* If we haven't already register the nest [name'], it means that
562+ [name] and [name'] are two nests of the same ADT. *)
563+ 1
564+ end
565+ | _ -> 0
566+ ) l
567+
568+ (* Comparison function used to ensure the termination of the model
569+ generation for recursive ADT values. *)
570+ let cons_weight name (_ , l1 ) (_ , l2 ) =
571+ let c = count_same_nest name l1 - count_same_nest name l2 in
572+ if c <> 0 then c
573+ else
574+ let c = count_same_adt name l1 - count_same_adt name l2 in
575+ if c <> 0 then c
576+ else List. compare_lengths l1 l2
577+
527578let t_adt ?(body =None ) s ty_vars =
528579 let hs = Hstring. make s in
529580 let ty = Tadt (hs, ty_vars) in
@@ -545,12 +596,13 @@ let t_adt ?(body=None) s ty_vars =
545596 Decls. add hs ty_vars (Adt cases)
546597 | Some cases ->
547598 let cases =
548- List. map (fun (s , l ) ->
599+ List. stable_sort (cons_weight hs) cases |>
600+ List. map (fun (c , l ) ->
549601 let l =
550602 List. map (fun (d , e ) -> Hstring. make d, e) l
551603 in
552- {constr = Hstring. make s ; destrs = l}
553- ) cases
604+ {constr = Hstring. make c ; destrs = l}
605+ )
554606 in
555607 Decls. add hs ty_vars (Adt cases)
556608 end ;
0 commit comments