Skip to content

Commit 2c6d421

Browse files
authored
Remove the Record theory (OCamlPro#1095)
This PR removes the `Record` theory, which is now handled by the ADT theory. - The context built for record definitions is still required by the matching module. We plan to remove it, but it is not easy to get rid of it. - The `xs_modulo_records` function in `Matching` is no longer useful. This PR removes it. - The test `1008/records.smt2` is now solved, but only with Tableaux.
1 parent 76deb5a commit 2c6d421

36 files changed

+150
-1120
lines changed

docs/sphinx_docs/Alt_ergo_native/05_theories.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ Alt-Ergo currently provides built-in support for the following theories.
1717
* Linear arithmetic over integers and rationals
1818
* (Fragment of) non-linear arithmetic
1919
* Floating-point arithmetic (as an extension)
20-
* Enumerated datatypes
21-
* Record datatypes
20+
* Algebraic datatypes
2221
* Polymorphic functional arrays
2322
* Fixed-size bitvectors
2423

@@ -28,7 +27,6 @@ All theories are always considered *modulo equality*.
2827
* `SUM`: Enumerated datatypes
2928
* `Adt`: Algebraic datatypes
3029
* `Arrays`: Polymorphic functional arrays
31-
* `Records`: Record datatypes
3230
* `Bitv`: Fixed-size bitvectors
3331
* `LIA`: Linear arithmetic over integers
3432
* `LRA`: Linear arithmetic over rationals

rsc/extra/subgraphs.dot

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,6 @@ subgraph cluster_lib {
141141
"Enum";
142142
"Ite";
143143
"Polynome";
144-
"Records";
145144
"Sig";
146145
}
147146

src/lib/dune

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
Ac Arith Arrays_rel Bitv Ccx Shostak Relation
5151
Fun_sat Fun_sat_frontend Inequalities Bitv_rel Th_util Adt Adt_rel
5252
Instances IntervalCalculus Intervals_intf Intervals_core Intervals
53-
Ite_rel Matching Matching_types Polynome Records Records_rel
53+
Ite_rel Matching Matching_types Polynome
5454
Satml_frontend_hybrid Satml_frontend Satml Sat_solver Sat_solver_sig
5555
Sig Sig_rel Theory Uf Use Domains Domains_intf Rel_utils Bitlist
5656
; structures

src/lib/frontend/models.ml

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ module Pp_smtlib_term = struct
4242
asprintf "%a" Ty.pp_smtlib t
4343

4444
let rec print fmt t =
45-
let {Expr.f;xs;ty; _} = Expr.term_view t in
45+
let {Expr.f;xs; _} = Expr.term_view t in
4646
match f, xs with
4747

4848
| Sy.Lit lit, xs ->
@@ -151,26 +151,6 @@ module Pp_smtlib_term = struct
151151
| Sy.Op Sy.Extract (i, j), [e] ->
152152
fprintf fmt "%a^{%d,%d}" print e i j
153153

154-
| Sy.Op (Sy.Access field), [e] ->
155-
if Options.get_output_smtlib () then
156-
fprintf fmt "(%a %a)" DE.Term.Const.print field print e
157-
else
158-
fprintf fmt "%a.%a" print e DE.Term.Const.print field
159-
160-
| Sy.Op (Sy.Record), _ ->
161-
begin match ty with
162-
| Ty.Trecord { Ty.lbs = lbs; _ } ->
163-
assert (List.length xs = List.length lbs);
164-
fprintf fmt "{";
165-
ignore (List.fold_left2 (fun first (field,_) e ->
166-
fprintf fmt "%s%a = %a" (if first then "" else "; ")
167-
DE.Term.Const.print field print e;
168-
false
169-
) true lbs xs);
170-
fprintf fmt "}";
171-
| _ -> assert false
172-
end
173-
174154
(* TODO: introduce PrefixOp in the future to simplify this ? *)
175155
| Sy.Op op, [e1; e2] when op == Sy.Pow || op == Sy.Integer_round ||
176156
op == Sy.Max_real || op == Sy.Max_int ||

src/lib/frontend/translate.ml

Lines changed: 11 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -515,85 +515,17 @@ let rec dty_to_ty ?(update = false) ?(is_var = false) dty =
515515
| _ -> unsupported "Type %a" DE.Ty.print dty
516516

517517
and handle_ty_app ?(update = false) ty_c l =
518-
(* Applies the substitutions in [tysubsts] to each encountered type
519-
variable. *)
520-
let rec apply_ty_substs tysubsts ty =
521-
match ty with
522-
| Ty.Tvar v ->
523-
Ty.TvMap.find v tysubsts
524-
525-
| Text (tyl, hs) ->
526-
Ty.Text (List.map (apply_ty_substs tysubsts) tyl, hs)
527-
528-
| Tfarray (ti, tv) ->
529-
Tfarray (
530-
apply_ty_substs tysubsts ti,
531-
apply_ty_substs tysubsts tv
532-
)
533-
534-
| Tadt (hs, tyl) ->
535-
Tadt (hs, List.map (apply_ty_substs tysubsts) tyl)
536-
537-
| Trecord ({ args; lbs; _ } as rcrd) ->
538-
Trecord {
539-
rcrd with
540-
args = List.map (apply_ty_substs tysubsts) args;
541-
lbs = List.map (
542-
fun (hs, t) ->
543-
hs, apply_ty_substs tysubsts t
544-
) lbs;
545-
}
546-
547-
| _ -> ty
548-
in
549518
let tyl = List.map (dty_to_ty ~update) l in
550519
(* Recover the initial versions of the types and apply them on the provided
551520
type arguments stored in [tyl]. *)
552521
match Cache.find_ty ty_c with
553-
| Tadt (hs, _) -> Tadt (hs, tyl)
554-
555-
| Trecord { args; _ } as ty ->
556-
let tysubsts =
557-
List.fold_left2 (
558-
fun acc tv ty ->
559-
match tv with
560-
| Ty.Tvar v -> Ty.TvMap.add v ty acc
561-
| _ -> assert false
562-
) Ty.TvMap.empty args tyl
563-
in
564-
apply_ty_substs tysubsts ty
565-
522+
| Tadt (hs, _) -> Tadt (hs, tyl )
566523
| Text (_, s) -> Text (tyl, s)
567524
| _ -> assert false
568525

569526
(** Handles a simple type declaration. *)
570527
let mk_ty_decl (ty_c: DE.ty_cst) =
571528
match DT.definition ty_c with
572-
| Some (
573-
(Adt
574-
{ cases = [| { cstr = { id_ty; _ } as cstr; dstrs; _ } |]; _ } as adt)
575-
) ->
576-
(* Records and adts that only have one case are treated in the same way,
577-
and considered as records. *)
578-
Nest.attach_orders [adt];
579-
let tyvl = Cache.store_ty_vars_ret id_ty in
580-
let lbs =
581-
Array.fold_right (
582-
fun c acc ->
583-
match c with
584-
| Some (DE.{ id_ty; _ } as id) ->
585-
let pty = dty_to_ty id_ty in
586-
(id, pty) :: acc
587-
| _ ->
588-
Fmt.failwith
589-
"Unexpected null label for some field of the record type %a"
590-
DE.Ty.Const.print ty_c
591-
592-
) dstrs []
593-
in
594-
let ty = Ty.trecord ~record_constr:cstr tyvl ty_c lbs in
595-
Cache.store_ty ty_c ty
596-
597529
| Some (Adt { cases; _ } as adt) ->
598530
Nest.attach_orders [adt];
599531
let tyvl = Cache.store_ty_vars_ret cases.(0).cstr.id_ty in
@@ -644,34 +576,10 @@ let mk_term_decl ({ id_ty; path; tags; _ } as tcst: DE.term_cst) =
644576
in
645577
(Hstring.make name, arg_tys, ret_ty)
646578

647-
(** Handles the definitions of a list of mutually recursive types.
648-
- If one of the types is an ADT, the ADTs that have only one case are
649-
considered as ADTs as well and not as records. *)
579+
(** Handles the definitions of a list of mutually recursive types. *)
650580
let mk_mr_ty_decls (tdl: DE.ty_cst list) =
651581
let handle_ty_decl (ty: Ty.t) (tdef: DE.Ty.def option) =
652582
match ty, tdef with
653-
| Trecord { args; name; record_constr; _ },
654-
Some (
655-
Adt { cases = [| { dstrs; _ } |]; ty = ty_c; _ }
656-
) ->
657-
let lbs =
658-
Array.fold_right (
659-
fun c acc ->
660-
match c with
661-
| Some (DE.{ id_ty; _ } as id) ->
662-
let pty = dty_to_ty id_ty in
663-
(id, pty) :: acc
664-
| _ ->
665-
Fmt.failwith
666-
"Unexpected null label for some field of the record type %a"
667-
DE.Ty.Const.print ty_c
668-
) dstrs []
669-
in
670-
let ty =
671-
Ty.trecord ~record_constr args name lbs
672-
in
673-
Cache.store_ty ty_c ty
674-
675583
| Tadt (hs, tyl), Some (Adt { cases; ty = ty_c; _ }) ->
676584
let cs =
677585
Array.fold_right (
@@ -693,37 +601,15 @@ let mk_mr_ty_decls (tdl: DE.ty_cst list) =
693601

694602
| _ -> assert false
695603
in
696-
(* If there are adts in the list of type declarations then records are
697-
converted to adts, because that's how it's done in the legacy typechecker.
698-
But it might be more efficient not to do that. *)
699-
let rev_tdefs, contains_adts =
700-
List.fold_left (
701-
fun (acc, ca) ty_c ->
702-
match DT.definition ty_c with
703-
| Some (Adt { record; cases; _ } as df)
704-
when not record && Array.length cases > 1 ->
705-
df :: acc, true
706-
| Some (Adt _ as df) ->
707-
df :: acc, ca
708-
| Some Abstract | None ->
709-
assert false
710-
) ([], false) tdl
711-
in
604+
let rev_tdefs = List.rev_map (fun td -> Option.get @@ DT.definition td) tdl in
712605
Nest.attach_orders rev_tdefs;
713606
let rev_l =
714607
List.fold_left (
715608
fun acc tdef ->
716609
match tdef with
717-
| DE.Adt { cases; record; ty = ty_c; } as adt ->
610+
| DE.Adt { cases; ty = ty_c; _ } as adt ->
718611
let tyvl = Cache.store_ty_vars_ret cases.(0).cstr.id_ty in
719-
let record_constr = cases.(0).cstr in
720-
let ty =
721-
if (record || Array.length cases = 1) && not contains_adts
722-
then
723-
Ty.trecord ~record_constr tyvl ty_c []
724-
else
725-
Ty.t_adt ty_c tyvl
726-
in
612+
let ty = Ty.t_adt ty_c tyvl in
727613
Cache.store_ty ty_c ty;
728614
(ty, Some adt) :: acc
729615

@@ -850,15 +736,11 @@ end = struct
850736
let mk_destr =
851737
match ty with
852738
| Ty.Tadt _ -> (fun hs -> Sy.destruct hs)
853-
| Ty.Trecord _ -> (fun hs -> Sy.Op (Sy.Access hs))
854739
| _ -> assert false
855740
in
856741
let mk_tester =
857742
match ty with
858743
| Ty.Tadt _ -> E.mk_tester
859-
| Ty.Trecord _ ->
860-
(* no need to test for records *)
861-
(fun _e _name -> assert false)
862744
| _ -> assert false
863745
in
864746
let res = compile mk_destr mk_tester e cases e in
@@ -1011,14 +893,8 @@ let rec mk_expr
1011893
E.mk_term sy [] ty
1012894

1013895
| B.Constructor _ ->
1014-
begin match dty_to_ty term_ty with
1015-
| Trecord _ as ty ->
1016-
E.mk_record [] ty
1017-
| Tadt _ as ty ->
1018-
E.mk_constr tcst [] ty
1019-
| ty ->
1020-
Fmt.failwith "unexpected type %a@." Ty.print ty
1021-
end
896+
let ty = dty_to_ty term_ty in
897+
E.mk_constr tcst [] ty
1022898

1023899
| _ -> unsupported "Constant term %a" DE.Term.print term
1024900
end
@@ -1059,10 +935,7 @@ let rec mk_expr
1059935
let e = aux_mk_expr x in
1060936
let sy =
1061937
match Cache.find_ty adt with
1062-
| Trecord _ ->
1063-
Sy.Op (Sy.Access destr)
1064-
| Tadt _ ->
1065-
Sy.destruct destr
938+
| Tadt _ -> Sy.destruct destr
1066939
| _ -> assert false
1067940
in
1068941
E.mk_term sy [e] ty
@@ -1093,11 +966,6 @@ let rec mk_expr
1093966
| Ty.Tadt _ ->
1094967
E.mk_tester cstr (aux_mk_expr x)
1095968

1096-
| Ty.Trecord _ ->
1097-
(* The typechecker allows only testers whose the
1098-
two arguments have the same type. Thus, we can always
1099-
replace the tester of a record by the true literal. *)
1100-
E.vrai
1101969
| _ -> assert false
1102970
end
1103971

@@ -1364,19 +1232,9 @@ let rec mk_expr
13641232

13651233
| B.Constructor _, _ ->
13661234
let ty = dty_to_ty term_ty in
1367-
begin match ty with
1368-
| Ty.Tadt _ ->
1369-
let l = List.map (fun t -> aux_mk_expr t) args in
1370-
E.mk_constr tcst l ty
1371-
| Ty.Trecord _ ->
1372-
let l = List.map (fun t -> aux_mk_expr t) args in
1373-
E.mk_record l ty
1374-
| _ ->
1375-
Fmt.failwith
1376-
"Constructor error: %a does not belong to a record nor an\
1377-
algebraic data type"
1378-
DE.Term.print app_term
1379-
end
1235+
let sy = Sy.constr tcst in
1236+
let l = List.map (fun t -> aux_mk_expr t) args in
1237+
E.mk_term sy l ty
13801238

13811239
| B.Coercion, [ x ] ->
13821240
begin match DT.view (DE.Term.ty x), DT.view term_ty with

0 commit comments

Comments
 (0)