Skip to content

Commit b81fc28

Browse files
Merge pull request #1740 from herd/aslspec-fixes
[aslspec] fixes
2 parents c3dff75 + d3adc75 commit b81fc28

File tree

4 files changed

+61
-32
lines changed

4 files changed

+61
-32
lines changed

asllib/aslspec/render.ml

Lines changed: 48 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -674,7 +674,7 @@ module Make (S : SPEC_VALUE) = struct
674674
missing prose templates. *)
675675
let prose_or_empty_message ~name prose =
676676
if Utils.string_is_empty prose then
677-
Format.asprintf "<empty prose for %s>"
677+
Format.asprintf "``empty prose for %s''"
678678
(Latex.spec_var_to_latex_var ~font_type:TextTT name)
679679
else prose
680680

@@ -689,6 +689,15 @@ module Make (S : SPEC_VALUE) = struct
689689
*)
690690
let var_to_prose id = spec_var_to_latex_var ~font_type:TextTT id
691691

692+
(** Removes angle brackets from the template and substitutes the
693+
placeholders with the provided substitutions. *)
694+
let preprocess_template_and_substitute template substitutions =
695+
(* Replace text inside angle brackets with the text itself. *)
696+
let template =
697+
Str.global_replace (Str.regexp "<\\([^>]*\\)>") "\\1" template
698+
in
699+
substitute template substitutions
700+
692701
(** [expr_to_prose expr] converts an expression [expr] to its prose
693702
representation. *)
694703
let rec expr_to_prose expr =
@@ -749,7 +758,7 @@ module Make (S : SPEC_VALUE) = struct
749758
| Some name -> Some (name, prose))
750759
formal_opt_prose_pairs
751760
in
752-
substitute expr_prose formal_prose_pairs
761+
preprocess_template_and_substitute expr_prose formal_prose_pairs
753762
| Record { label_opt; fields } ->
754763
let variant = Spec.record_variant_for_expr S.spec expr in
755764
let name =
@@ -764,12 +773,33 @@ module Make (S : SPEC_VALUE) = struct
764773
TypeVariant.prose_description variant
765774
|> prose_or_empty_message ~name
766775
in
776+
let declared_fields =
777+
match variant.term with
778+
| Record { fields } -> fields
779+
| _ -> assert false
780+
in
781+
(* A record expression is allowed to specify only a subset of the declared fields.
782+
We figure those out, associate them with _, and append them to the explicitly
783+
specified fields.
784+
*)
785+
let unspecified_defaults =
786+
let declared_field_names =
787+
List.map (fun field -> field.Term.name) declared_fields
788+
in
789+
let unspecified_fields =
790+
Utils.string_list_difference declared_field_names
791+
(List.map fst fields)
792+
in
793+
List.map
794+
(fun field -> (field, Expr.Var Spec.ignore_var))
795+
unspecified_fields
796+
in
767797
let field_to_prose =
768798
List.map
769799
(fun (field, field_expr) -> (field, expr_to_prose field_expr))
770-
fields
800+
(fields @ unspecified_defaults)
771801
in
772-
substitute expr_prose field_to_prose
802+
preprocess_template_and_substitute expr_prose field_to_prose
773803
| RecordUpdate { record_expr; updates } ->
774804
let record_prose = expr_to_prose record_expr in
775805
let updates_prose =
@@ -837,7 +867,7 @@ module Make (S : SPEC_VALUE) = struct
837867
relation.name
838868
in
839869
let formal_prose_pair = [ (formal_arg_name, args_prose) ] in
840-
substitute expr_prose formal_prose_pair
870+
preprocess_template_and_substitute expr_prose formal_prose_pair
841871
else
842872
let formal_arg_pairs = List.combine formal_args args in
843873
let formal_prose_pairs =
@@ -846,7 +876,7 @@ module Make (S : SPEC_VALUE) = struct
846876
named_args_for_opt_named_term opt_named_term arg)
847877
formal_arg_pairs
848878
in
849-
substitute expr_prose formal_prose_pairs
879+
preprocess_template_and_substitute expr_prose formal_prose_pairs
850880

851881
(** [short_circuit_to_prose relation_name short_circuit] returns the prose
852882
for the short-circuit expressions added as superscripts. *)
@@ -956,6 +986,14 @@ module Make (S : SPEC_VALUE) = struct
956986
"one of the following applies". *)
957987
pp_prose_rule_elements fmt ~case_name:"" rule_elements
958988

989+
(** [pp_render_rule_math_and_prose fmt def] renders both the mathematical
990+
inference rules and the prose description of the rules referenced by
991+
[def] with the formatter [fmt]. *)
992+
let pp_render_rule_math_and_prose fmt def =
993+
pp_render_rule fmt def;
994+
fprintf fmt "@.@.";
995+
pp_render_rule_prose fmt def
996+
959997
(** [pp_render_rule_macro fmt def] renders the LaTeX wrapper macro
960998
[\DefineRule{name}{...}] around the rendering of the mathematical
961999
inference rules referenced by [def] with the formatter [fmt]. *)
@@ -1010,7 +1048,7 @@ module Make (S : SPEC_VALUE) = struct
10101048
| Elem_Type def -> pp_type_definition fmt def
10111049
| Elem_Relation def -> pp_relation_definition fmt def
10121050
| Elem_RenderTypes def -> RenderTypeSubsets.pp_render_types fmt def
1013-
| Elem_RenderRule def -> RenderRule.pp_render_rule fmt def
1051+
| Elem_RenderRule def -> RenderRule.pp_render_rule_math_and_prose fmt def
10141052

10151053
(** [pp_elem_definition_macro fmt elem] renders a macro definition for an
10161054
element of the specification. *)
@@ -1042,28 +1080,9 @@ module Make (S : SPEC_VALUE) = struct
10421080
Latex.spec_var_to_latex_var ~font_type:Latex.Text name
10431081
in
10441082
match elem with
1045-
| Elem_Constant _ ->
1046-
fprintf fmt {|
1047-
\section*{%s}
1048-
%a
1049-
|} latex_name pp_elem elem
1050-
| Elem_Relation _ ->
1051-
if is_operator elem then ()
1052-
else fprintf fmt {|
1053-
\section*{%s}
1054-
%a
1055-
|} latex_name pp_elem elem
1056-
| Elem_Type _ ->
1057-
fprintf fmt {|
1058-
\section*{%s}
1059-
%a
1060-
|} latex_name pp_elem elem
1061-
| Elem_RenderTypes _ ->
1062-
fprintf fmt {|
1063-
\section*{%s}
1064-
%a
1065-
|} latex_name pp_elem elem
1066-
| Elem_RenderRule _ ->
1083+
| Elem_Relation _ when is_operator elem -> ()
1084+
| Elem_Constant _ | Elem_Type _ | Elem_RenderTypes _
1085+
| Elem_RenderRule _ | Elem_Relation _ ->
10671086
fprintf fmt {|
10681087
\section*{%s}
10691088
%a

asllib/aslspec/spec.ml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1478,9 +1478,10 @@ module Check = struct
14781478
(* Filters out identifiers that are definitely not variables. *)
14791479
let is_non_var id =
14801480
match StringMap.find_opt id id_to_defining_node with
1481-
| Some (Node_Constant _) | Some (Node_TypeVariant _) ->
1482-
(* Constants and variant labels are not variables. *)
1481+
| Some (Node_Constant _) | Some (Node_TypeVariant { term = Label _ }) ->
1482+
(* Constants and label variant are not variables. *)
14831483
true
1484+
| Some (Node_TypeVariant _)
14841485
| Some (Node_Type _)
14851486
| Some (Node_RecordField _)
14861487
| Some (Node_Relation _)

asllib/aslspec/utils.ml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,20 @@ let rec list_iter3 f lst1 lst2 lst3 =
6262
list_iter3 f t1 t2 t3
6363
| _ -> invalid_arg "list_iter3: lists have different lengths"
6464

65+
(** [string_list_is_subset lst1 lst2] checks if all elements of [lst1] are
66+
contained in [lst2]. *)
6567
let string_list_is_subset lst1 lst2 =
6668
let set1 = StringSet.of_list lst1 in
6769
let set2 = StringSet.of_list lst2 in
6870
StringSet.subset set1 set2
6971

72+
(** [string_list_difference lst1 lst2] returns the list of elements that are in
73+
[lst1] but not in [lst2]. *)
74+
let string_list_difference lst1 lst2 =
75+
let set1 = StringSet.of_list lst1 in
76+
let set2 = StringSet.of_list lst2 in
77+
StringSet.elements (StringSet.diff set1 set2)
78+
7079
(***************************************
7180
String-related utilities.
7281
***************************************)

asllib/doc/asl.spec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6962,7 +6962,7 @@ typing function to_well_constrained(t: ty) ->
69626962

69636963
case t_int_other {
69646964
t =: T_Int(i);
6965-
i != Parameterized;
6965+
i != Parameterized(_);
69666966
--
69676967
t;
69686968
}

0 commit comments

Comments
 (0)