@@ -5,8 +5,8 @@ structure Z_Machine = struct
5
5
type param = string * string
6
6
7
7
datatype operation_body =
8
- OperDefn of {params: param list, pre: string list, update: string, guard : string list } |
9
- OperComp of {params: param list, body: string} |
8
+ OperDefn of {params: param list, pre: string list, update: string, output : string} |
9
+ OperComp of {params: param list, pre: string list, body: string} |
10
10
OperProm of {promop: string, plens: string} |
11
11
OperEmit of {emit: string}
12
12
@@ -52,7 +52,7 @@ fun mk_chan_show_fun tname ops ctx =
52
52
let val typ = Syntax.read_typ ctx tname in
53
53
Function_Fun.add_fun
54
54
[(Binding.name (" show_" ^ tname), SOME (typ --> @{typ " String.literal" }), NoSyn)]
55
- (map (fn n => ((Binding.empty_atts, mk_chan_show_eq n ctx), [], [])) ops)
55
+ (map (fn n => ((Binding.empty_atts, mk_chan_show_eq n ctx), [], [])) ( ops @ map ( fn n => n ^ " _Out " ) ops) )
56
56
(Function_Fun.fun_config) ctx
57
57
end
58
58
@@ -72,25 +72,23 @@ fun zop_update n = n ^ "_update"
72
72
73
73
(* FIXME: Guard ~> Precondition, Postcondition ~> Guard *)
74
74
75
+ fun gen n ty term ctx = snd (Local_Theory.define
76
+ ((Binding.name n, NoSyn)
77
+ , ((Binding.name (n ^ " _def" )
78
+ , @{attributes [code_unfold, z_defs]})
79
+ , Syntax.check_term ctx (Type.constraint ty term))) ctx);
80
+
75
81
fun def_zop n set st body ctx =
76
82
let open Syntax; open HOLogic; open Local_Theory
77
83
val parm = dest_setT (range_type (Term.type_of (check_term ctx set)))
78
84
in
79
85
(* Generate the type of the operation (i.e. the set of possible parameter values *)
80
- snd (define
81
- ((Binding.name (zop_type n), NoSyn)
82
- , ((Binding.name (zop_type n ^ " _def" )
83
- , @{attributes [code_unfold, z_defs]})
84
- , check_term ctx set)) ctx) |>
85
- (* Generate the precondition *)
86
- snd o define
87
- ((Binding.name n, NoSyn)
88
- , ((Binding.name (n ^ " _def" )
89
- (* It would be better if we could mark these as "code" rather than "code_unfold" to retain
90
- the structure in the language target. For now, code_unfold is required to ensure that
91
- the semantics of enumerated inputs is correctly calculated *)
92
- , @{attributes [code_unfold, z_defs]})
93
- , check_term ctx (Type.constraint (parm --> st --> dummyT) body)))
86
+ gen (zop_type n) dummyT (check_term ctx set) ctx |>
87
+ (* Generate the operation body *)
88
+ (* It would be better if we could mark these as "code" rather than "code_unfold" to retain
89
+ the structure in the language target. For now, code_unfold is required to ensure that
90
+ the semantics of enumerated inputs is correctly calculated *)
91
+ gen n (parm --> st --> dummyT) body
94
92
end
95
93
96
94
fun mk_zinit (Init {name = n, state = s, update = upd}) ctx =
@@ -103,30 +101,30 @@ fun mk_zinit (Init {name = n, state = s, update = upd}) ctx =
103
101
, check_term ctx (Type.constraint (st --> st) (parse_term ctx upd)))) ctx)
104
102
end ;
105
103
106
- fun mk_zop (Operation {name = n, state = s, body = OperDefn {params = ps, pre = pre, update = upd, guard = g }}) ctx =
104
+ fun mk_zop (Operation {name = n, state = s, body = OperDefn {params = ps, pre = pre, update = upd, output = ot }}) ctx =
107
105
let open Syntax; open Library; open Logic; open HOLogic; open Lift_Expr
108
106
val pss = (map (fn (p, t) => (p, lift_expr ctx ((parse_term ctx t)))) ps)
109
107
val pset = params_set (map snd pss)
110
108
val set = SEXP $ pset
111
109
val parm = dest_setT (range_type (Term.type_of (check_term ctx set)))
112
110
val st = read_typ ctx s
113
111
val ppat = mk_tuple (map (free o fst) pss)
112
+
114
113
val ppre =
115
- lambda (free state_id)
116
- (mk_lift_expr ctx (foldr1 mk_conj ((map (parse_term ctx) pre))) $ Bound 0 )
117
- val pguard =
118
114
lambda (free state_id)
119
115
(mk_conj (const @{const_name Set.member} $ ppat $ (pset $ Bound 0 )
120
- , mk_lift_expr ctx (foldr1 mk_conj ((map (parse_term ctx) g))) $ Bound 0 ))
121
-
116
+ , mk_lift_expr ctx (foldr1 mk_conj ((map (parse_term ctx) pre))) $ Bound 0 ))
117
+ val poutput =
118
+ lambda (free state_id)
119
+ ((mk_lift_expr ctx (parse_term ctx ot)) $ Bound 0 )
122
120
val body = (
123
121
(Const (@{const_name " mk_zop" }, (parm --> st --> dummyT) --> dummyT)
124
122
$ tupled_lambda ppat (SEXP $ ppre))
125
123
$ tupled_lambda ppat (Type.constraint (st --> st) (parse_term ctx upd))
126
- $ tupled_lambda ppat (SEXP $ pguard )
124
+ $ tupled_lambda ppat (SEXP $ poutput )
127
125
)
128
-
129
- in def_zop n set st body ctx
126
+ in def_zop n set st body ctx
127
+ |> gen (zop_pre n) (parm --> st --> dummyT) (tupled_lambda ppat (SEXP $ ppre))
130
128
end |
131
129
(*
132
130
(* Generate the precondition *)
@@ -144,36 +142,56 @@ mk_zop (Operation {name = n, state = s, body = OperProm {promop = opr, plens = l
144
142
let open Syntax; open Lift_Expr
145
143
val opr' = read_term ctx opr;
146
144
val pn = fst (dest_Const opr');
147
- val opr_type = const (pn ^ " _type" );
145
+ val opr_type = const (zop_type pn);
146
+ val opr_pre = const (zop_pre pn);
148
147
val lens' = parse_term ctx lens
149
148
val st = read_typ ctx s
150
149
val set = check_term ctx (const @{const_name " promoted_type" } $ lens' $ const @{const_name collection_lens} $ opr_type)
150
+ val ppre = check_term ctx (const @{const_name " promote_pre" } $ lens' $ const @{const_name collection_lens} $ opr_pre)
151
151
val body = const @{const_name " promote_operation" } $ lens' $ const @{const_name collection_lens} $ const pn
152
152
in def_zop n set st body ctx
153
+ |> gen (zop_pre n) (dummyT --> st --> dummyT) ppre
153
154
end |
154
- mk_zop (Operation {name = n, state = s, body = OperComp {params = ps, body = bdy}}) ctx =
155
+ mk_zop (Operation {name = n, state = s, body = OperComp {params = ps, pre = pre, body = bdy}}) ctx =
155
156
let open Syntax; open Library; open Logic; open HOLogic; open Lift_Expr
156
157
val pss = (map (fn (p, t) => (p, lift_expr ctx ((parse_term ctx t)))) ps)
157
158
val pset = params_set (map snd pss)
158
159
val set = SEXP $ pset
160
+ val parm = dest_setT (range_type (Term.type_of (check_term ctx set)))
159
161
val st = read_typ ctx s
160
162
val ppat = mk_tuple (map (free o fst) pss)
163
+ val ppre =
164
+ lambda (free state_id)
165
+ (mk_lift_expr ctx (foldr1 mk_conj ((map (parse_term ctx) pre))) $ Bound 0 )
161
166
val body = tupled_lambda ppat (Type.constraint (st --> dummyT) (parse_term ctx bdy))
162
167
in def_zop n set st body ctx
168
+ |> gen (zop_pre n) (parm --> st --> dummyT) (tupled_lambda ppat (SEXP $ ppre))
163
169
end |
164
170
mk_zop (Operation {name = n, state = s, body = OperEmit {emit = e}}) ctx =
165
171
let open Syntax; open HOLogic; open Lift_Expr
166
172
val set = mk_lift_expr ctx (mk_set dummyT [parse_term ctx e])
167
173
val st = read_typ ctx s
174
+ val parm = dest_setT (range_type (Term.type_of (check_term ctx set)))
168
175
val body = const @{const_abbrev emit_op}
169
- in def_zop n set st body ctx
176
+ in def_zop n set st body ctx
177
+ (* Generate precondition *)
178
+ |> gen (zop_pre n) (parm --> st --> dummyT) (Abs (" p" , parm, SEXP $ lambda (free state_id) @{term True}))
170
179
end ;
171
180
172
181
fun get_zop_ptype n ctx =
173
182
case Proof_Context.read_const {proper = false , strict = false } ctx n of
174
183
Const (_, Type (@{type_name fun}, [a, _])) => a |
175
184
_ => raise Match;
176
-
185
+
186
+ fun get_zop_outtype n ctx =
187
+ case Proof_Context.read_const {proper = false , strict = false } ctx n of
188
+ Const (_, Type (@{type_name fun},
189
+ [_, Type (@{type_name fun},
190
+ [_, Type (@{type_name itree},
191
+ [_, Type (@{type_name prod}, [a, _])])])])) => a |
192
+ _ => raise Match;
193
+
194
+
177
195
fun read_const_name ctx n =
178
196
case Proof_Context.read_const {proper = false , strict = false } ctx n of
179
197
Const (n', _) => n' |
@@ -184,7 +202,12 @@ fun zmachine_body_sem n st init inve ops ends ctx =
184
202
let open Syntax; open HOLogic; open Proof_Context
185
203
val oplist =
186
204
mk_list dummyT
187
- (map (fn n => const @{const_name zop_event} $ read_const {proper = false , strict = false } ctx (firstLower n) $ const (read_const_name ctx (zop_type n)) $ const (read_const_name ctx n)) ops)
205
+ (map (fn n => const @{const_name zop_event}
206
+ $ read_const {proper = false , strict = false } ctx (firstLower n)
207
+ $ const (read_const_name ctx (zop_type n))
208
+ $ const (read_const_name ctx (zop_pre n))
209
+ $ read_const {proper = false , strict = false } ctx (firstLower n ^ " _Out" )
210
+ $ const (read_const_name ctx n)) ops)
188
211
in snd (Local_Theory.define
189
212
((Binding.name n, NoSyn)
190
213
, ((Binding.name (n ^ " _def" )
@@ -196,7 +219,8 @@ fun chantype_name n = n ^ "_chan"
196
219
197
220
fun zmachine_sem (ZMachine {name = n, state = s, init = i, inv = inv, operations = ops, ends = e}) ctx =
198
221
let open Syntax; open HOLogic; open Lift_Expr
199
- val cs = map (fn n => (firstLower n, YXML.content_of (string_of_typ ctx (get_zop_ptype n ctx)))) ops
222
+ val cs = map (fn n => (firstLower n, YXML.content_of (string_of_typ ctx (get_zop_ptype n ctx)))) ops @
223
+ map (fn n => (firstLower n ^ " _Out" , YXML.content_of (string_of_typ ctx (get_zop_outtype n ctx)))) ops
200
224
val st = read_typ ctx s
201
225
val inve = mk_lift_expr ctx (parse_term ctx inv)
202
226
val init = parse_term ctx i
@@ -216,14 +240,15 @@ val parse_operdefn =
216
240
((Scan.optional (@{keyword " params" } |-- repeat1 parse_param) []) --
217
241
(Scan.optional (@{keyword " pre" } |-- repeat1 term) [" True" ]) --
218
242
(Scan.optional (@{keyword " update" } |-- term) " [\< leadsto>]" ) --
219
- (Scan.optional (@{keyword " where " } |-- repeat1 term) [ " True " ] )
220
- >> (fn (((ps, g), upd), post ) => OperDefn {params = ps, pre = g, update = upd, guard = post }))
243
+ (Scan.optional (@{keyword " output " } |-- term) " () " )
244
+ >> (fn (((ps, g), upd), ot ) => OperDefn {params = ps, pre = g, update = upd, output = ot }))
221
245
end
222
246
223
247
val parse_opercomp =
224
248
let open Scan; open Parse in
225
249
((@{keyword " params" } |-- repeat1 parse_param) --
226
- (@{keyword " is" } |-- term)) >> (fn (ps, bdy) => OperComp {params = ps, body = bdy})
250
+ (Scan.optional (@{keyword " pre" } |-- repeat1 term) [" True" ]) --
251
+ (@{keyword " is" } |-- term)) >> (fn ((ps, pre), bdy) => OperComp {params = ps, pre = pre, body = bdy})
227
252
end
228
253
229
254
val parse_operprom =
0 commit comments