@@ -20,6 +20,8 @@ module Desugar = struct
20
20
let cn_assertion = CF.Cabs_to_ail. desugar_cn_assertion
21
21
22
22
let cn_expr = CF.Cabs_to_ail. desugar_cn_expr
23
+
24
+ let cn_arg = CF.Cabs_to_ail. desugar_cn_arg
23
25
end
24
26
25
27
let get_loc = CF.Annot. get_loc
@@ -997,7 +999,7 @@ let make_function_args f_i loc env args (accesses, requires) =
997
999
aux [] [] env C.LocalState. init_st args
998
1000
999
1001
1000
- let make_fun_with_spec_args f_i loc env args requires =
1002
+ let make_fun_with_spec_args f_i loc env args ( accesses , requires ) =
1001
1003
let rec aux good_lcs env st = function
1002
1004
| ((pure_arg , cn_bt ), ct_ct ) :: rest ->
1003
1005
let ct = convert_ct loc ct_ct in
@@ -1028,7 +1030,7 @@ let make_fun_with_spec_args f_i loc env args requires =
1028
1030
let @ at = aux (* good_lc :: *) good_lcs env st rest in
1029
1031
return (Mu. mComputational ((pure_arg, bt), (loc, None )) at)
1030
1032
| [] ->
1031
- let @ lat = make_largs_with_accesses f_i env st ([] , requires) in
1033
+ let @ lat = make_largs_with_accesses f_i env st (accesses , requires) in
1032
1034
return (Mu. L (Mu. mConstraints (List. rev good_lcs) lat))
1033
1035
in
1034
1036
aux [] env C.LocalState. init_st args
@@ -1204,23 +1206,153 @@ let normalise_label
1204
1206
| None -> assert_error loc ! ^ " non-loop labels" )
1205
1207
1206
1208
1207
- let add_spec_arg_renames
1208
- loc
1209
- args
1210
- arg_cts
1211
- (spec : (CF.Symbol.sym, Ctype.ctype) Cn.cn_fun_spec )
1212
- env
1213
- =
1214
- List. fold_right
1215
- (fun ((fun_sym , _ ), (ct , (spec_sym , _ ))) env ->
1216
- C. add_renamed_computational
1217
- spec_sym
1218
- fun_sym
1219
- (Memory. sbt_of_sct (convert_ct loc ct))
1220
- env)
1221
- (List. combine args (List. combine arg_cts spec.Cn. cn_spec_args))
1222
- env
1209
+ module Spec = struct
1210
+ type 'a parsed =
1211
+ { trusted : Mu .trusted ;
1212
+ accesses : (Cerb_location .t * Id .t ) list ;
1213
+ requires : (Cerb_location .t * (Id .t , 'a ) Cn .cn_condition ) list ;
1214
+ ensures : (Cerb_location .t * (Id .t , 'a ) Cn .cn_condition ) list ;
1215
+ functions : (Cerb_location .t * Id .t ) list
1216
+ }
1217
+
1218
+ let default : _ parsed =
1219
+ { trusted = Mucore. Checked ;
1220
+ accesses = [] ;
1221
+ requires = [] ;
1222
+ ensures = [] ;
1223
+ functions = []
1224
+ }
1225
+
1226
+
1227
+ let combine parsed : _ parsed t =
1228
+ let process
1229
+ Cn. { cn_func_trusted; cn_func_acc_func; cn_func_requires; cn_func_ensures }
1230
+ : _ parsed
1231
+ =
1232
+ let cross_fst x =
1233
+ match x with None -> [] | Some (a , bs ) -> List. map (fun b -> (a, b)) bs
1234
+ in
1235
+ let trusted =
1236
+ match cn_func_trusted with
1237
+ | None -> Mucore. Checked
1238
+ | Some loc -> Mucore. Trusted loc
1239
+ in
1240
+ let accesses, functions =
1241
+ match cn_func_acc_func with
1242
+ | None -> ([] , [] )
1243
+ | Some (loc , Cn. CN_mk_function nm ) -> ([] , [ (loc, nm) ])
1244
+ | Some (loc , Cn. CN_accesses ids ) -> (cross_fst (Some (loc, ids)), [] )
1245
+ in
1246
+ let requires = cross_fst cn_func_requires in
1247
+ let ensures = cross_fst cn_func_ensures in
1248
+ { trusted; accesses; requires; ensures; functions }
1249
+ in
1250
+ let parsed = List. map process parsed in
1251
+ match parsed with
1252
+ | [] -> return default
1253
+ | [ condition ] -> return condition
1254
+ | _ :: _ :: _ ->
1255
+ let trust left right =
1256
+ match (left, right) with
1257
+ | Mucore. Trusted loc , _ -> Mucore. Trusted loc
1258
+ | _ , Mucore. Trusted loc -> Mucore. Trusted loc
1259
+ | _ , _ -> Mucore. Checked
1260
+ in
1261
+ let combine left right =
1262
+ match (left, right) with
1263
+ | { ensures = _ :: _ as ens ; _ } , { requires = (loc , _ ) :: _ ; _ } ->
1264
+ let ens_loc = fst (Option. get (List. last ens)) in
1265
+ fail { loc; msg = Requires_after_ensures { ens_loc } }
1266
+ | ( { trusted = t1; accesses = a1; requires = r1; ensures = e1; functions = f1 },
1267
+ { trusted = t2; accesses = a2; requires = r2; ensures = e2; functions = f2 } )
1268
+ ->
1269
+ return
1270
+ { trusted = trust t1 t2;
1271
+ accesses = a1 @ a2;
1272
+ requires = r1 @ r2;
1273
+ ensures = e1 @ e2;
1274
+ functions = f1 @ f2
1275
+ }
1276
+ in
1277
+ ListM. fold_leftM combine default parsed
1278
+
1279
+
1280
+ let there_can_only_be_one loc fname opt_spec parsed_decl_spec parsed_defn_specs =
1281
+ match (parsed_decl_spec, parsed_defn_specs) with
1282
+ | [] , [] -> return default
1283
+ | [] , (_ :: _ as parsed_defn_specs ) -> combine parsed_defn_specs
1284
+ | parsed_decl_spec :: _ , [] -> combine [ parsed_decl_spec ]
1285
+ | _ :: _ , _ :: _ ->
1286
+ let _, spec = Option. get opt_spec in
1287
+ let doc =
1288
+ Sym. pp fname
1289
+ ^^ colon
1290
+ ^^^ ! ^ " re-specification of CN annotations from:"
1291
+ ^^ break 1
1292
+ ^^^ Locations. pp spec.Cn. cn_decl_loc
1293
+ in
1294
+ fail { loc; msg = Generic doc }
1295
+
1223
1296
1297
+ let desugar_and_add_args decl_d_st spec_args =
1298
+ do_ail_desugar_op decl_d_st
1299
+ @@ CF.State_exception. stExpect_mapM (Desugar. cn_arg Cn. CN_vars ) spec_args
1300
+
1301
+
1302
+ let add_spec_arg_renames loc args arg_cts cn_spec_args env =
1303
+ List. fold_right
1304
+ (fun ((fun_sym , _ ), (ct , (spec_sym , _ ))) env ->
1305
+ C. add_renamed_computational
1306
+ spec_sym
1307
+ fun_sym
1308
+ (Memory. sbt_of_sct (convert_ct loc ct))
1309
+ env)
1310
+ (List. combine args (List. combine arg_cts cn_spec_args))
1311
+ env
1312
+
1313
+
1314
+ let setup_env_desugaring_state loc defn_marker markers_env opt_spec env args arg_cts =
1315
+ match opt_spec with
1316
+ | None -> return (env, CAE. { inner = Pmap. find defn_marker markers_env; markers_env })
1317
+ | Some (decl_marker , spec ) ->
1318
+ let decl_d_st = CAE. { inner = Pmap. find decl_marker markers_env; markers_env } in
1319
+ let @ spec_args, decl_d_st = desugar_and_add_args decl_d_st spec.Cn. cn_decl_args in
1320
+ return (add_spec_arg_renames loc args arg_cts spec_args env, decl_d_st)
1321
+
1322
+
1323
+ let logical_fun_syms d_st mk_functions =
1324
+ ListM. mapM
1325
+ (fun (loc , id ) ->
1326
+ (* from Thomas's convert_c_logical_funs *)
1327
+ let @ logical_fun_sym = do_ail_desugar_rdonly d_st (CAE. lookup_cn_function id) in
1328
+ return (loc, logical_fun_sym))
1329
+ mk_functions
1330
+
1331
+
1332
+ type desugared =
1333
+ { trusted : Mu .trusted ;
1334
+ accesses : (Cerb_location .t * (Sym .t * Ctype .ctype )) list ;
1335
+ requires : (Sym .t , Ctype .ctype ) Cn .cn_condition list ;
1336
+ ensures : (Sym .t , Ctype .ctype ) Cn .cn_condition list ;
1337
+ functions : (Cerb_location .t * Sym .t ) list
1338
+ }
1339
+
1340
+ let desugar
1341
+ global_types
1342
+ d_st
1343
+ ({ trusted; accesses; requires; ensures; functions } : _ parsed )
1344
+ : (desugared * _ * _ ) t
1345
+ =
1346
+ let @ functions = logical_fun_syms d_st functions in
1347
+ let @ accesses = ListM. mapM (desugar_access d_st global_types) accesses in
1348
+ let @ requires, d_st = desugar_conds d_st (List. map snd requires) in
1349
+ debug 6 (lazy (string " desugared requires conds" ));
1350
+ let here = Locations. other __LOC__ in
1351
+ let @ ret_s, ret_d_st = register_new_cn_local (Id. make here " return" ) d_st in
1352
+ let @ ensures, _ = desugar_conds ret_d_st (List. map snd ensures) in
1353
+ debug 6 (lazy (string " desugared ensures conds" ));
1354
+ return ({ trusted; accesses; requires; ensures; functions }, ret_s, ret_d_st)
1355
+ end
1224
1356
1225
1357
let normalise_fun_map_decl
1226
1358
~inherit_loc
@@ -1241,67 +1373,32 @@ let normalise_fun_map_decl
1241
1373
| CF.Milicore. Mi_Fun (_bt , _args , _pe ) -> assert false
1242
1374
| Mi_Proc (loc , _mrk , _ret_bt , args , body , labels ) ->
1243
1375
debug 2 (lazy (item " normalising procedure" (Sym. pp fname)));
1244
- let _, ail_marker, _, ail_args, _ =
1245
- List. assoc Sym. equal fname ail_prog.CF.AilSyntax. function_definitions
1376
+ let @ parsed_defn_specs = Parse. function_spec attrs in
1377
+ let opt_spec, parsed_decl_spec =
1378
+ match Sym.Map. find_opt fname fun_specs with
1379
+ | None -> (None , [] )
1380
+ | Some (decl_marker , spec ) -> (Some (decl_marker, spec), [ spec.Cn. cn_func_spec ])
1246
1381
in
1247
- (* let ail_env = Pmap.find ail_marker ail_prog.markers_env in *)
1248
- (* let d_st = CAE.set_cn_c_identifier_env ail_env d_st in *)
1249
- let d_st = CAE. { inner = Pmap. find ail_marker markers_env; markers_env } in
1250
- let @ trusted, accesses, requires, ensures, mk_functions =
1251
- Parse. function_spec loc attrs
1382
+ let @ parsed =
1383
+ Spec. there_can_only_be_one loc fname opt_spec parsed_decl_spec parsed_defn_specs
1252
1384
in
1253
1385
debug 6 (lazy (string " parsed spec attrs" ));
1254
- let @ mk_functions =
1255
- ListM. mapM
1256
- (fun (loc , `Make_Logical_Function id ) ->
1257
- (* from Thomas's convert_c_logical_funs *)
1258
- let @ logical_fun_sym =
1259
- do_ail_desugar_rdonly d_st (CAE. lookup_cn_function id)
1260
- in
1261
- return (loc, logical_fun_sym))
1262
- mk_functions
1386
+ let _, defn_marker, _, ail_args, _ =
1387
+ List. assoc Sym. equal fname ail_prog.CF.AilSyntax. function_definitions
1263
1388
in
1264
- let defn_spec_sites =
1265
- List. map fst requires @ List. map fst ensures @ List. map fst accesses
1389
+ let @ env, d_st =
1390
+ Spec. setup_env_desugaring_state
1391
+ loc
1392
+ defn_marker
1393
+ markers_env
1394
+ opt_spec
1395
+ env
1396
+ args
1397
+ (List. map snd arg_cts)
1266
1398
in
1267
- let @ accesses = ListM. mapM (desugar_access d_st global_types) accesses in
1268
- let @ requires, d_st = desugar_conds d_st (List. map snd requires) in
1269
- debug 6 (lazy (string " desugared requires conds" ));
1270
- let here = Locations. other __LOC__ in
1271
- let @ ret_s, ret_d_st = register_new_cn_local (Id. make here " return" ) d_st in
1272
- let @ ensures, _ret_d_st = desugar_conds ret_d_st (List. map snd ensures) in
1273
- debug 6 (lazy (string " desugared ensures conds" ));
1274
- let @ spec_req, spec_ens, env =
1275
- match Sym.Map. find_opt fname fun_specs with
1276
- | Some (_ , spec ) ->
1277
- let @ () =
1278
- match defn_spec_sites with
1279
- | [] -> return ()
1280
- | loc2 :: _ ->
1281
- fail
1282
- { loc = loc2;
1283
- msg =
1284
- Generic
1285
- (Sym. pp fname
1286
- ^^ colon
1287
- ^^^ ! ^ " re-specification of CN annotations from:"
1288
- ^^ break 1
1289
- ^^^ Locations. pp spec.Cn. cn_spec_loc)
1290
- }
1291
- in
1292
- let env = add_spec_arg_renames loc args (List. map snd arg_cts) spec env in
1293
- let env =
1294
- C. add_renamed_computational
1295
- spec.Cn. cn_spec_ret_name
1296
- ret_s
1297
- (Memory. sbt_of_sct (convert_ct loc ret_ct))
1298
- env
1299
- in
1300
- return (spec.cn_spec_requires, spec.cn_spec_ensures, env)
1301
- | _ -> return ([] , [] , env)
1399
+ let @ { trusted; accesses; requires; ensures; functions }, ret_s, d_st =
1400
+ Spec. desugar global_types d_st parsed
1302
1401
in
1303
- let requires = requires @ spec_req in
1304
- let ensures = ensures @ spec_ens in
1305
1402
debug 6 (lazy (! ^ " function requires/ensures" ^^^ Sym. pp fname));
1306
1403
debug 6 (lazy (CF.Pp_ast. pp_doc_tree (dtree_of_accesses accesses)));
1307
1404
debug 6 (lazy (CF.Pp_ast. pp_doc_tree (dtree_of_requires requires)));
@@ -1345,38 +1442,34 @@ let normalise_fun_map_decl
1345
1442
(List. combine (List. combine ail_args arg_cts) args)
1346
1443
(accesses, requires)
1347
1444
in
1348
- (* let ft = at_of_arguments (fun (_body, _labels, rt) -> rt) args_and_body in *)
1349
1445
let desugared_spec = Mu. { accesses = List. map snd accesses; requires; ensures } in
1350
- return
1351
- (Some (Mu. Proc { loc; args_and_body; trusted; desugared_spec }, mk_functions))
1446
+ return (Some (Mu. Proc { loc; args_and_body; trusted; desugared_spec }, functions))
1352
1447
| Mi_ProcDecl (loc , ret_bt , _bts ) ->
1353
1448
(match Sym.Map. find_opt fname fun_specs with
1354
- | Some (_ail_marker , (spec : (CF.Symbol.sym, Ctype.ctype) Cn.cn_fun_spec )) ->
1449
+ | Some (ail_marker , (spec : _ Cn.cn_decl_spec )) ->
1355
1450
let @ () =
1356
1451
check_against_core_bt loc ret_bt (Memory. bt_of_sct (convert_ct loc ret_ct))
1357
1452
in
1358
- (* let@ (requires, d_st2) = desugar_conds d_st spec.cn_spec_requires in *)
1359
- (* FIXME: do we need to note the return var somehow? *)
1360
- (* let@ (ensures, _) = desugar_conds d_st spec.cn_spec_ensures in *)
1453
+ let @ parsed = Spec. combine [ spec.cn_func_spec ] in
1454
+ let d_st = CAE. { inner = Pmap. find ail_marker markers_env; markers_env } in
1455
+ let @ spec_args, d_st = Spec. desugar_and_add_args d_st spec.cn_decl_args in
1456
+ let @ { trusted = _; accesses; requires; ensures; functions }, ret_s, _ =
1457
+ Spec. desugar global_types d_st parsed
1458
+ in
1361
1459
let @ args_and_rt =
1362
1460
make_fun_with_spec_args
1363
1461
(fun env st ->
1364
1462
let @ returned =
1365
- C. make_rt
1366
- loc
1367
- env
1368
- st
1369
- (spec.cn_spec_ret_name, ret_ct)
1370
- ([] , spec.cn_spec_ensures)
1463
+ C. make_rt loc env st (ret_s, ret_ct) (accesses, ensures)
1371
1464
in
1372
1465
return returned)
1373
1466
loc
1374
1467
env
1375
- (List. combine spec.cn_spec_args (List. map snd arg_cts))
1376
- spec.cn_spec_requires
1468
+ (List. combine spec_args (List. map snd arg_cts))
1469
+ (accesses, requires)
1377
1470
in
1378
1471
let ft = at_of_arguments Tools. id args_and_rt in
1379
- return (Some (Mu. ProcDecl (loc, Some ft), [] ))
1472
+ return (Some (Mu. ProcDecl (loc, Some ft), functions ))
1380
1473
| _ -> return (Some (Mu. ProcDecl (loc, None ), [] )))
1381
1474
| Mi_BuiltinDecl (_loc , _bt , _bts ) -> assert false )
1382
1475
@@ -1556,8 +1649,8 @@ let normalise_file ~inherit_loc ((fin_markers_env : CAE.fin_markers_env), ail_pr
1556
1649
let env = List. fold_left register_glob env globs in
1557
1650
let fun_specs_map =
1558
1651
List. fold_right
1559
- (fun (id , spec ) acc -> Sym.Map. add spec. Cn. cn_spec_name (id, spec) acc)
1560
- ail_prog.cn_fun_specs
1652
+ (fun (id , key , spec ) acc -> Sym.Map. add key (id, spec) acc)
1653
+ ail_prog.cn_decl_specs
1561
1654
Sym.Map. empty
1562
1655
in
1563
1656
let @ funs, mk_functions =
0 commit comments