Skip to content

Commit 0adb65c

Browse files
Merge pull request herd#1451 from herd/aslspec
[asl] A DSL for specifying semantics fo ASL - phase 1
2 parents 34d27e3 + 5f19e98 commit 0adb65c

65 files changed

Lines changed: 5498 additions & 1856 deletions

Some content is hidden

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

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@ asllib/doc/*.synctex.gz
2323
asllib/doc/*.toc
2424
asllib/doc/*.fls
2525
asllib/doc/*.fdb_latexmk
26+
asllib/doc/generated_elements.tex

asllib/aslspec/AST.ml

Lines changed: 362 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,362 @@
1+
(** A module for representing the abstract syntax trees of aslspec --- the
2+
domain-specific language that defines the semantics-specification for ASL.
3+
*)
4+
5+
exception SpecError of string
6+
7+
type type_kind = TypeKind_Generic | TypeKind_AST
8+
9+
(** Terms for constructing types out of other types, with [Label t] being the
10+
leaf case.
11+
12+
In the context of a type definition, a [Label] variant defines a new label -
13+
a type representing just this single label. In other contexts, for example a
14+
type variant appearing in the signature of a relation, this can either refer
15+
to a type name of a label defined as a type variant. *)
16+
type type_term =
17+
| Label of string
18+
(** Either a set containing the single value named by the given string or
19+
a reference to a type with the given name. *)
20+
| Powerset of { term : type_term; finite : bool }
21+
(** A set containing all subsets of the given type. If [finite] is true
22+
then only the finite subsets are included. *)
23+
| Option of type_term
24+
(** Either the empty set of a set containing a single value of the given
25+
type. *)
26+
| LabelledTuple of {
27+
label_opt : string option;
28+
components : opt_named_type_term list;
29+
}
30+
(** A set containing all optionally-labelled tuples formed by the given
31+
components. An unlabelled tuple containing a single term is a special
32+
case - its domain is the domain of that term; this serves to reference
33+
types defined elsewhere. *)
34+
| LabelledRecord of {
35+
label_opt : string option;
36+
fields : named_type_term list;
37+
}
38+
(** A set containing all optionally-labelled records formed by the given
39+
fields. *)
40+
| List of { maybe_empty : bool; member_type : type_term }
41+
(** A set containing all sequences of the given member type. If
42+
[maybe_empty] is true, the list may also be empty. *)
43+
| ConstantsSet of string list
44+
(** A set containing all constants formed by the given names. *)
45+
| Function of { from_type : type_term; to_type : type_term; total : bool }
46+
(** A set containing all functions formed by the given types. If [total]
47+
is true, the function is total, otherwise it is partial. *)
48+
49+
and named_type_term = string * type_term
50+
(** A term associated with a variable name. *)
51+
52+
and opt_named_type_term = string option * type_term
53+
(** A term optionally associated with a variable name. *)
54+
55+
(** [make_tuple components] Constructs an unlabelled tuple for the tuple
56+
components [components]. *)
57+
let make_tuple components = LabelledTuple { label_opt = None; components }
58+
59+
(** [make_labelled_tuple label components] Constructs a tuple labelled [label]
60+
and tuple components [components]. *)
61+
let make_labelled_tuple label components =
62+
LabelledTuple { label_opt = Some label; components }
63+
64+
(** [make_record fields] Constructs an unlabelled record with fields [fields].
65+
*)
66+
let make_record fields = LabelledRecord { label_opt = None; fields }
67+
68+
(** [make_labelled_record label fields] Constructs a record labelled [label] and
69+
fields [fields]. *)
70+
let make_labelled_record label fields =
71+
LabelledRecord { label_opt = Some label; fields }
72+
73+
(** Specifies how to layout a compound term. *)
74+
type layout =
75+
| Unspecified
76+
(** No specific layout, appropriate for atomic terms and terms with
77+
singleton lists. *)
78+
| Horizontal of layout list
79+
(** Specifies a horizontal layout for terms where the layout for each term
80+
is specified individually. *)
81+
| Vertical of layout list
82+
(** Specifies a vertical layout for terms where the layout for each term
83+
is specified individually. *)
84+
85+
(** A module for totally ordered attribute keys. *)
86+
module AttributeKey = struct
87+
type t =
88+
| Prose_Description (** A description of the element in prose. *)
89+
| Prose_Application
90+
(** A description of the element in prose describing its application in
91+
an inference rule premise. *)
92+
| Math_Macro (** A LaTeX macro for the element. *)
93+
| Math_Layout (** The layout of the element in a mathematical context. *)
94+
95+
(* A total ordering on attribute keys. *)
96+
let compare a b =
97+
let key_to_int = function
98+
| Prose_Description -> 0
99+
| Prose_Application -> 1
100+
| Math_Macro -> 2
101+
| Math_Layout -> 3
102+
in
103+
let a_int = key_to_int a in
104+
let b_int = key_to_int b in
105+
Stdlib.compare a_int b_int
106+
107+
(** Converts an attribute key with the same string as the corresponding token.
108+
*)
109+
let to_str = function
110+
| Prose_Description -> "prose_description"
111+
| Prose_Application -> "prose_application"
112+
| Math_Macro -> "math_macro"
113+
| Math_Layout -> "math_layout"
114+
end
115+
116+
(** A value associated with an attribute key. *)
117+
type attribute = StringAttribute of string | MathLayoutAttribute of layout
118+
119+
(** A module for associating attributes with attribute keys. *)
120+
module Attributes = struct
121+
include Map.Make (AttributeKey)
122+
123+
type 'a map = 'a t
124+
(** Shadows [Map.t] with a string-to-string map type. *)
125+
126+
type t = attribute map
127+
128+
(** Shadows [of_list] by raising a [SpecError] exception on pairs containing
129+
the same key. *)
130+
let of_list pairs =
131+
List.fold_left
132+
(fun acc_map (k, v) ->
133+
if mem k acc_map then
134+
let msg =
135+
Format.sprintf {| encountered second occurrence of attribute '%s'|}
136+
(AttributeKey.to_str k)
137+
in
138+
raise (SpecError msg)
139+
else add k v acc_map)
140+
empty pairs
141+
end
142+
143+
(** A datatype for top-level type terms used in the definition of a type. *)
144+
module TypeVariant : sig
145+
type t = { type_kind : type_kind; term : type_term; att : Attributes.t }
146+
147+
val make : type_kind -> type_term -> (AttributeKey.t * attribute) list -> t
148+
val attributes_to_list : t -> (AttributeKey.t * attribute) list
149+
val prose_description : t -> string
150+
val math_macro : t -> string option
151+
152+
val math_layout : t -> layout option
153+
(** The layout of the type term when rendered in the context of its containing
154+
type. *)
155+
end = struct
156+
type t = { type_kind : type_kind; term : type_term; att : Attributes.t }
157+
158+
let make type_kind term attribute_pairs =
159+
{ type_kind; term; att = Attributes.of_list attribute_pairs }
160+
161+
open Attributes
162+
163+
let attributes_to_list self = bindings self.att
164+
165+
let prose_description self =
166+
match Attributes.find_opt AttributeKey.Prose_Description self.att with
167+
| Some (StringAttribute s) -> s
168+
| _ -> assert false
169+
170+
let math_macro self =
171+
match find_opt AttributeKey.Math_Macro self.att with
172+
| Some (StringAttribute s) -> Some s
173+
| _ -> None
174+
175+
let math_layout self =
176+
match find_opt AttributeKey.Math_Layout self.att with
177+
| Some (MathLayoutAttribute layout) -> Some layout
178+
| _ -> None
179+
end
180+
181+
(** A datatype for a type definition. *)
182+
module Type : sig
183+
type t = {
184+
name : string;
185+
type_kind : type_kind;
186+
variants : TypeVariant.t list;
187+
att : Attributes.t;
188+
}
189+
190+
val make :
191+
type_kind ->
192+
string ->
193+
TypeVariant.t list ->
194+
(AttributeKey.t * attribute) list ->
195+
t
196+
197+
val attributes_to_list : t -> (AttributeKey.t * attribute) list
198+
val prose_description : t -> string
199+
val math_macro : t -> string option
200+
201+
val math_layout : t -> layout option
202+
(** The layout used when rendered as a stand-alone type definition. *)
203+
end = struct
204+
type t = {
205+
name : string;
206+
type_kind : type_kind;
207+
variants : TypeVariant.t list;
208+
att : Attributes.t;
209+
}
210+
211+
let make type_kind name variants attribute_pairs =
212+
(* The [type_kind] of the variants is the [type_kind] given above. *)
213+
let variants_with_parent_type_kind =
214+
List.map
215+
(fun ({ TypeVariant.term } as variant) ->
216+
let attribute_pairs = TypeVariant.attributes_to_list variant in
217+
TypeVariant.make type_kind term attribute_pairs)
218+
variants
219+
in
220+
{
221+
type_kind;
222+
name;
223+
variants = variants_with_parent_type_kind;
224+
att = Attributes.of_list attribute_pairs;
225+
}
226+
227+
open Attributes
228+
229+
let attributes_to_list self = Attributes.bindings self.att
230+
231+
let prose_description self =
232+
match Attributes.find_opt AttributeKey.Prose_Description self.att with
233+
| Some (StringAttribute s) -> s
234+
| _ -> assert false
235+
236+
let math_macro self =
237+
match find_opt AttributeKey.Math_Macro self.att with
238+
| Some (StringAttribute s) -> Some s
239+
| _ -> None
240+
241+
let math_layout self =
242+
match find_opt AttributeKey.Math_Layout self.att with
243+
| Some (MathLayoutAttribute layout) -> Some layout
244+
| _ -> None
245+
end
246+
247+
(** A datatype for a relation definition. *)
248+
module Relation : sig
249+
type t = {
250+
name : string;
251+
input : opt_named_type_term list;
252+
output : type_term list;
253+
att : Attributes.t;
254+
}
255+
256+
val make :
257+
string ->
258+
opt_named_type_term list ->
259+
type_term list ->
260+
(AttributeKey.t * attribute) list ->
261+
t
262+
263+
val attributes_to_list : t -> (AttributeKey.t * attribute) list
264+
val prose_description : t -> string
265+
val math_macro : t -> string option
266+
val prose_application : t -> string
267+
268+
val math_layout : t -> layout option
269+
(** The layout used when rendered as a stand-alone relation definition. *)
270+
end = struct
271+
type t = {
272+
name : string;
273+
input : opt_named_type_term list;
274+
output : type_term list;
275+
att : Attributes.t;
276+
}
277+
278+
let make name input output attributes =
279+
{ name; input; output; att = Attributes.of_list attributes }
280+
281+
let attributes_to_list self = Attributes.bindings self.att
282+
283+
open Attributes
284+
285+
let prose_description self =
286+
match Attributes.find_opt AttributeKey.Prose_Description self.att with
287+
| Some (StringAttribute s) -> s
288+
| _ -> assert false
289+
290+
let math_macro self =
291+
match find_opt AttributeKey.Math_Macro self.att with
292+
| Some (StringAttribute s) -> Some s
293+
| _ -> None
294+
295+
let prose_application self =
296+
match find_opt AttributeKey.Prose_Application self.att with
297+
| Some (StringAttribute s) -> s
298+
| _ -> assert false
299+
300+
let math_layout self =
301+
match find_opt AttributeKey.Math_Layout self.att with
302+
| Some (MathLayoutAttribute layout) -> Some layout
303+
| _ -> None
304+
end
305+
306+
(** A datatype for a constant definition. *)
307+
module Constant : sig
308+
type t = { name : string; att : Attributes.t }
309+
310+
val make : string -> (AttributeKey.t * attribute) list -> t
311+
val attributes_to_list : t -> (AttributeKey.t * attribute) list
312+
val prose_description : t -> string
313+
val math_macro : t -> string option
314+
end = struct
315+
type t = { name : string; att : Attributes.t }
316+
317+
let attributes_to_list self = Attributes.bindings self.att
318+
319+
open Attributes
320+
321+
let make name attributes = { name; att = Attributes.of_list attributes }
322+
323+
let prose_description self =
324+
match Attributes.find_opt AttributeKey.Prose_Description self.att with
325+
| Some (StringAttribute s) -> s
326+
| _ -> assert false
327+
328+
let math_macro self =
329+
match find_opt AttributeKey.Math_Macro self.att with
330+
| Some (StringAttribute s) -> Some s
331+
| _ -> None
332+
end
333+
334+
(** A datatype for grouping (subsets of) type definitions. *)
335+
module TypesRender : sig
336+
type type_subset_pointer = { type_name : string; variant_names : string list }
337+
type render = { name : string; pointers : type_subset_pointer list }
338+
339+
val make : string -> (string * string list) list -> render
340+
end = struct
341+
type type_subset_pointer = { type_name : string; variant_names : string list }
342+
type render = { name : string; pointers : type_subset_pointer list }
343+
344+
let make name pointer_pairs =
345+
{
346+
name;
347+
pointers =
348+
List.map
349+
(fun (type_name, variant_names) -> { type_name; variant_names })
350+
pointer_pairs;
351+
}
352+
end
353+
354+
(** The top-level elements of a specification. *)
355+
type elem =
356+
| Elem_Type of Type.t
357+
| Elem_Relation of Relation.t
358+
| Elem_Constant of Constant.t
359+
| Elem_Render of TypesRender.render
360+
361+
type t = elem list
362+
(** A specification is a list of top-level elements. *)

0 commit comments

Comments
 (0)