@@ -1116,25 +1116,40 @@ let doc_val ctx pat exp =
1116
1116
let base_pp = doc_exp false ctx exp in
1117
1117
nest 2 (group (string " def" ^^ space ^^ idpp ^^ typpp ^^ space ^^ coloneq ^/^ base_pp))
1118
1118
1119
- let rec doc_defs_rec ctx defs types docdefs =
1119
+ let should_print_function_def def =
1120
+ match def with
1121
+ | DEF_aux (DEF_fundef fdef , dannot ) -> not (Env. is_extern (id_of_fundef fdef) dannot.env " lean" )
1122
+ | DEF_aux (DEF_let (LB_aux (LB_val (pat , exp ), _ )), _ ) -> true
1123
+ | _ -> false
1124
+
1125
+ let rec doc_defs_rec ctx defs types (former_funcs : document list ) (docdefs : document ) =
1120
1126
match defs with
1121
- | [] -> (types, docdefs)
1127
+ | [] -> (types, former_funcs @ [ docdefs] )
1122
1128
| DEF_aux (DEF_fundef fdef , dannot ) :: defs' ->
1123
1129
let env = dannot.env in
1124
1130
let pp_f =
1125
1131
if Env. is_extern (id_of_fundef fdef) env " lean" then docdefs
1126
1132
else docdefs ^^ group (doc_fundef ctx fdef) ^/^ hardline
1127
1133
in
1128
- doc_defs_rec ctx defs' types pp_f
1134
+ doc_defs_rec ctx defs' types former_funcs pp_f
1129
1135
| DEF_aux (DEF_type tdef , _ ) :: defs' when List. mem (string_of_id (id_of_type_def tdef)) ! opt_extern_types ->
1130
- doc_defs_rec ctx defs' types docdefs
1136
+ doc_defs_rec ctx defs' types former_funcs docdefs
1131
1137
| DEF_aux (DEF_type tdef , _ ) :: defs' ->
1132
- doc_defs_rec ctx defs' (types ^^ group (doc_typdef ctx tdef) ^/^ hardline) docdefs
1138
+ doc_defs_rec ctx defs' (types ^^ group (doc_typdef ctx tdef) ^/^ hardline) former_funcs docdefs
1133
1139
| DEF_aux (DEF_let (LB_aux (LB_val (pat , exp ), _ )), _ ) :: defs' ->
1134
- doc_defs_rec ctx defs' types (docdefs ^^ group (doc_val ctx pat exp) ^/^ hardline)
1135
- | _ :: defs' -> doc_defs_rec ctx defs' types docdefs
1136
-
1137
- let doc_defs ctx defs = doc_defs_rec ctx defs empty empty
1140
+ doc_defs_rec ctx defs' types former_funcs (docdefs ^^ group (doc_val ctx pat exp) ^/^ hardline)
1141
+ | DEF_aux (DEF_pragma (" include_start" , Pragma_line (file, _)), _) :: defs'
1142
+ | DEF_aux (DEF_pragma (" file_start" , Pragma_line (file, _)), _) :: defs'
1143
+ | DEF_aux (DEF_pragma (" include_end" , Pragma_line (file, _)), _) :: defs'
1144
+ | DEF_aux (DEF_pragma (" file_end" , Pragma_line (file, _)), _) :: defs'
1145
+ when Filename. check_suffix file " .sail" ->
1146
+ if docdefs = empty then doc_defs_rec ctx defs' types former_funcs docdefs
1147
+ else doc_defs_rec ctx defs' types (former_funcs @ [docdefs]) empty
1148
+ | d :: defs' ->
1149
+ if should_print_function_def d then failwith " this case of doc_defs_rec should be unreachable"
1150
+ else doc_defs_rec ctx defs' types former_funcs docdefs
1151
+
1152
+ let doc_defs ctx defs = doc_defs_rec ctx defs empty [] empty
1138
1153
1139
1154
(* Remove all imports for now, they will be printed in other files. Probably just for testing. *)
1140
1155
let rec remove_imports (defs : (Libsail.Type_check.tannot, Libsail.Type_check.env) def list ) depth =
@@ -1258,8 +1273,40 @@ let populate_fun_args defs =
1258
1273
in
1259
1274
List. fold_left (fun args d -> add_args args d) Bindings. empty defs
1260
1275
1261
- let pp_ast_lean (env : Type_check.env ) effect_info ({ defs; _ } as ast : Libsail.Type_check.typed_ast ) types_file
1262
- funcs_file =
1276
+ let rec collect_import_files_aux defs file_stack last_namespace ret =
1277
+ match defs with
1278
+ | [] -> ret
1279
+ | DEF_aux (DEF_pragma (" include_start" , Pragma_line (file, _)), _) :: ds
1280
+ | DEF_aux (DEF_pragma (" file_start" , Pragma_line (file, _)), _) :: ds
1281
+ when Filename. check_suffix file " .sail" ->
1282
+ collect_import_files_aux ds (file :: file_stack) last_namespace ret
1283
+ | DEF_aux (DEF_pragma (" include_end" , Pragma_line (file, _)), _) :: ds
1284
+ | DEF_aux (DEF_pragma (" file_end" , Pragma_line (file, _)), _) :: ds
1285
+ when Filename. check_suffix file " .sail" -> (
1286
+ match file_stack with
1287
+ | f :: fs -> collect_import_files_aux ds fs last_namespace ret
1288
+ | _ -> failwith " should not be reachable"
1289
+ )
1290
+ | d :: ds -> (
1291
+ match file_stack with
1292
+ | f :: _ ->
1293
+ if should_print_function_def d && not (last_namespace = Some f) then
1294
+ collect_import_files_aux ds file_stack (Some f) (ret @ [f])
1295
+ else collect_import_files_aux ds file_stack last_namespace ret
1296
+ | _ -> failwith " should not be reachable"
1297
+ )
1298
+
1299
+ let collect_import_files defs base =
1300
+ let res = collect_import_files_aux defs [base] None [] in
1301
+ if res = [] then [base] else res
1302
+
1303
+ let rec take n xs = match (n, xs) with 0 , _ -> [] | n , x :: xs -> x :: take (n - 1 ) xs | n , xs -> xs
1304
+
1305
+ let rec last xs =
1306
+ match xs with [] -> failwith " cannot take last element of empty list" | [x] -> x | x :: xs -> last xs
1307
+
1308
+ let pp_ast_lean (env : Type_check.env ) effect_info ({ defs; _ } as ast : Libsail.Type_check.typed_ast ) out_name_camel
1309
+ types_file imp_funcs_files funcs_file noncomputable =
1263
1310
let regs = State. find_registers defs in
1264
1311
let fun_args = populate_fun_args defs in
1265
1312
let global = { effect_info; fun_args } in
@@ -1271,12 +1318,29 @@ let pp_ast_lean (env : Type_check.env) effect_info ({ defs; _ } as ast : Libsail
1271
1318
in
1272
1319
let monad = doc_monad_abbrev defs has_registers in
1273
1320
let instantiations = doc_instantiations ctx env in
1274
- let types, fundefs = doc_defs ctx defs in
1275
- let fundefs = string " namespace Functions\n\n " ^^ fundefs ^^ string " end Functions\n " in
1321
+ let types, all_fundefss = doc_defs ctx defs in
1322
+ let imp_fundefss, main_fundefs =
1323
+ if imp_funcs_files = [] then ([] , concat all_fundefss)
1324
+ else (
1325
+ let imp_fundefss = take (List. length all_fundefss - 1 ) all_fundefss in
1326
+ let main_fundefs = last all_fundefss in
1327
+ (imp_fundefss, main_fundefs)
1328
+ )
1329
+ in
1330
+ let main_fundefs = main_fundefs ^^ string (" end " ^ out_name_camel ^ " .Functions" ) ^^ hardline in
1276
1331
let main_function =
1277
- if ! the_main_function_has_been_seen then main_function_stub effect_info has_registers else empty
1332
+ if ! the_main_function_has_been_seen then (
1333
+ let stub = main_function_stub effect_info has_registers in
1334
+ [string (" open " ^ out_name_camel ^ " .Functions\n\n " ) ^^ stub]
1335
+ )
1336
+ else []
1278
1337
in
1279
1338
let opens = IdSet. fold (fun id doc -> string " open " ^^ doc_id_ctor id ^^ hardline ^^ doc) ! opens empty in
1280
1339
print types_file (types ^^ register_refs ^^ monad ^^ instantiations);
1281
- print funcs_file (opens ^^ hardline ^^ fundefs ^^ string " open Functions\n\n " ^^ main_function);
1340
+ let _ =
1341
+ List. map2
1342
+ (fun file defs -> print file (separate hardline (remove_empties [opens; defs])))
1343
+ imp_funcs_files imp_fundefss
1344
+ in
1345
+ print funcs_file (separate hardline (remove_empties ([opens; main_fundefs] @ main_function)));
1282
1346
! the_main_function_has_been_seen
0 commit comments