Skip to content

Commit 971d0bb

Browse files
Merge pull request herd#1703 from herd/aslspec-importing-rules
Importing inference rules from LaTeX to aslspec
2 parents 80aea03 + ae8fc3f commit 971d0bb

49 files changed

Lines changed: 12911 additions & 3526 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

asllib/StaticOperations.ml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,11 @@ let filter_reduce_constraint_div =
141141
| _ -> None)
142142
| _ -> None
143143
in
144+
let make_constraint_range_opt z1 z2 =
145+
if Z.equal z1 z2 then Some (exact (expr_of_z z1))
146+
else if Z.leq z1 z2 then Some (range (expr_of_z z1) (expr_of_z z2))
147+
else None
148+
in
144149
function
145150
| Constraint_Exact e as c -> (
146151
match get_literal_div_opt e with
@@ -167,9 +172,7 @@ let filter_reduce_constraint_div =
167172
Format.eprintf "Reducing %a DIV %a@ got z1=%a and z2=%a@."
168173
PP.pp_expr e1 PP.pp_expr e2 Z.pp_print z1 Z.pp_print z2
169174
in
170-
if Z.equal z1 z2 then Some (exact (expr_of_z z1))
171-
else if Z.leq z1 z2 then Some (range (expr_of_z z1) (expr_of_z z2))
172-
else None
175+
make_constraint_range_opt z1 z2
173176
| Some z1, None -> Some (range (expr_of_z z1) e2)
174177
| None, Some z2 -> Some (range e1 (expr_of_z z2))
175178
| None, None -> Some c)

asllib/aslspec/AST.ml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ module AttributeKey = struct
4040
| Custom
4141
(** Whether an operator over a list of arguments should be rendered by a
4242
custom multi-argument macro. *)
43+
| Typecast (** Whether an operator serves only to perform a typecast. *)
4344
| Short_Circuit_Macro
4445
(** A LaTeX macro name to succinctly denote any value of a type [T].
4546
This is used to denote the short-circuit result of a relation
@@ -60,6 +61,7 @@ module AttributeKey = struct
6061
| LHS_Hypertargets -> 5
6162
| Associative -> 6
6263
| Custom -> 7
64+
| Typecast -> 8
6365
in
6466
let a_int = key_to_int a in
6567
let b_int = key_to_int b in
@@ -76,6 +78,7 @@ module AttributeKey = struct
7678
| LHS_Hypertargets -> "lhs_hypertargets"
7779
| Associative -> "associative"
7880
| Custom -> "custom"
81+
| Typecast -> "typecast"
7982
end
8083

8184
(** A value associated with an attribute key. *)
@@ -582,6 +585,10 @@ module Relation : sig
582585
(** [is_custom_operator t] tests whether the operator represented by [t] has
583586
the [custom] attributes set to [true]. *)
584587

588+
val is_typecast_operator : t -> bool
589+
(** [is_typecast_operator t] tests whether the operator represented by [t] has
590+
the [typecast] attributes set to [true]. *)
591+
585592
val math_layout : t -> layout option
586593
(** The layout used when rendered as a stand-alone relation definition. *)
587594
end = struct
@@ -655,6 +662,9 @@ end = struct
655662

656663
let is_custom_operator self =
657664
Attributes.get_bool AttributeKey.Custom ~default:false self.att
665+
666+
let is_typecast_operator self =
667+
Attributes.get_bool AttributeKey.Typecast ~default:false self.att
658668
end
659669

660670
(** A datatype for grouping (subsets of) type definitions. *)

asllib/aslspec/SpecLexer.mll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ rule token = parse
6363
| "semantics" { SEMANTICS }
6464
| "short_circuit_macro" { SHORT_CIRCUIT_MACRO }
6565
| "then" { THEN }
66+
| "typecast" { TYPECAST }
6667
| "typedef" { TYPEDEF }
6768
| "typing" { TYPING }
6869
| "variadic" { VARIADIC }

asllib/aslspec/SpecParser.mly

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ let bool_of_string s =
5959
%token RULE
6060
%token SEMANTICS
6161
%token SHORT_CIRCUIT_MACRO
62+
%token TYPECAST
6263
%token TYPEDEF
6364
%token TYPING
6465
%token VARIADIC
@@ -294,6 +295,7 @@ let operator_attribute :=
294295
let operator_style_attribute ==
295296
| ASSOCIATIVE; EQ; value=IDENTIFIER; { (Associative, BoolAttribute (bool_of_string value)) }
296297
| CUSTOM; EQ; value=IDENTIFIER; { (Custom, BoolAttribute (bool_of_string value)) }
298+
| TYPECAST; EQ; value=IDENTIFIER; { (Typecast, BoolAttribute (bool_of_string value)) }
297299

298300
let prose_application_attribute ==
299301
PROSE_APPLICATION; EQ; template=STRING; { (Prose_Application, StringAttribute template) }

asllib/aslspec/builtins.spec

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
operator cond_case[T](Bool, T) -> T
2+
{
3+
math_macro = \condcase,
4+
custom = true,
5+
};
6+
7+
// TODO: add a custom rendering where all conditions
8+
// and all values are properly aligned.
9+
// Perhaps this can be achieved by adding a raw attribute to macros, which doesn't wrap them with braces.
10+
// TODO: add custom syntac for cases.
11+
variadic operator cond_op[T](list1(T)) -> T
12+
{
13+
math_macro = \condop,
14+
custom = true,
15+
};
16+
17+
// This constant is for internal use only.
118
constant bot { "bottom", math_macro = \bot };
219

320
constant None { "the empty \optionalterm{}" };
@@ -34,6 +51,18 @@ typedef Z
3451
math_macro = \Z,
3552
};
3653

54+
operator is_integer(q: Q) -> Bool
55+
{
56+
"{q} is an integer",
57+
math_macro = \isintegerop,
58+
};
59+
60+
operator is_not_integer(q: Q) -> Bool
61+
{
62+
"{q} is not an integer",
63+
math_macro = \isnotintegerop,
64+
};
65+
3766
typedef Q
3867
{ "rational",
3968
math_macro = \Q,
@@ -56,7 +85,7 @@ operator assign[T](lhs: T, rhs: T) -> Bool
5685

5786
operator reverse_assign[T](lhs: T, rhs: T) -> Bool
5887
{
59-
math_macro = \eqname,
88+
math_macro = \reverseeqdef,
6089
};
6190

6291
operator equal[T](a: T, b: T) -> (c: Bool)
@@ -75,21 +104,6 @@ operator if_then_else[T](Bool, T, T) -> T
75104
math_macro = \ifthenelseop,
76105
};
77106

78-
// TODO: add a custom rendering where all conditions
79-
// and all values are properly aligned.
80-
// Perhaps this can be achieved by adding a "raw" attribute to macros, which doesn't wrap them with braces.
81-
// TODO: add custom syntax for cases.
82-
variadic operator cond_op[T](list1(T)) -> T
83-
{
84-
math_macro = \condop,
85-
custom = true,
86-
};
87-
operator cond_case[T](Bool, T) -> T
88-
{
89-
math_macro = \condcase,
90-
custom = true,
91-
};
92-
93107
variadic operator and(list1(Bool)) -> Bool
94108
{
95109
associative = true,
@@ -102,21 +116,28 @@ variadic operator or(list1(Bool)) -> Bool
102116
math_macro = \lor,
103117
};
104118

105-
operator list_and(list1(Bool)) -> Bool
119+
operator list_and(list0(Bool)) -> Bool
106120
{
107-
math_macro = \land,
121+
math_macro = \listand,
108122
};
109123

110-
operator list_or(list1(Bool)) -> Bool
124+
operator list_or(list0(Bool)) -> Bool
111125
{
112-
math_macro = \lor,
126+
math_macro = \listor,
113127
};
114128

115129
operator not(Bool) -> Bool
116130
{
117131
math_macro = \opnot,
118132
};
119133

134+
// This is negation, specialized to a single variable to allow
135+
// the macro to drop the parenthesis around the variable.
136+
operator not_single(Bool) -> Bool
137+
{
138+
math_macro = \opnotvar,
139+
};
140+
120141
operator iff(Bool, Bool) -> Bool
121142
{
122143
math_macro = \IFF,
@@ -138,6 +159,11 @@ operator num_minus[NumType](NumType, NumType) -> NumType
138159
math_macro = \numminus,
139160
};
140161

162+
operator num_negate[NumType](NumType) -> NumType
163+
{
164+
math_macro = \numnegate,
165+
};
166+
141167
// Negation for number types.
142168
operator negate[NumType](NumType) -> NumType
143169
{
@@ -147,6 +173,7 @@ operator negate[NumType](NumType) -> NumType
147173
variadic operator num_times[NumType](list1(NumType)) -> NumType
148174
{
149175
math_macro = \numtimes,
176+
associative = true,
150177
};
151178

152179
operator num_divide[NumType](NumType, NumType) -> NumType
@@ -157,6 +184,7 @@ operator num_divide[NumType](NumType, NumType) -> NumType
157184
operator num_exponent[NumType](NumType, NumType) -> NumType
158185
{
159186
math_macro = \numexponent,
187+
custom = true,
160188
};
161189

162190
operator less_than[NumType](NumType, NumType) -> Bool

asllib/aslspec/render.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,7 @@ module Make (S : SPEC_VALUE) = struct
516516
let op_macro = get_or_gen_math_macro op_name in
517517
let layout =
518518
if Spec.is_cond_operator_name S.spec op_name then
519-
(* Special case for the match_cases operator, which is always vertical. *)
519+
(* Special case for the 'cond' operator, which is always vertical. *)
520520
vertical_if_unspecified layout args
521521
else horizontal_if_unspecified layout args
522522
in
@@ -623,7 +623,7 @@ module Make (S : SPEC_VALUE) = struct
623623
pp_case_name_opt name_opt
624624
(pp_print_list
625625
(* The quadruple backslash means the next premise definitely starts on a new line. *)
626-
~pp_sep:(fun fmt () -> fprintf fmt {|\hva\\\\@.|})
626+
~pp_sep:(fun fmt () -> fprintf fmt {|\hva\\@.|})
627627
pp_premise)
628628
premises pp_conclusion conclusion
629629

asllib/aslspec/spec.ml

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1840,6 +1840,17 @@ module Check = struct
18401840
use_def_mode * Term.t list ->
18411841
context_expr:Expr.t ->
18421842
Term.t list * Term.t
1843+
(** [instantiate_operator_types_from_inferred_types spec relation_name
1844+
num_actual_args (mode, inferred_types) ~context_expr] instantiates
1845+
the types of the arguments and output of the operator [relation_name]
1846+
given the number of actual arguments [num_actual_args] and the
1847+
[inferred_types] for either its arguments or its output depending on
1848+
[mode]. The [context_expr] is used for error reporting. When mode is
1849+
[Use], the [inferred_types] correspond to the argument types. When
1850+
mode is [Def], the [inferred_types] correspond to the output type. By
1851+
instantiating we mean substituting type parameters in the operator
1852+
definition with concrete types inferred for a given operator
1853+
invocation expression. *)
18431854
end = struct
18441855
(** [unify_parameter_type spec ~relation_name parameter_name
18451856
parameter_type type_env] attempts to unify [parameter_type] with any
@@ -2076,17 +2087,6 @@ module Check = struct
20762087
in
20772088
(instantiated_arg_types, instantiated_output_type)
20782089

2079-
(** [instantiate_operator_types_from_inferred_types spec relation_name
2080-
num_actual_args (mode, inferred_types) ~context_expr] instantiates
2081-
the types of the arguments and output of the operator [relation_name]
2082-
given the number of actual arguments [num_actual_args] and the
2083-
[inferred_types] for either its arguments or its output depending on
2084-
[mode]. The [context_expr] is used for error reporting. When mode is
2085-
[Use], the [inferred_types] correspond to the argument types. When
2086-
mode is [Def], the [inferred_types] correspond to the output type. By
2087-
instantiating we mean substituting type parameters in the operator
2088-
definition with concrete types inferred for a given operator
2089-
invocation expression. *)
20902090
let instantiate_operator_types_from_inferred_types spec relation_name
20912091
num_actual_args (mode, inferred_types) ~context_expr =
20922092
let formal_arg_types =
@@ -2509,7 +2509,7 @@ module Check = struct
25092509
and return the function's output type. *)
25102510
let lhs_type, type_env = infer_type_in_env spec type_env lhs in
25112511
let from_term, to_term =
2512-
match lhs_type with
2512+
match CheckTypeInstantiations.reduce_term spec lhs_type with
25132513
| Function { from_type = _, from_term; to_type = _, to_term } ->
25142514
(from_term, to_term)
25152515
| _ -> Error.invalid_map_lhs_type lhs_type ~context_expr:expr
@@ -3111,25 +3111,34 @@ module ExtendNames = struct
31113111
open Expr
31123112
open Rule
31133113

3114-
(** [opt_extend] Wraps [expr] with a name if [opt_name] is [Some]. Avoids
3115-
naming a variable expression with its own name, as an optimization. *)
3116-
let opt_extend expr opt_name =
3117-
match (expr, opt_name) with
3114+
(** [opt_extend] Wraps [expr] with a name if [opt_param_name] is [Some].
3115+
Avoids naming a variable expression with its own name. *)
3116+
let opt_extend spec expr opt_param_name =
3117+
match (expr, opt_param_name) with
31183118
| _, None -> expr
31193119
| Var v, Some name when String.equal v name ->
31203120
expr (* Avoid naming a variable with its own name. *)
3121+
| ( Expr.Relation
3122+
{ name = operator_name; is_operator = true; args = [ Var v ] },
3123+
Some name ) ->
3124+
let relation = relation_for_id spec operator_name in
3125+
if Relation.is_typecast_operator relation && String.equal v name then
3126+
(* Typecasts render the input variable. If the input variable has the same name
3127+
as the parameter, avoid naming it. *)
3128+
expr
3129+
else NamedExpr (expr, name)
31213130
| _, Some name -> NamedExpr (expr, name)
31223131

31233132
(** [extend_with_names type_term expr ] recursively transforms [expr] by
31243133
adding names from [type_term] to sub-expressions of [expr]. Currently,
31253134
only tuples (labelled or unlabelled) are supported, which is sufficient
31263135
for most output configurations. *)
3127-
let rec extend_with_names type_term expr =
3136+
let rec extend_with_names spec type_term expr =
31283137
match (type_term, expr) with
31293138
| Term.Tuple { label_opt = None; args = [ (opt_name, _) ] }, _ ->
31303139
(* An unlabelled tuple with a single component serves as a named reference
31313140
to any type.*)
3132-
opt_extend expr opt_name
3141+
opt_extend spec expr opt_name
31333142
| ( Term.Tuple { label_opt = term_label_opt; args = term_components },
31343143
Expr.Tuple { label_opt = expr_label_opt; args = expr_components } )
31353144
when Option.equal String.equal term_label_opt expr_label_opt ->
@@ -3147,7 +3156,7 @@ module ExtendNames = struct
31473156
let extended_args =
31483157
List.map2
31493158
(fun (opt_name, arg_type) arg ->
3150-
opt_extend (extend_with_names arg_type arg) opt_name)
3159+
opt_extend spec (extend_with_names spec arg_type arg) opt_name)
31513160
term_components expr_components
31523161
in
31533162
Expr.Tuple { label_opt = expr_label_opt; args = extended_args }
@@ -3167,7 +3176,7 @@ module ExtendNames = struct
31673176
(* Fallback to the main output type. *)
31683177
List.hd output_types
31693178
in
3170-
let extended_rhs = extend_with_names output_type rhs in
3179+
let extended_rhs = extend_with_names spec output_type rhs in
31713180
let extended_expr =
31723181
Transition { lhs; rhs = extended_rhs; short_circuit }
31733182
in

asllib/aslspec/tests.t/operators.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ The relation
4141
} % EndDefineRelation
4242

4343
\DefineRule{f}{\begin{mathpar}
44-
\inferrule{ { { { \texttt{a}\intplus\texttt{b} } \equal \texttt{c} } } \\\\
44+
\inferrule{ { { { \texttt{a}\intplus\texttt{b} } \equal \texttt{c} } } \hva\\
4545
{ { \texttt{d} \eqdef { \ifthenelseop[H]{{ \texttt{a} \member \texttt{S} }}{\texttt{b}}{\texttt{c}} } } } }{
4646
{ \f(\texttt{a}, \texttt{b}, \texttt{c}, \texttt{S}) \typearrow \texttt{d} }
4747
}

asllib/aslspec/tests.t/rule.expected

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ The relation
6161
{ \condcase[H]{{ \texttt{a} \equal \texttt{b} }}{\texttt{a}} }, \\
6262
{ \condcase[H]{{ \texttt{a} \greaterthan \texttt{b} }}{{ \texttt{a}\numplus\texttt{b} }} }, \\
6363
{ \condcase[H]{{ \texttt{a} \lessthan \texttt{b} }}{\texttt{b}} }
64-
\end{array}} } } } \\\\
65-
{ { \texttt{r\_f} \eqdef { \texttt{r}.\FIELDf\numplus\texttt{r}.\FIELDg } } } \\\\
64+
\end{array}} } } } \hva\\
65+
{ { \texttt{r\_f} \eqdef { \texttt{r}.\FIELDf\numplus\texttt{r}.\FIELDg } } } \hva\\
6666
{ { \texttt{r'} \eqdef \texttt{r}\left\{\begin{array}{lcl}
6767
\FIELDf & : & \texttt{res}
6868
\end{array}\right\} } } }{

asllib/aslspec/tests.t/run.t

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,8 @@
77
Generated LaTeX macros into generated_macros.tex
88
$ aslspec rule.spec --render; diff -w generated_macros.tex rule.expected; rm -f generated_macros.tex
99
Generated LaTeX macros into generated_macros.tex
10-
64,65c64,65
11-
< \end{array}} } } } \hva\\\\
12-
< { { \texttt{r\_f} \eqdef { \texttt{r}.\FIELDf\numplus\texttt{r}.\FIELDg } } } \hva\\\\
13-
---
14-
> \end{array}} } } } \\\\
15-
> { { \texttt{r\_f} \eqdef { \texttt{r}.\FIELDf\numplus\texttt{r}.\FIELDg } } } \\\\
1610
$ aslspec operators.spec --render; diff -w generated_macros.tex operators.expected; rm -f generated_macros.tex
1711
Generated LaTeX macros into generated_macros.tex
18-
44c44
19-
< \inferrule{ { { { \texttt{a}\intplus\texttt{b} } \equal \texttt{c} } } \hva\\\\
20-
---
21-
> \inferrule{ { { { \texttt{a}\intplus\texttt{b} } \equal \texttt{c} } } \\\\
2212

2313
$ aslspec type_name.bad
2414
Syntax Error: illegal element-defining identifier: t2 around type_name.bad line 1 column 41

0 commit comments

Comments
 (0)