diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/isail.ml | 119 | ||||
| -rw-r--r-- | src/rewrites.ml | 191 | ||||
| -rw-r--r-- | src/rewrites.mli | 18 | ||||
| -rw-r--r-- | src/sail.ml | 3 | ||||
| -rw-r--r-- | src/slice.ml | 15 | ||||
| -rw-r--r-- | src/slice.mli | 2 |
6 files changed, 257 insertions, 91 deletions
diff --git a/src/isail.ml b/src/isail.ml index 3eea268d..0b8d4b84 100644 --- a/src/isail.ml +++ b/src/isail.ml @@ -233,6 +233,18 @@ let rec emacs_error l contents = | Parse_ast.Documented (_, l) -> emacs_error l contents | Parse_ast.Generated l -> emacs_error l contents +module SliceNodeSet = Set.Make(Slice.Node) +let slice_roots = ref SliceNodeSet.empty +let slice_cuts = ref SliceNodeSet.empty + +let rec describe_rewrite = + let open Rewrites in + function + | String_rewriter rw -> "<string>" :: describe_rewrite (rw "") + | Bool_rewriter rw -> "<bool>" :: describe_rewrite (rw false) + | Literal_rewriter rw -> "<ocaml/lem/all>" :: describe_rewrite (rw (fun _ -> true)) + | Basic_rewriter rw -> [] + type session = { id : string; files : string list @@ -434,6 +446,55 @@ let handle_input' input = Interactive.ast := append_ast !Interactive.ast ast; Interactive.env := env; interactive_state := initial_state !Interactive.ast Value.primops; + | ":graph" -> + let format = if arg = "" then "svg" else arg in + let dotfile, out_chan = Filename.open_temp_file "sail_graph_" ".gz" in + let image = Filename.temp_file "sail_graph_" ("." ^ format) in + Slice.dot_of_ast out_chan !Interactive.ast; + close_out out_chan; + let _ = Unix.system (Printf.sprintf "dot -T%s %s -o %s" format dotfile image) in + let _ = Unix.system (Printf.sprintf "xdg-open %s" image) in + () + | ":slice_roots" -> + let args = Str.split (Str.regexp " +") arg in + let ids = List.map (fun str -> Slice.Function (mk_id str)) args |> SliceNodeSet.of_list in + slice_roots := SliceNodeSet.union ids !slice_roots + | ":slice_cuts" -> + let args = Str.split (Str.regexp " +") arg in + let ids = List.map (fun str -> Slice.Function (mk_id str)) args |> SliceNodeSet.of_list in + slice_cuts := SliceNodeSet.union ids !slice_cuts + | ":slice" -> + let module G = Graph.Make(Slice.Node) in + let g = Slice.graph_of_ast !Interactive.ast in + let g = G.prune !slice_roots !slice_cuts g in + Interactive.ast := Slice.filter_ast g !Interactive.ast + | ":list_rewrites" -> + List.iter print_endline (List.map fst Rewrites.all_rewrites) + | ":rewrite" -> + let open Rewrites in + let args = Str.split (Str.regexp " +") arg in + let rec parse_args rw args = + match rw, args with + | Basic_rewriter rw, [] -> rw + | Bool_rewriter rw, arg :: args -> parse_args (rw (bool_of_string arg)) args + | String_rewriter rw, arg :: args -> parse_args (rw arg) args + | Literal_rewriter rw, arg :: args -> + begin match arg with + | "ocaml" -> parse_args (rw rewrite_lit_ocaml) args + | "lem" -> parse_args (rw rewrite_lit_lem) args + | "all" -> parse_args (rw (fun _ -> true)) args + | _ -> failwith "target for literal rewrite must be one of ocaml/lem/all" + end + | _, _ -> failwith "Invalid arguments to rewrite" + in + begin match args with + | rw :: args -> + let rw = List.assoc rw Rewrites.all_rewrites in + let rw = parse_args rw args in + Interactive.ast := rw !Interactive.env !Interactive.ast + | [] -> + failwith "Must provide the name of a rewrite, use :list_rewrites for a list of possible rewrites" + end | _ -> unrecognised_command cmd end | Expression str -> @@ -539,6 +600,8 @@ let handle_input' input = let handle_input input = try handle_input' input with + | Failure str -> + print_endline ("Error: " ^ str) | Type_check.Type_error (env, l, err) -> print_endline (Type_error.string_of_type_error err) | Reporting.Fatal_error err -> @@ -547,7 +610,7 @@ let handle_input input = print_endline (Printexc.to_string exn) let () = - (* Auto complete function names based on val specs, or directories if :load command *) + (* Auto complete function names based on val specs, directories if :load command, or rewrites if :rewrite command *) LNoise.set_completion_callback ( fun line_so_far ln_completions -> let line_so_far, last_id = @@ -561,31 +624,36 @@ let () = let n = try String.index line_so_far ' ' with Not_found -> String.length line_so_far in let cmd = Str.string_before line_so_far n in if last_id <> "" then - if cmd = ":load" || cmd = ":l" then - begin - let dirname, basename = Filename.dirname last_id, Filename.basename last_id in - if Sys.file_exists last_id then - LNoise.add_completion ln_completions (line_so_far ^ last_id); - if (try Sys.is_directory dirname with Sys_error _ -> false) then - let contents = Sys.readdir (Filename.concat (Sys.getcwd ()) dirname) in - for i = 0 to Array.length contents - 1 do - if Str.string_match (Str.regexp_string basename) contents.(i) 0 then - let is_dir = (try Sys.is_directory (Filename.concat dirname contents.(i)) with Sys_error _ -> false) in - LNoise.add_completion ln_completions - (line_so_far ^ Filename.concat dirname contents.(i) ^ (if is_dir then Filename.dir_sep else "")) - done - end - else if cmd = ":option" then - List.map (fun (opt, _, _) -> opt) options - |> List.filter (fun opt -> Str.string_match (Str.regexp_string last_id) opt 0) - |> List.map (fun completion -> line_so_far ^ completion) - |> List.iter (LNoise.add_completion ln_completions) - else + begin match cmd with + | ":load" | ":l" -> + let dirname, basename = Filename.dirname last_id, Filename.basename last_id in + if Sys.file_exists last_id then + LNoise.add_completion ln_completions (line_so_far ^ last_id); + if (try Sys.is_directory dirname with Sys_error _ -> false) then + let contents = Sys.readdir (Filename.concat (Sys.getcwd ()) dirname) in + for i = 0 to Array.length contents - 1 do + if Str.string_match (Str.regexp_string basename) contents.(i) 0 then + let is_dir = (try Sys.is_directory (Filename.concat dirname contents.(i)) with Sys_error _ -> false) in + LNoise.add_completion ln_completions + (line_so_far ^ Filename.concat dirname contents.(i) ^ (if is_dir then Filename.dir_sep else "")) + done + | ":rewrite" -> + List.map fst Rewrites.all_rewrites + |> List.filter (fun opt -> Str.string_match (Str.regexp_string last_id) opt 0) + |> List.map (fun completion -> line_so_far ^ completion) + |> List.iter (LNoise.add_completion ln_completions) + | ":option" -> + List.map (fun (opt, _, _) -> opt) options + |> List.filter (fun opt -> Str.string_match (Str.regexp_string last_id) opt 0) + |> List.map (fun completion -> line_so_far ^ completion) + |> List.iter (LNoise.add_completion ln_completions) + | _ -> IdSet.elements !vs_ids |> List.map string_of_id |> List.filter (fun id -> Str.string_match (Str.regexp_string last_id) id 0) |> List.map (fun completion -> line_so_far ^ completion) |> List.iter (LNoise.add_completion ln_completions) + end else () ); @@ -605,6 +673,15 @@ let () = | str -> let args = Str.split (Str.regexp " +") str in match args with + | [":rewrite"] -> hint "<rewrite>" + | ":rewrite" :: rw :: args -> + begin match List.assoc_opt rw Rewrites.all_rewrites with + | Some rw -> + let hints = describe_rewrite rw in + let hints = Util.drop (List.length args) hints in + (match hints with [] -> None | _ -> hint (String.concat " " hints)) + | None -> None + end | [":option"] -> hint "<flag>" | [":option"; flag] -> begin match List.find_opt (fun (opt, _, _) -> flag = opt) options with diff --git a/src/rewrites.ml b/src/rewrites.ml index 502b910c..21422fe2 100644 --- a/src/rewrites.ml +++ b/src/rewrites.ml @@ -4047,7 +4047,6 @@ let rewrite_defs_realise_mappings _ (Defs defs) = in Defs (List.map rewrite_def defs |> List.flatten) - (* Rewrite to make all pattern matches in Coq output exhaustive. Assumes that guards, vector patterns, etc have been rewritten already, and the scattered functions have been merged. @@ -4761,78 +4760,138 @@ let rewrite_defs_coq = [ ("recheck_defs", recheck_defs) ] -let rewrite_defs_ocaml = [ - (* ("undefined", rewrite_undefined); *) - ("no_effect_check", (fun _ defs -> opt_no_effects := true; defs)); - ("realise_mappings", rewrite_defs_realise_mappings); - ("toplevel_string_append", rewrite_defs_toplevel_string_append); - ("pat_string_append", rewrite_defs_pat_string_append); - ("mapping_builtins", rewrite_defs_mapping_patterns); - ("rewrite_undefined", rewrite_undefined_if_gen false); - ("rewrite_defs_vector_string_pats_to_bit_list", rewrite_defs_vector_string_pats_to_bit_list); - ("pat_lits", rewrite_defs_pat_lits rewrite_lit_ocaml); - ("vector_concat_assignments", rewrite_vector_concat_assignments); - ("tuple_assignments", rewrite_tuple_assignments); - ("simple_assignments", rewrite_simple_assignments); - ("remove_not_pats", rewrite_defs_not_pats); - ("remove_vector_concat", rewrite_defs_remove_vector_concat); - ("remove_bitvector_pats", rewrite_defs_remove_bitvector_pats); - ("remove_numeral_pats", rewrite_defs_remove_numeral_pats); - ("exp_lift_assign", rewrite_defs_exp_lift_assign); - ("top_sort_defs", fun _ -> top_sort_defs); - ("simple_types", rewrite_simple_types); - ("overload_cast", rewrite_overload_cast); - (* ("separate_numbs", rewrite_defs_separate_numbs) *) +type rewriter = + | Basic_rewriter of (Env.t -> tannot defs -> tannot defs) + | Bool_rewriter of (bool -> rewriter) + | String_rewriter of (string -> rewriter) + | Literal_rewriter of ((lit -> bool) -> rewriter) + +type rewriter_arg = + | If_mono_arg + | Bool_arg of bool + | String_arg of string + | Literal_arg of string + +let instantiate_rewrite rewriter args = + let selector_function = function + | "ocaml" -> rewrite_lit_ocaml + | "lem" -> rewrite_lit_lem + | "all" -> (fun _ -> true) + | arg -> + raise (Reporting.err_general Parse_ast.Unknown ("No rewrite for literal target \"" ^ arg ^ "\", valid targets are ocaml/lem/all")) + in + let instantiate rewriter arg = + match rewriter, arg with + | Basic_rewriter rw, If_mono_arg -> Basic_rewriter (if_mono rw) + | Bool_rewriter rw, Bool_arg b -> rw b + | String_rewriter rw, String_arg str -> rw str + | Literal_rewriter rw, Literal_arg selector -> rw (selector_function selector) + | _, _ -> + raise (Reporting.err_unreachable Parse_ast.Unknown __POS__ "Invalid rewrite argument") + in + match List.fold_left instantiate rewriter args with + | Basic_rewriter rw -> rw + | _ -> + raise (Reporting.err_general Parse_ast.Unknown "Rewrite not fully instantiated") + +let all_rewrites = [ + ("no_effect_check", Basic_rewriter (fun _ defs -> opt_no_effects := true; defs)); + ("recheck_defs", Basic_rewriter recheck_defs); + ("optimize_recheck_defs", Basic_rewriter (fun _ -> Optimize.recheck)); + ("realise_mappings", Basic_rewriter rewrite_defs_realise_mappings); + ("toplevel_string_append", Basic_rewriter rewrite_defs_toplevel_string_append); + ("pat_string_append", Basic_rewriter rewrite_defs_pat_string_append); + ("mapping_builtins", Basic_rewriter rewrite_defs_mapping_patterns); + ("mono_rewrites", Basic_rewriter mono_rewrites); + ("toplevel_nexps", Basic_rewriter rewrite_toplevel_nexps); + ("monomorphise", Basic_rewriter monomorphise); + ("atoms_to_singletons", Basic_rewriter (fun _ -> Monomorphise.rewrite_atoms_to_singletons)); + ("undefined", Bool_rewriter (fun b -> Basic_rewriter (rewrite_undefined_if_gen b))); + ("vector_string_pats_to_bit_list", Basic_rewriter rewrite_defs_vector_string_pats_to_bit_list); + ("remove_not_pats", Basic_rewriter rewrite_defs_not_pats); + ("pattern_literals", Literal_rewriter (fun f -> Basic_rewriter (rewrite_defs_pat_lits f))); + ("vector_concat_assignments", Basic_rewriter rewrite_vector_concat_assignments); + ("tuple_assignments", Basic_rewriter rewrite_tuple_assignments); + ("simple_assignments", Basic_rewriter rewrite_simple_assignments); + ("remove_vector_concat", Basic_rewriter rewrite_defs_remove_vector_concat); + ("remove_bitvector_pats", Basic_rewriter rewrite_defs_remove_bitvector_pats); + ("remove_numeral_pats", Basic_rewriter rewrite_defs_remove_numeral_pats); + ("exp_lift_assign", Basic_rewriter rewrite_defs_exp_lift_assign); + ("merge_function_clauses", Basic_rewriter merge_funcls); + ("simple_types", Basic_rewriter rewrite_simple_types); + ("overload_cast", Basic_rewriter rewrite_overload_cast); + ("top_sort_defs", Basic_rewriter (fun _ -> top_sort_defs)); + ("split", String_rewriter (fun str -> Basic_rewriter (rewrite_split_fun_ctor_pats str))) ] -let opt_separate_execute = ref false - -let if_separate f env defs = - if !opt_separate_execute then f env defs else defs +let rewriters_ocaml = [ + ("no_effect_check", []); + ("realise_mappings", []); + ("toplevel_string_append", []); + ("pat_string_append", []); + ("mapping_builtins", []); + ("undefined", [Bool_arg false]); + ("vector_string_pats_to_bit_list", []); + ("pattern_literals", [Literal_arg "ocaml"]); + ("vector_concat_assignments", []); + ("tuple_assignments", []); + ("simple_assignments", []); + ("remove_not_pats", []); + ("remove_vector_concat", []); + ("remove_bitvector_pats", []); + ("remove_numeral_pats", []); + ("exp_lift_assign", []); + ("top_sort_defs", []); + ("simple_types", []); + ("overload_cast", []) + ] -let rewrite_defs_c = [ - ("no_effect_check", (fun _ defs -> opt_no_effects := true; defs)); +let rewriters_c = [ + ("no_effect_check", []); + ("realise_mappings", []); + ("toplevel_string_append", []); + ("pat_string_append", []); + ("mapping_builtins", []); + ("mono_rewrites", [If_mono_arg]); + ("recheck_defs", [If_mono_arg]); + ("toplevel_nexps", [If_mono_arg]); + ("monomorphise", [If_mono_arg]); + ("atoms_to_singletons", [If_mono_arg]); + ("recheck_defs", [If_mono_arg]); + ("undefined", [Bool_arg false]); + ("vector_string_pats_to_bit_list", []); + ("remove_not_pats", []); + ("pattern_literals", [Literal_arg "all"]); + ("vector_concat_assignments", []); + ("tuple_assignments", []); + ("simple_assignments", []); + ("remove_vector_concat", []); + ("remove_bitvector_pats", []); + ("exp_lift_assign", []); + ("merge_function_clauses", []); + ("optimize_recheck_defs", []) + ] - (* Remove bidirectional mappings *) - ("realise_mappings", rewrite_defs_realise_mappings); - ("toplevel_string_append", rewrite_defs_toplevel_string_append); - ("pat_string_append", rewrite_defs_pat_string_append); - ("mapping_builtins", rewrite_defs_mapping_patterns); +let rewriters_interpreter = [ + ("no_effect_check", []); + ("realise_mappings", []); + ("toplevel_string_append", []); + ("pat_string_append", []); + ("mapping_builtins", []); + ("undefined", [Bool_arg false]); + ("vector_concat_assignments", []); + ("tuple_assignments", []); + ("simple_assignments", []) + ] - (* Monomorphisation *) - ("mono_rewrites", if_mono mono_rewrites); - ("recheck_defs", if_mono recheck_defs); - ("rewrite_toplevel_nexps", if_mono rewrite_toplevel_nexps); - ("monomorphise", if_mono monomorphise); - ("rewrite_atoms_to_singletons", if_mono (fun _ -> Monomorphise.rewrite_atoms_to_singletons)); - ("recheck_defs", if_mono recheck_defs); +let rewrite_defs_ocaml = + List.map (fun (name, args) -> (name, instantiate_rewrite (List.assoc name all_rewrites) args)) rewriters_ocaml - ("rewrite_undefined", rewrite_undefined_if_gen false); - ("rewrite_defs_vector_string_pats_to_bit_list", rewrite_defs_vector_string_pats_to_bit_list); - ("remove_not_pats", rewrite_defs_not_pats); - ("pat_lits", rewrite_defs_pat_lits (fun _ -> true)); - ("vector_concat_assignments", rewrite_vector_concat_assignments); - ("tuple_assignments", rewrite_tuple_assignments); - ("simple_assignments", rewrite_simple_assignments); - ("remove_vector_concat", rewrite_defs_remove_vector_concat); - ("remove_bitvector_pats", rewrite_defs_remove_bitvector_pats); - ("split_execute", if_separate (rewrite_split_fun_ctor_pats "execute")); - ("exp_lift_assign", rewrite_defs_exp_lift_assign); - ("merge_function_clauses", merge_funcls); - ("recheck_defs", fun _ -> Optimize.recheck) - ] +let rewrite_defs_c = + List.map (fun (name, args) -> (name, instantiate_rewrite (List.assoc name all_rewrites) args)) rewriters_c -let rewrite_defs_interpreter = [ - ("no_effect_check", (fun _ defs -> opt_no_effects := true; defs)); - ("realise_mappings", rewrite_defs_realise_mappings); - ("toplevel_string_append", rewrite_defs_toplevel_string_append); - ("pat_string_append", rewrite_defs_pat_string_append); - ("mapping_builtins", rewrite_defs_mapping_patterns); - ("rewrite_undefined", rewrite_undefined_if_gen false); - ("vector_concat_assignments", rewrite_vector_concat_assignments); - ("tuple_assignments", rewrite_tuple_assignments); - ("simple_assignments", rewrite_simple_assignments) - ] +let rewrite_defs_interpreter = + List.map (fun (name, args) -> (name, instantiate_rewrite (List.assoc name all_rewrites) args)) rewriters_interpreter let rewrite_check_annot = let check_annot exp = diff --git a/src/rewrites.mli b/src/rewrites.mli index 811d52e8..f5b26f3a 100644 --- a/src/rewrites.mli +++ b/src/rewrites.mli @@ -59,7 +59,6 @@ val opt_dmono_analysis : int ref val opt_auto_mono : bool ref val opt_dall_split_errors : bool ref val opt_dmono_continue : bool ref -val opt_separate_execute : bool ref (* Generate a fresh id with the given prefix *) val fresh_id : string -> l -> id @@ -79,6 +78,23 @@ val rewrite_defs_lem : (string * (Env.t -> tannot defs -> tannot defs)) list (* Perform rewrites to exclude AST nodes not supported for coq out*) val rewrite_defs_coq : (string * (Env.t -> tannot defs -> tannot defs)) list +type rewriter = + | Basic_rewriter of (Env.t -> tannot defs -> tannot defs) + | Bool_rewriter of (bool -> rewriter) + | String_rewriter of (string -> rewriter) + | Literal_rewriter of ((lit -> bool) -> rewriter) + +val rewrite_lit_ocaml : lit -> bool +val rewrite_lit_lem : lit -> bool + +type rewriter_arg = + | If_mono_arg + | Bool_arg of bool + | String_arg of string + | Literal_arg of string + +val all_rewrites : (string * rewriter) list + (* Warn about matches where we add a default case for Coq because they're not exhaustive *) val opt_coq_warn_nonexhaustive : bool ref diff --git a/src/sail.ml b/src/sail.ml index 7da36dd9..7416aac2 100644 --- a/src/sail.ml +++ b/src/sail.ml @@ -144,9 +144,6 @@ let options = Arg.align ([ ( "-c_no_rts", Arg.Set C_backend.opt_no_rts, " do not include the Sail runtime" ); - ( "-c_separate_execute", - Arg.Set Rewrites.opt_separate_execute, - " separate execute scattered function into multiple functions"); ( "-c_prefix", Arg.String (fun prefix -> C_backend.opt_prefix := prefix), "<prefix> prefix generated C functions" ); diff --git a/src/slice.ml b/src/slice.ml index f50104c4..036b80d3 100644 --- a/src/slice.ml +++ b/src/slice.ml @@ -283,6 +283,21 @@ let rec graph_of_ast (Defs defs) = | [] -> G.empty +let rec filter_ast' g = + let module NM = Map.Make(Node) in + function + | DEF_fundef fdef :: defs when NM.mem (Function (id_of_fundef fdef)) g -> DEF_fundef fdef :: filter_ast' g defs + | DEF_fundef _ :: defs -> filter_ast' g defs + + | DEF_spec vs :: defs when NM.mem (Function (id_of_val_spec vs)) g -> DEF_spec vs :: filter_ast' g defs + | DEF_spec _ :: defs -> filter_ast' g defs + + | def :: defs -> def :: filter_ast' g defs + + | [] -> [] + +let filter_ast g (Defs defs) = Defs (filter_ast' g defs) + let dot_of_ast out_chan ast = let module G = Graph.Make(Node) in let module NodeSet = Set.Make(Node) in diff --git a/src/slice.mli b/src/slice.mli index 09558ebf..0eefd087 100644 --- a/src/slice.mli +++ b/src/slice.mli @@ -66,3 +66,5 @@ end val graph_of_ast : Type_check.tannot defs -> Graph.Make(Node).graph val dot_of_ast : out_channel -> Type_check.tannot defs -> unit + +val filter_ast : Graph.Make(Node).graph -> Type_check.tannot defs -> Type_check.tannot defs |
