From 0d8433a5e7a2d1e91512a6422506dbd19241d128 Mon Sep 17 00:00:00 2001 From: Son Ho Date: Tue, 7 Mar 2023 12:31:18 +0100 Subject: Automate the generation of the lakefile.lean files --- compiler/Driver.ml | 2 +- compiler/Translate.ml | 285 ++++++++++++++++++------------- tests/lean/hashmap_on_disk/lakefile.lean | 10 +- 3 files changed, 170 insertions(+), 127 deletions(-) diff --git a/compiler/Driver.ml b/compiler/Driver.ml index e7425122..476907c1 100644 --- a/compiler/Driver.ml +++ b/compiler/Driver.ml @@ -225,7 +225,7 @@ let () = I.Test.test_functions_symbolic synthesize m; (* Translate the functions *) - Translate.translate_module filename dest_dir m; + Translate.translate_crate filename dest_dir m; (* Print total elapsed time *) log#linfo diff --git a/compiler/Translate.ml b/compiler/Translate.ml index 7ee86b28..ab1addab 100644 --- a/compiler/Translate.ml +++ b/compiler/Translate.ml @@ -266,10 +266,10 @@ let translate_function_to_pure (trans_ctx : trans_ctx) (* Return *) (pure_forward, pure_backwards) -let translate_module_to_pure (crate : A.crate) : +let translate_crate_to_pure (crate : A.crate) : trans_ctx * Pure.type_decl list * (bool * pure_fun_translation) list = (* Debug *) - log#ldebug (lazy "translate_module_to_pure"); + log#ldebug (lazy "translate_crate_to_pure"); (* Compute the type and function contexts *) let type_context, fun_context, global_context = @@ -777,13 +777,11 @@ let extract_file (config : gen_config) (ctx : gen_ctx) (filename : string) (* Flush and close the file *) close_out out -(** Translate a module and write the synthesized code to an output file. - TODO: rename to translate_crate - *) -let translate_module (filename : string) (dest_dir : string) (crate : A.crate) : +(** Translate a crate and write the synthesized code to an output file. *) +let translate_crate (filename : string) (dest_dir : string) (crate : A.crate) : unit = (* Translate the module to the pure AST *) - let trans_ctx, trans_types, trans_funs = translate_module_to_pure crate in + let trans_ctx, trans_types, trans_funs = translate_crate_to_pure crate in (* Initialize the extraction context - for now we extract only to F*. * We initialize the names map by registering the keywords used in the @@ -972,122 +970,121 @@ let translate_module (filename : string) (dest_dir : string) (crate : A.crate) : in (* Extract one or several files, depending on the configuration *) - if !Config.split_files then ( - let base_gen_config = - { - extract_types = false; - extract_decreases_clauses = !Config.extract_decreases_clauses; - extract_template_decreases_clauses = false; - extract_fun_decls = false; - extract_transparent = true; - extract_opaque = false; - extract_state_type = false; - extract_globals = false; - interface = false; - test_trans_unit_functions = false; - } - in - - (* Check if there are opaque types and functions - in which case we need - * to split *) - let has_opaque_types, has_opaque_funs = module_has_opaque_decls gen_ctx in - let has_opaque_types = has_opaque_types || !Config.use_state in + (if !Config.split_files then ( + let base_gen_config = + { + extract_types = false; + extract_decreases_clauses = !Config.extract_decreases_clauses; + extract_template_decreases_clauses = false; + extract_fun_decls = false; + extract_transparent = true; + extract_opaque = false; + extract_state_type = false; + extract_globals = false; + interface = false; + test_trans_unit_functions = false; + } + in - (* Extract the types *) - (* If there are opaque types, we extract in an interface *) - let types_filename_ext = - match !Config.backend with - | FStar -> if has_opaque_types then ".fsti" else ".fst" - | Coq -> ".v" - | Lean -> ".lean" - in - let types_filename = - extract_filebasename ^ file_delimiter ^ "Types" ^ types_filename_ext + (* Check if there are opaque types and functions - in which case we need + * to split *) + let has_opaque_types, has_opaque_funs = module_has_opaque_decls gen_ctx in + let has_opaque_types = has_opaque_types || !Config.use_state in + + (* Extract the types *) + (* If there are opaque types, we extract in an interface *) + let types_filename_ext = + match !Config.backend with + | FStar -> if has_opaque_types then ".fsti" else ".fst" + | Coq -> ".v" + | Lean -> ".lean" + in + let types_filename = + extract_filebasename ^ file_delimiter ^ "Types" ^ types_filename_ext + in + let types_module = module_name ^ module_delimiter ^ "Types" in + let types_config = + { + base_gen_config with + extract_types = true; + extract_opaque = true; + extract_state_type = !Config.use_state; + interface = has_opaque_types; + } + in + extract_file types_config gen_ctx types_filename crate.A.name types_module + ": type definitions" [] []; + + (* Extract the template clauses *) + (if needs_clauses_module && !Config.extract_template_decreases_clauses then + let template_clauses_filename = + extract_filebasename ^ file_delimiter ^ "Clauses" ^ file_delimiter + ^ "Template" ^ ext in - let types_module = module_name ^ module_delimiter ^ "Types" in - let types_config = - { - base_gen_config with - extract_types = true; - extract_opaque = true; - extract_state_type = !Config.use_state; - interface = has_opaque_types; - } + let template_clauses_module = + module_name ^ module_delimiter ^ "Clauses" ^ module_delimiter ^ "Template" in - extract_file types_config gen_ctx types_filename crate.A.name types_module - ": type definitions" [] []; - - (* Extract the template clauses *) - (if needs_clauses_module && !Config.extract_template_decreases_clauses then - let template_clauses_filename = - extract_filebasename ^ file_delimiter ^ "Clauses" ^ file_delimiter - ^ "Template" ^ ext - in - let template_clauses_module = - module_name ^ module_delimiter ^ "Clauses" ^ module_delimiter - ^ "Template" - in - let template_clauses_config = - { base_gen_config with extract_template_decreases_clauses = true } - in - extract_file template_clauses_config gen_ctx template_clauses_filename - crate.A.name template_clauses_module - ": templates for the decreases clauses" [ types_module ] []); - - (* Extract the opaque functions, if needed *) - let opaque_funs_module = - if has_opaque_funs then ( - let opaque_filename = - extract_filebasename ^ file_delimiter ^ "Opaque" ^ opaque_ext - in - let opaque_module = module_name ^ module_delimiter ^ "Opaque" in - let opaque_config = - { - base_gen_config with - extract_fun_decls = true; - extract_transparent = false; - extract_opaque = true; - interface = true; - } - in - let gen_ctx = - { - gen_ctx with - extract_ctx = { gen_ctx.extract_ctx with use_opaque_pre = false }; - } - in - extract_file opaque_config gen_ctx opaque_filename crate.A.name - opaque_module ": opaque function definitions" [] [ types_module ]; - [ opaque_module ]) - else [] + let template_clauses_config = + { base_gen_config with extract_template_decreases_clauses = true } in + extract_file template_clauses_config gen_ctx template_clauses_filename + crate.A.name template_clauses_module + ": templates for the decreases clauses" [ types_module ] []); + + (* Extract the opaque functions, if needed *) + let opaque_funs_module = + if has_opaque_funs then ( + let opaque_filename = + extract_filebasename ^ file_delimiter ^ "Opaque" ^ opaque_ext + in + let opaque_module = module_name ^ module_delimiter ^ "Opaque" in + let opaque_config = + { + base_gen_config with + extract_fun_decls = true; + extract_transparent = false; + extract_opaque = true; + interface = true; + } + in + let gen_ctx = + { + gen_ctx with + extract_ctx = { gen_ctx.extract_ctx with use_opaque_pre = false }; + } + in + extract_file opaque_config gen_ctx opaque_filename crate.A.name + opaque_module ": opaque function definitions" [] [ types_module ]; + [ opaque_module ]) + else [] + in - (* Extract the functions *) - let fun_filename = extract_filebasename ^ file_delimiter ^ "Funs" ^ ext in - let fun_module = module_name ^ module_delimiter ^ "Funs" in - let fun_config = - { - base_gen_config with - extract_fun_decls = true; - extract_globals = true; - test_trans_unit_functions = !Config.test_trans_unit_functions; - } - in - let clauses_module = - if needs_clauses_module then - let clauses_submodule = - if !Config.backend = Lean then module_delimiter ^ "Clauses" else "" - in - [ module_name ^ clauses_submodule ^ module_delimiter ^ "Clauses" ] - else [] - in - let custom_variables = - if has_opaque_funs then [ "section variable (opaque_defs: OpaqueDefs)" ] - else [] - in - extract_file fun_config gen_ctx fun_filename crate.A.name fun_module - ": function definitions" [] ~custom_variables - ([ types_module ] @ opaque_funs_module @ clauses_module)) + (* Extract the functions *) + let fun_filename = extract_filebasename ^ file_delimiter ^ "Funs" ^ ext in + let fun_module = module_name ^ module_delimiter ^ "Funs" in + let fun_config = + { + base_gen_config with + extract_fun_decls = true; + extract_globals = true; + test_trans_unit_functions = !Config.test_trans_unit_functions; + } + in + let clauses_module = + if needs_clauses_module then + let clauses_submodule = + if !Config.backend = Lean then module_delimiter ^ "Clauses" else "" + in + [ module_name ^ clauses_submodule ^ module_delimiter ^ "Clauses" ] + else [] + in + let custom_variables = + if has_opaque_funs then [ "section variable (opaque_defs: OpaqueDefs)" ] + else [] + in + extract_file fun_config gen_ctx fun_filename crate.A.name fun_module + ": function definitions" [] ~custom_variables + ([ types_module ] @ opaque_funs_module @ clauses_module)) else let gen_config = { @@ -1107,4 +1104,54 @@ let translate_module (filename : string) (dest_dir : string) (crate : A.crate) : (* Add the extension for F* *) let extract_filename = extract_filebasename ^ ext in extract_file gen_config gen_ctx extract_filename crate.A.name module_name "" - [] [] + [] []); + + (* Generate the build file *) + match !Config.backend with + | Coq | FStar -> + () + (* Nothing to do - TODO: we might want to generate the _CoqProject file for Coq. + But then we can't modify it if we want to add more files for the proofs + for instance. But we might want to put the proofs elsewhere anyway. + Remark: there is the same problem for Lean actually. + *) + | Lean -> + (* + * Generate the lakefile.lean file + *) + + (* Open the file *) + let filename = Filename.concat dest_dir "lakefile.lean" in + let out = open_out filename in + + (* Generate the content *) + Printf.fprintf out "import Lake\nopen Lake DSL\n\n"; + Printf.fprintf out "require mathlib from git\n"; + Printf.fprintf out + " \"https://github.com/leanprover-community/mathlib4.git\"\n\n"; + + let package_name = StringUtils.to_snake_case module_name in + Printf.fprintf out "package «%s» {\n" package_name; + Printf.fprintf out " -- add package configuration options here\n}\n\n"; + + Printf.fprintf out "lean_lib «Base» {\n"; + Printf.fprintf out " -- add library configuration options here\n}\n\n"; + + Printf.fprintf out "lean_lib «%s» {\n" module_name; + Printf.fprintf out " -- add library configuration options here\n}\n\n"; + + (* No default target for now. + Format would be: + {[ + @[default_target] + lean_exe «package_name» { + root := `Main + } + ]} + *) + + (* Flush and close the file *) + close_out out; + + (* Logging *) + log#linfo (lazy ("Generated: " ^ filename)) diff --git a/tests/lean/hashmap_on_disk/lakefile.lean b/tests/lean/hashmap_on_disk/lakefile.lean index 0ca1ef9b..bdb614cd 100644 --- a/tests/lean/hashmap_on_disk/lakefile.lean +++ b/tests/lean/hashmap_on_disk/lakefile.lean @@ -4,19 +4,15 @@ open Lake DSL require mathlib from git "https://github.com/leanprover-community/mathlib4.git" -package «hashmap» { +package «hashmap_main» { -- add package configuration options here } -lean_lib «HashmapMain» { +lean_lib «Base» { -- add library configuration options here } -lean_lib «Base» { +lean_lib «HashmapMain» { -- add library configuration options here } -@[default_target] -lean_exe «hashmap» { - root := `Main -} -- cgit v1.2.3