Skip to content

Commit 3b46588

Browse files
committed
Mostly translate quantification tests
Signed-off-by: Andrew Helwer <[email protected]>
1 parent 1f644b6 commit 3b46588

File tree

3 files changed

+225
-57
lines changed

3 files changed

+225
-57
lines changed

test/parser/parser_tests.ml

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,6 @@ let expect_parse_failure (test : syntax_test) : bool =
8080
"Nonfix Double Exclamation Operator (GH TSTLA #GH97, GH tlaplus/tlaplus #884)";
8181
]
8282

83-
let expect_tree_comparison_failure (test : syntax_test) : bool =
84-
List.mem test.info.name [
85-
(* TLAPM appears to simply return an empty set here? *)
86-
"Mistaken Set Filter Test";
87-
"Mistaken Set Filter Tuples Test";
88-
]
89-
9083
let should_skip_tree_comparison (test : syntax_test) : bool =
9184
List.mem test.info.path [
9285
"syntax_corpus/assume-prove.txt";
@@ -99,7 +92,6 @@ let should_skip_tree_comparison (test : syntax_test) : bool =
9992
"syntax_corpus/postfix_op.txt";
10093
"syntax_corpus/prefix_op.txt";
10194
"syntax_corpus/proofs.txt";
102-
"syntax_corpus/quantification.txt";
10395
"syntax_corpus/records.txt";
10496
"syntax_corpus/recursive.txt";
10597
"syntax_corpus/step_expressions.txt";
@@ -119,6 +111,13 @@ let should_skip_tree_comparison (test : syntax_test) : bool =
119111
"Nonfix Minus (GH tlaplus/tlaplus #GH884)";
120112
]
121113

114+
let expect_tree_comparison_failure (test : syntax_test) : bool =
115+
List.mem test.info.name [
116+
(* TLAPM appears to simply return an empty set here? *)
117+
"Mistaken Set Filter Test";
118+
"Mistaken Set Filter Tuples Test";
119+
]
120+
122121
let tests = "Standardized syntax test corpus" >::: (
123122
get_all_tests_under "syntax_corpus"
124123
|> List.map (fun test ->

test/parser/syntax_corpus/quantification.txt

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,3 +377,92 @@ op == CHOOSE <<x, y, z>> : FALSE
377377
)
378378
)
379379
(double_line)))
380+
381+
==============================|||
382+
Bounded CHOOSE with Multiple Identifiers
383+
:error
384+
==============================|||
385+
386+
---- MODULE Test ----
387+
op == CHOOSE x, y \in S : TRUE
388+
====
389+
390+
------------------------------|||
391+
392+
==============================|||
393+
Bounded Tuple CHOOSE with Multiple Identifiers
394+
:error
395+
==============================|||
396+
397+
---- MODULE Test ----
398+
op == CHOOSE <<x>>, <<y>> \in S : TRUE
399+
====
400+
401+
------------------------------|||
402+
403+
==============================|||
404+
Unbounded CHOOSE with Multiple Identifiers
405+
:error
406+
==============================|||
407+
408+
---- MODULE Test ----
409+
op == CHOOSE x, y : TRUE
410+
====
411+
412+
------------------------------|||
413+
414+
==============================|||
415+
Unbounded Tuple CHOOSE with Multiple Identifiers
416+
:error
417+
==============================|||
418+
419+
---- MODULE Test ----
420+
op == CHOOSE <<x>>, <<y>> : TRUE
421+
====
422+
423+
------------------------------|||
424+
425+
==============================|||
426+
Quantifier with Mixed Tuples and Standalone Identifiers
427+
:error
428+
==============================|||
429+
430+
---- MODULE Test ----
431+
op == \A x, <<y>>, z \in S : FALSE
432+
====
433+
434+
------------------------------|||
435+
436+
==============================|||
437+
Quantifier with Multiple Tuples for Single Bound
438+
:error
439+
==============================|||
440+
441+
---- MODULE Test ----
442+
op == \A <<x>>, <<y>> \in S : FALSE
443+
====
444+
445+
------------------------------|||
446+
447+
==============================|||
448+
Mixed Bounded and Unbounded Quantifiers
449+
:error
450+
==============================|||
451+
452+
---- MODULE Test ----
453+
op == \A x, y \in S, z : FALSE
454+
====
455+
456+
------------------------------|||
457+
458+
==============================|||
459+
Quantifiers with Unbounded Tuple
460+
:error
461+
==============================|||
462+
463+
---- MODULE Test ----
464+
op == \A <<x, y>> : FALSE
465+
====
466+
467+
------------------------------|||
468+

test/parser/translate_syntax_tree.ml

Lines changed: 129 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,25 @@ let translate_number (_number : string) (decimal : string) : ts_node =
209209
then leaf_node "nat_number"
210210
else leaf_node "real_number"
211211

212+
(** For expressions like \A x, y \in Nat : f(x, y), the first x will have
213+
bound_domain variant Domain with an associated expression corresponding
214+
to the set being enumerated, and the second variable y will have
215+
bound_domain variant Ditto without any associated domain information;
216+
this function regroups these into a list of identifiers underneath a
217+
single set expression. It is different from the unditto function which
218+
clones the set expression into the y variable bound_domain. This also
219+
handles unbounded quantification, which is represented by the No_domain
220+
variant and bundled by this function into an option.
221+
*)
222+
let group_bounds (bounds : Expr.T.bound list) : (ts_node list * Expr.T.expr) list =
223+
let (final_groups, _) = List.fold_right (fun ((_, _, domain) : Expr.T.bound) ((groups, partial_group) : ((ts_node list * Expr.T.expr) list) * ts_node list) ->
224+
match domain with
225+
| Ditto -> (groups, leaf_node "identifier" :: partial_group)
226+
| Domain expr -> ((leaf_node "identifier" :: partial_group, expr) :: groups, [])
227+
| No_domain -> failwith "Encountered unbounded domain when grouping bounds"
228+
) bounds ([], [])
229+
in final_groups
230+
212231
(** Translates the substitution component of INSTANCE statements like s <- expr *)
213232
let rec translate_substitution ((hint, expr) : (Util.hint * Expr.T.expr)) : field_or_node =
214233
Node {
@@ -287,45 +306,55 @@ and translate_jlist (bullet : Expr.T.bullet) (juncts : Expr.T.expr list) : ts_no
287306
children = [leaf ("bullet_" ^ jtype); Node (translate_expr expr)]
288307
}) juncts
289308
}
290-
and translate_quantifier_bound ((names, domain) : (ts_node list * Expr.T.expr)) : ts_node = {
291-
name = "quantifier_bound";
292-
children = List.flatten [
293-
field_list "intro" names;
294-
[leaf "set_in"];
295-
[Field ("set", translate_expr domain)]
296-
]
297-
}
298309

299310
and translate_quantifier_bounds (bounds : Expr.T.bound list) : ts_node list =
300-
let group_bounds (bounds : Expr.T.bound list) : (ts_node list * Expr.T.expr) list =
301-
let (final_groups, _) = List.fold_right (fun ((_, _, domain) : Expr.T.bound) ((groups, partial_group) : ((ts_node list * Expr.T.expr) list) * ts_node list) ->
302-
match domain with
303-
| Ditto -> (groups, leaf_node "identifier" :: partial_group)
304-
| Domain expr -> ((leaf_node "identifier" :: partial_group, expr) :: groups, [])
305-
| _ -> failwith "unknown quantifier bound type"
306-
) bounds ([], [])
307-
in final_groups
311+
let translate_quantifier_bound ((names, domain) : (ts_node list * Expr.T.expr)) : ts_node = {
312+
name = "quantifier_bound";
313+
children = List.flatten [
314+
field_list "intro" names;
315+
[leaf "set_in"];
316+
[Field ("set", translate_expr domain)]
317+
]
318+
}
308319
in bounds |> group_bounds |> List.map translate_quantifier_bound
309320

310-
and translate_tuple_quantifier_bound ((names, bound_domain) : Expr.T.tuply_name * Expr.T.bound_domain) : ts_node =
311-
match names, bound_domain with
312-
| (Bound_names names, Domain set) -> {
313-
name = "quantifier_bound";
314-
children = [
315-
Field ("intro", {
316-
name = "tuple_of_identifiers";
317-
children = List.flatten [
318-
[leaf "langle_bracket"];
319-
List.map (fun _ -> leaf "identifier") names;
320-
[leaf "rangle_bracket"];
321-
]
322-
});
323-
leaf "set_in";
324-
Field ("set", translate_expr set);
325-
]
326-
}
327-
| (Bound_names _, Ditto) -> failwith "tuple quantifier ditto"
328-
| _ -> failwith "unknown tuple quantifier bound type"
321+
and translate_tuple_quantifier_bounds (bounds : Expr.T.tuply_bound list) : ts_node list =
322+
let translate_tuple_quantifier_bound ((names, bound_domain) : Expr.T.tuply_name * Expr.T.bound_domain) : ts_node =
323+
match names, bound_domain with
324+
| (Bound_names names, Domain set) -> {
325+
name = "quantifier_bound";
326+
children = [
327+
Field ("intro", {
328+
name = "tuple_of_identifiers";
329+
children = List.flatten [
330+
[leaf "langle_bracket"];
331+
List.map (fun _ -> leaf "identifier") names;
332+
[leaf "rangle_bracket"];
333+
]
334+
});
335+
leaf "set_in";
336+
Field ("set", translate_expr set);
337+
]
338+
}
339+
| (Bound_name _, Domain set) -> {
340+
name = "quantifier_bound";
341+
children = [
342+
Field ("intro", {
343+
name = "tuple_of_identifiers";
344+
children = [
345+
leaf "langle_bracket";
346+
field_leaf "intro" "identifier";
347+
leaf "rangle_bracket";
348+
]
349+
});
350+
leaf "set_in";
351+
Field ("set", translate_expr set);
352+
]
353+
}
354+
| (Bound_names _, Ditto) -> failwith "multiple_names_ditto"
355+
| (Bound_name _, Ditto) -> leaf_node "single_name_ditto"
356+
| (_, No_domain) -> failwith "Tuple quantifiers must have a domain; this should not be representable"
357+
in List.map translate_tuple_quantifier_bound bounds
329358

330359
and translate_case_arm (index : int) ((pred, expr) : Expr.T.expr * Expr.T.expr) : field_or_node list =
331360
let case = Node {
@@ -438,20 +467,22 @@ and translate_set_filter (_name : Util.hint) (set : Expr.T.expr) (filter : Expr.
438467
]
439468
}
440469

470+
and translate_tuple_of_identifiers (names : Util.hint list) : ts_node = {
471+
name = "tuple_of_identifiers";
472+
children = List.flatten [
473+
[leaf "langle_bracket"];
474+
List.map (fun _ -> leaf "identifier") names;
475+
[leaf "rangle_bracket"];
476+
]
477+
}
478+
441479
and translate_tuple_set_filter (names : Util.hint list) (set : Expr.T.expr) (filter : Expr.T.expr) : ts_node = {
442480
name = "set_filter";
443481
children = [
444482
Field ("generator", {
445483
name = "quantifier_bound";
446484
children = [
447-
Field ("intro", {
448-
name = "tuple_of_identifiers";
449-
children = List.flatten [
450-
[leaf "langle_bracket"];
451-
List.map (fun _ -> leaf "identifier") names;
452-
[leaf "rangle_bracket"];
453-
]
454-
});
485+
Field ("intro", translate_tuple_of_identifiers names);
455486
leaf "set_in";
456487
Field ("set", translate_expr set)
457488
]
@@ -473,17 +504,62 @@ and translate_tuple_set_map (map : Expr.T.expr) (bounds : Expr.T.tuply_bound lis
473504
name = "set_map";
474505
children = List.flatten [
475506
[Field ("map", translate_expr map)];
476-
field_list_map "generator" translate_tuple_quantifier_bound bounds;
507+
bounds |> translate_tuple_quantifier_bounds |> field_list "generator";
477508
]
478509
}
479510

480-
and translate_bounded_quantification (quantifier : Expr.T.quantifier) (bounds : Expr.T.bound list) (expr : Expr.T.expr) : ts_node =
481-
let bounds = Expr.T.unditto bounds in {
511+
and translate_quantification (quantifier : Expr.T.quantifier) (bounds : Expr.T.bound list) (body : Expr.T.expr) : ts_node =
512+
let is_bound (bounds : Expr.T.bound list) : bool =
513+
List.for_all (fun (_, _, domain) -> match (domain : Expr.T.bound_domain) with | No_domain -> false | _ -> true ) bounds
514+
in if is_bound bounds then {
515+
name = "bounded_quantification";
516+
children = List.flatten [
517+
[field_leaf "quantifier" (match quantifier with | Forall -> "forall" | Exists -> "exists")];
518+
bounds |> translate_quantifier_bounds |> field_list "bound";
519+
[Field ("expression", translate_expr body)];
520+
]
521+
} else {
522+
name = "unbounded_quantification";
523+
children = List.flatten [
524+
[field_leaf "quantifier" (match quantifier with | Forall -> "forall" | Exists -> "exists")];
525+
List.map (fun _ -> field_leaf "intro" "identifier") bounds;
526+
[Field ("expression", translate_expr body)];
527+
]
528+
}
529+
530+
and translate_tuple_bounded_quantification (quantifier : Expr.T.quantifier) (bounds : Expr.T.tuply_bound list) (body : Expr.T.expr) : ts_node = {
482531
name = "bounded_quantification";
483532
children = List.flatten [
484533
[field_leaf "quantifier" (match quantifier with | Forall -> "forall" | Exists -> "exists")];
485-
field_list "generator" (translate_quantifier_bounds bounds);
486-
[Field ("expression", translate_expr expr)];
534+
bounds |> translate_tuple_quantifier_bounds |> field_list "bound";
535+
[Field ("expression", translate_expr body)];
536+
]
537+
}
538+
539+
and translate_temporal_quantification (quantifier : Expr.T.quantifier) (names : Util.hints) (body : Expr.T.expr) : ts_node = {
540+
name = "unbounded_quantification";
541+
children = List.flatten [
542+
[field_leaf "quantifier" (match quantifier with | Forall -> "temporal_forall" | Exists -> "temporal_exists")];
543+
List.map (fun _ -> field_leaf "intro" "identifier") names;
544+
[Field ("expression", translate_expr body)];
545+
]
546+
}
547+
548+
and translate_choose (_name : Util.hint) (set : Expr.T.expr option) (body : Expr.T.expr) : ts_node = {
549+
name = "choose";
550+
children = List.flatten [
551+
[field_leaf "intro" "identifier"];
552+
(match set with | Some expr -> [leaf "set_in"; Field ("set", translate_expr expr)] | None -> []);
553+
[Field ("expression", translate_expr body)]
554+
]
555+
}
556+
557+
and translate_tuple_choose (names : Util.hint list) (set : Expr.T.expr option) (body : Expr.T.expr) : ts_node = {
558+
name = "choose";
559+
children = List.flatten [
560+
[Field ("intro", translate_tuple_of_identifiers names)];
561+
(match set with | Some expr -> [leaf "set_in"; Field ("set", translate_expr expr)] | None -> []);
562+
[Field ("expression", translate_expr body)]
487563
]
488564
}
489565

@@ -504,7 +580,11 @@ and translate_expr (expr : Expr.T.expr) : ts_node =
504580
| SetStTuply (names, set, filter) -> translate_tuple_set_filter names set filter
505581
| SetOf (map, bounds) -> translate_set_map map bounds
506582
| SetOfTuply (map, bounds) -> translate_tuple_set_map map bounds
507-
| Quant (quantifier, bounds, expr) -> translate_bounded_quantification quantifier bounds expr
583+
| Quant (quantifier, bounds, expr) -> translate_quantification quantifier bounds expr
584+
| QuantTuply (quantifier, bounds, expr) -> translate_tuple_bounded_quantification quantifier bounds expr
585+
| Tquant (quantifier, hints, expr) -> translate_temporal_quantification quantifier hints expr
586+
| Choose (name, set, expr) -> translate_choose name set expr
587+
| ChooseTuply (names, set, expr) -> translate_tuple_choose names set expr
508588
| Tuple expr_ls -> {
509589
name = "tuple_literal";
510590
children = [leaf "langle_bracket"] @ (node_list_map translate_expr expr_ls) @ [leaf "rangle_bracket"]

0 commit comments

Comments
 (0)