diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/c_backend.ml | 2 | ||||
| -rw-r--r-- | src/constant_fold.ml | 2 | ||||
| -rw-r--r-- | src/error_format.ml | 95 | ||||
| -rw-r--r-- | src/interactive.ml | 7 | ||||
| -rw-r--r-- | src/interactive.mli | 9 | ||||
| -rw-r--r-- | src/interpreter.ml | 2 | ||||
| -rw-r--r-- | src/isail.ml | 74 | ||||
| -rw-r--r-- | src/pretty_print_coq.ml | 2 | ||||
| -rw-r--r-- | src/process_file.ml | 2 | ||||
| -rw-r--r-- | src/reporting.ml | 24 | ||||
| -rw-r--r-- | src/reporting.mli | 8 | ||||
| -rw-r--r-- | src/rewrites.ml | 18 | ||||
| -rw-r--r-- | src/sail.ml | 20 | ||||
| -rw-r--r-- | src/type_check.ml | 486 | ||||
| -rw-r--r-- | src/type_check.mli | 10 | ||||
| -rw-r--r-- | src/type_error.ml | 150 |
16 files changed, 476 insertions, 435 deletions
diff --git a/src/c_backend.ml b/src/c_backend.ml index 79d4693a..53e7dc88 100644 --- a/src/c_backend.ml +++ b/src/c_backend.ml @@ -3460,4 +3460,4 @@ let compile_ast ctx c_includes (Defs defs) = ^^ model_main) |> print_endline with - Type_error (l, err) -> c_error ("Unexpected type error when compiling to C:\n" ^ Type_error.string_of_type_error err) + Type_error (_, l, err) -> c_error ("Unexpected type error when compiling to C:\n" ^ Type_error.string_of_type_error err) diff --git a/src/constant_fold.ml b/src/constant_fold.ml index 9e474912..7321a801 100644 --- a/src/constant_fold.ml +++ b/src/constant_fold.ml @@ -161,7 +161,7 @@ let rec rewrite_constant_function_calls' ast = let v = run (Interpreter.Step (lazy "", (lstate, gstate), initial_monad, [])) in let exp = exp_of_value v in try (ok (); Type_check.check_exp (env_of_annot annot) exp (typ_of_annot annot)) with - | Type_error (l, err) -> + | Type_error (env, l, err) -> (* A type error here would be unexpected, so don't ignore it! *) Util.warn ("Type error when folding constants in " ^ string_of_exp (E_aux (e_aux, annot)) diff --git a/src/error_format.ml b/src/error_format.ml new file mode 100644 index 00000000..3e91f065 --- /dev/null +++ b/src/error_format.ml @@ -0,0 +1,95 @@ + +let rec skip_lines in_chan = function + | n when n <= 0 -> () + | n -> ignore (input_line in_chan); skip_lines in_chan (n - 1) + +let rec read_lines in_chan = function + | n when n <= 0 -> [] + | n -> + let l = input_line in_chan in + let ls = read_lines in_chan (n - 1) in + l :: ls + +type formatter = { + indent : string; + endline : string -> unit; + loc_color : string -> string + } + +let err_formatter = { + indent = ""; + endline = prerr_endline; + loc_color = Util.red + } + +let buffer_formatter b = { + indent = ""; + endline = (fun str -> Buffer.add_string b (str ^ "\n")); + loc_color = Util.red + } + +let format_endline str ppf = ppf.endline (ppf.indent ^ (Str.global_replace (Str.regexp_string "\n") ("\n" ^ ppf.indent) str)) + +let underline_single color cnum_from cnum_to = + if (cnum_from + 1) >= cnum_to then + Util.(String.make cnum_from ' ' ^ clear (color "^")) + else + Util.(String.make cnum_from ' ' ^ clear (color ("^" ^ String.make (cnum_to - cnum_from - 2) '-' ^ "^"))) + +let format_code_single' fname in_chan lnum cnum_from cnum_to contents ppf = + skip_lines in_chan (lnum - 1); + let line = input_line in_chan in + let line_prefix = string_of_int lnum ^ Util.(clear (cyan " |")) in + let blank_prefix = String.make (String.length (string_of_int lnum)) ' ' ^ Util.(clear (ppf.loc_color " |")) in + format_endline (Printf.sprintf "[%s]:%d:%d-%d" Util.(fname |> cyan |> clear) lnum cnum_from cnum_to) ppf; + format_endline (line_prefix ^ line) ppf; + format_endline (blank_prefix ^ underline_single ppf.loc_color cnum_from cnum_to) ppf; + contents { ppf with indent = blank_prefix ^ " " } + +let format_code_single fname lnum cnum_from cnum_to contents ppf = + try + let in_chan = open_in fname in + begin + try format_code_single' fname in_chan lnum cnum_from cnum_to contents ppf + with + | _ -> close_in_noerr in_chan; () + end + with + | _ -> () + +let format_pos p1 p2 contents ppf = + let open Lexing in + if p1.pos_lnum == p2.pos_lnum + then format_code_single p1.pos_fname p1.pos_lnum (p1.pos_cnum - p1.pos_bol) (p2.pos_cnum - p2.pos_bol) contents ppf + else failwith "Range" + +let format_loc l contents = + match l with + | Parse_ast.Unknown -> failwith "No location" + | Parse_ast.Range (p1, p2) -> format_pos p1 p2 contents + | _ -> failwith "not range" + +type message = + | Location of Parse_ast.l * message + | Line of string + | List of (string * message) list + | Seq of message list + | With of (formatter -> formatter) * message + +let bullet = Util.(clear (blue "*")) + +let rec format_message msg = + match msg with + | Location (l, msg) -> + format_loc l (format_message msg) + | Line str -> + format_endline str + | Seq messages -> + fun ppf -> List.iter (fun msg -> format_message msg ppf) messages + | List list -> + let format_list_item ppf (header, msg) = + format_endline (Util.(clear (blue "*")) ^ " " ^ header) ppf; + format_message msg { ppf with indent = ppf.indent ^ " " } + in + fun ppf -> List.iter (format_list_item ppf) list + | With (f, msg) -> fun ppf -> format_message msg (f ppf) diff --git a/src/interactive.ml b/src/interactive.ml new file mode 100644 index 00000000..3c4619a0 --- /dev/null +++ b/src/interactive.ml @@ -0,0 +1,7 @@ + +let opt_interactive = ref false +let opt_suppress_banner = ref false + +let env = ref Type_check.initial_env + +let ast = ref (Ast.Defs []) diff --git a/src/interactive.mli b/src/interactive.mli new file mode 100644 index 00000000..7782f646 --- /dev/null +++ b/src/interactive.mli @@ -0,0 +1,9 @@ +open Ast +open Type_check + +val opt_interactive : bool ref +val opt_suppress_banner : bool ref + +val ast : tannot defs ref + +val env : Env.t ref diff --git a/src/interpreter.ml b/src/interpreter.ml index 194812ca..40ee251d 100644 --- a/src/interpreter.ml +++ b/src/interpreter.ml @@ -673,7 +673,7 @@ let rec eval_frame' = function let eval_frame frame = try eval_frame' frame with - | Type_check.Type_error (l, err) -> + | Type_check.Type_error (env, l, err) -> raise (Reporting.err_typ l (Type_error.string_of_type_error err)) let rec run_frame frame = diff --git a/src/isail.ml b/src/isail.ml index d8876cf0..a3dfe680 100644 --- a/src/isail.ml +++ b/src/isail.ml @@ -90,13 +90,15 @@ let rec user_input callback = let sail_logo = let banner str = str |> Util.bold |> Util.red |> Util.clear in let logo = - [ {| ___ ___ ___ ___ |}; - {| /\ \ /\ \ /\ \ /\__\|}; - {| /::\ \ /::\ \ _\:\ \ /:/ /|}; - {| /\:\:\__\ /::\:\__\ /\/::\__\ /:/__/ |}; - {| \:\:\/__/ \/\::/ / \::/\/__/ \:\ \ |}; - {| \::/ / /:/ / \:\__\ \:\__\|}; - {| \/__/ \/__/ \/__/ \/__/|} ] + if !Interactive.opt_suppress_banner then [] + else + [ {| ___ ___ ___ ___ |}; + {| /\ \ /\ \ /\ \ /\__\|}; + {| /::\ \ /::\ \ _\:\ \ /:/ /|}; + {| /\:\:\__\ /::\:\__\ /\/::\__\ /:/__/ |}; + {| \:\:\/__/ \/\::/ / \::/\/__/ \:\ \ |}; + {| \::/ / /:/ / \:\__\ \:\__\|}; + {| \/__/ \/__/ \/__/ \/__/|} ] in let help = [ "Type :commands for a list of commands, and :help <command> for help."; @@ -104,9 +106,9 @@ let sail_logo = in List.map banner logo @ [""] @ help @ [""] -let vs_ids = ref (Initial_check.val_spec_ids !interactive_ast) +let vs_ids = ref (Initial_check.val_spec_ids !Interactive.ast) -let interactive_state = ref (initial_state !interactive_ast Value.primops) +let interactive_state = ref (initial_state !Interactive.ast Value.primops) let interactive_bytecode = ref [] @@ -259,7 +261,7 @@ let handle_input' input = | ":n" | ":normal" -> current_mode := Normal | ":t" | ":type" -> - let typq, typ = Type_check.Env.get_val_spec (mk_id arg) !interactive_env in + let typq, typ = Type_check.Env.get_val_spec (mk_id arg) !Interactive.env in pretty_sail stdout (doc_binding (typq, typ)); print_newline (); | ":q" | ":quit" -> @@ -267,15 +269,15 @@ let handle_input' input = exit 0 | ":i" | ":infer" -> let exp = Initial_check.exp_of_string arg in - let exp = Type_check.infer_exp !interactive_env exp in + let exp = Type_check.infer_exp !Interactive.env exp in pretty_sail stdout (doc_typ (Type_check.typ_of exp)); print_newline () | ":canon" -> let typ = Initial_check.typ_of_string arg in - print_endline (string_of_typ (Type_check.canonicalize !interactive_env typ)) + print_endline (string_of_typ (Type_check.canonicalize !Interactive.env typ)) | ":prove" -> let nc = Initial_check.constraint_of_string arg in - print_endline (string_of_bool (Type_check.prove __POS__ !interactive_env nc)) + print_endline (string_of_bool (Type_check.prove __POS__ !Interactive.env nc)) | ":v" | ":verbose" -> Type_check.opt_tc_debug := (!Type_check.opt_tc_debug + 1) mod 3; print_endline ("Verbosity: " ^ string_of_int !Type_check.opt_tc_debug) @@ -301,7 +303,7 @@ let handle_input' input = | "Order" -> is_order_kopt | _ -> failwith "Invalid kind" in - let ids = Specialize.polymorphic_functions is_kopt !interactive_ast in + let ids = Specialize.polymorphic_functions is_kopt !Interactive.ast in List.iter (fun id -> print_endline (string_of_id id)) (IdSet.elements ids) | ":option" -> begin @@ -312,17 +314,17 @@ let handle_input' input = | Arg.Bad message | Arg.Help message -> print_endline message end; | ":spec" -> - let ast, env = Specialize.specialize !interactive_ast !interactive_env in - interactive_ast := ast; - interactive_env := env; - interactive_state := initial_state !interactive_ast Value.primops + let ast, env = Specialize.specialize !Interactive.ast !Interactive.env in + Interactive.ast := ast; + Interactive.env := env; + interactive_state := initial_state !Interactive.ast Value.primops | ":pretty" -> - print_endline (Pretty_print_sail.to_string (Latex.defs !interactive_ast)) + print_endline (Pretty_print_sail.to_string (Latex.defs !Interactive.ast)) | ":compile" -> let open PPrint in let open C_backend in - let ast = Process_file.rewrite_ast_c !interactive_ast in - let ast, env = Specialize.specialize ast !interactive_env in + let ast = Process_file.rewrite_ast_c !Interactive.ast in + let ast, env = Specialize.specialize ast !Interactive.env in let ctx = initial_ctx env in interactive_bytecode := bytecode_ast ctx (List.map flatten_cdef) ast | ":ir" -> @@ -339,7 +341,7 @@ let handle_input' input = print_endline (Pretty_print_sail.to_string (separate_map hardline pp_cdef cdefs)) | ":ast" -> let chan = open_out arg in - Pretty_print_sail.pp_defs chan !interactive_ast; + Pretty_print_sail.pp_defs chan !Interactive.ast; close_out chan | ":output" -> let chan = open_out arg in @@ -361,24 +363,24 @@ let handle_input' input = | ":elf" -> Elf_loader.load_elf arg | ":l" | ":load" -> let files = Util.split_on_char ' ' arg in - let (_, ast, env) = load_files !interactive_env files in + let (_, ast, env) = load_files !Interactive.env files in let ast = Process_file.rewrite_ast_interpreter ast in - interactive_ast := append_ast !interactive_ast ast; - interactive_state := initial_state !interactive_ast Value.primops; - interactive_env := env; - vs_ids := Initial_check.val_spec_ids !interactive_ast + Interactive.ast := append_ast !Interactive.ast ast; + interactive_state := initial_state !Interactive.ast Value.primops; + Interactive.env := env; + vs_ids := Initial_check.val_spec_ids !Interactive.ast | ":u" | ":unload" -> - interactive_ast := Ast.Defs []; - interactive_env := Type_check.initial_env; - interactive_state := initial_state !interactive_ast Value.primops; - vs_ids := Initial_check.val_spec_ids !interactive_ast; + Interactive.ast := Ast.Defs []; + Interactive.env := Type_check.initial_env; + interactive_state := initial_state !Interactive.ast Value.primops; + vs_ids := Initial_check.val_spec_ids !Interactive.ast; (* See initial_check.mli for an explanation of why we need this. *) Initial_check.have_undefined_builtins := false | ":exec" -> let open Bytecode_interpreter in - let exp = Type_check.infer_exp !interactive_env (Initial_check.exp_of_string arg) in + let exp = Type_check.infer_exp !Interactive.env (Initial_check.exp_of_string arg) in let anf = Anf.anf exp in - let ctx = C_backend.initial_ctx !interactive_env in + let ctx = C_backend.initial_ctx !Interactive.env in let ctyp = C_backend.ctyp_of_typ ctx (Type_check.typ_of exp) in let setup, call, cleanup = C_backend.compile_aexp ctx anf in let instrs = C_backend.flatten_instrs (setup @ [call (CL_id (mk_id "interactive#", ctyp))] @ cleanup) in @@ -389,7 +391,7 @@ let handle_input' input = | Expression str -> (* An expression in normal mode is type checked, then puts us in evaluation mode. *) - let exp = Type_check.infer_exp !interactive_env (Initial_check.exp_of_string str) in + let exp = Type_check.infer_exp !Interactive.env (Initial_check.exp_of_string str) in current_mode := Evaluation (eval_frame (Step (lazy "", !interactive_state, return exp, []))); print_program () | Empty -> () @@ -444,7 +446,7 @@ let handle_input' input = let handle_input input = try handle_input' input with - | Type_check.Type_error (l, err) -> + | Type_check.Type_error (env, l, err) -> print_endline (Type_error.string_of_type_error err) | Reporting.Fatal_error err -> Reporting.print_error err @@ -491,7 +493,7 @@ let () = LNoise.history_load ~filename:"sail_history" |> ignore; LNoise.history_set ~max_length:100 |> ignore; - if !opt_interactive then + if !Interactive.opt_interactive then begin List.iter print_endline sail_logo; user_input handle_input diff --git a/src/pretty_print_coq.ml b/src/pretty_print_coq.ml index b408c6eb..a5478c31 100644 --- a/src/pretty_print_coq.ml +++ b/src/pretty_print_coq.ml @@ -2457,7 +2457,7 @@ try hardline; string "End Content."; hardline]) -with Type_check.Type_error (l,err) -> +with Type_check.Type_error (env,l,err) -> let extra = "\nError during Coq printing\n" ^ if Printexc.backtrace_status () diff --git a/src/process_file.ml b/src/process_file.ml index 0194baa8..03fc36a2 100644 --- a/src/process_file.ml +++ b/src/process_file.ml @@ -384,7 +384,7 @@ let rewrite_step defs (name, rewriter) = let rewrite rewriters defs = try List.fold_left rewrite_step defs rewriters with - | Type_check.Type_error (l, err) -> + | Type_check.Type_error (_, l, err) -> raise (Reporting.err_typ l (Type_error.string_of_type_error err)) let rewrite_ast = rewrite [("initial", Rewriter.rewrite_defs)] diff --git a/src/reporting.ml b/src/reporting.ml index 858e5c41..f27e4c03 100644 --- a/src/reporting.ml +++ b/src/reporting.ml @@ -238,20 +238,15 @@ let loc_to_string ?code:(code=true) l = let s = Format.flush_str_formatter () in s -type pos_or_loc = Loc of Parse_ast.l | LocD of Parse_ast.l * Parse_ast.l | Pos of Lexing.position +type pos_or_loc = Loc of Parse_ast.l | Pos of Lexing.position let print_err_internal fatal verb_loc p_l m1 m2 = - Format.eprintf "%s at " m1; - let _ = (match p_l with Pos p -> print_err_pos p - | Loc l -> print_err_loc l - | LocD (l1,l2) -> - print_err_loc l1; Format.fprintf Format.err_formatter " and "; print_err_loc l2) in - Format.eprintf "%s\n" m2; - if verb_loc then (match p_l with Loc l -> - format_loc_source Format.err_formatter l; - Format.pp_print_newline Format.err_formatter (); | _ -> ()); - Format.pp_print_flush Format.err_formatter (); - if fatal then (exit 1) else () + let open Error_format in + begin match p_l with + | Loc l -> format_message (Location (l, Line m2)) err_formatter + | _ -> failwith "Pos" + end; + if fatal then exit 1 else () let print_err fatal verb_loc l m1 m2 = print_err_internal fatal verb_loc (Loc l) m1 m2 @@ -264,7 +259,6 @@ type error = | Err_syntax_locn of Parse_ast.l * string | Err_lex of Lexing.position * string | Err_type of Parse_ast.l * string - | Err_type_dual of Parse_ast.l * Parse_ast.l * string let issues = "\n\nPlease report this as an issue on GitHub at https://github.com/rems-project/sail/issues" @@ -277,7 +271,6 @@ let dest_err = function | Err_syntax_locn (l, m) -> ("Syntax error", false, Loc l, m) | Err_lex (p, s) -> ("Lexical error", false, Pos p, s) | Err_type (l, m) -> ("Type error", false, Loc l, m) - | Err_type_dual(l1,l2,m) -> ("Type error", false, LocD (l1,l2), m) exception Fatal_error of error @@ -286,11 +279,10 @@ let err_todo l m = Fatal_error (Err_todo (l, m)) let err_unreachable l ocaml_pos m = Fatal_error (Err_unreachable (l, ocaml_pos, m)) let err_general l m = Fatal_error (Err_general (l, m)) let err_typ l m = Fatal_error (Err_type (l,m)) -let err_typ_dual l1 l2 m = Fatal_error (Err_type_dual (l1,l2,m)) let report_error e = let (m1, verb_pos, pos_l, m2) = dest_err e in - (print_err_internal verb_pos false pos_l m1 m2; exit 1) + print_err_internal verb_pos false pos_l m1 m2 let print_error e = let (m1, verb_pos, pos_l, m2) = dest_err e in diff --git a/src/reporting.mli b/src/reporting.mli index 63ed3eee..4ce0ced8 100644 --- a/src/reporting.mli +++ b/src/reporting.mli @@ -90,8 +90,7 @@ type error = | Err_syntax_locn of Parse_ast.l * string | Err_lex of Lexing.position * string | Err_type of Parse_ast.l * string - | Err_type_dual of Parse_ast.l * Parse_ast.l * string - + exception Fatal_error of error (** [err_todo l m] is an abreviatiation for [Fatal_error (Err_todo (l, m))] *) @@ -106,11 +105,8 @@ val err_unreachable : Parse_ast.l -> (string * int * int * int) -> string -> exn (** [err_typ l m] is an abreviatiation for [Fatal_error (Err_type (l, m))] *) val err_typ : Parse_ast.l -> string -> exn -(** [err_typ_dual l1 l2 m] is an abreviatiation for [Fatal_error (Err_type_dual (l1, l2, m))] *) -val err_typ_dual : Parse_ast.l -> Parse_ast.l -> string -> exn - (** Report error should only be used by main to print the error in the end. Everywhere else, raising a [Fatal_error] exception is recommended. *) -val report_error : error -> 'a +val report_error : error -> unit val print_error : error -> unit diff --git a/src/rewrites.ml b/src/rewrites.ml index 8df5ce02..1e3d319a 100644 --- a/src/rewrites.ml +++ b/src/rewrites.ml @@ -462,7 +462,7 @@ let rewrite_sizeof (Defs defs) = for the given parameters in the original environment *) let inst = try instantiation_of orig_exp with - | Type_error (l, err) -> + | Type_error (_, l, err) -> raise (Reporting.err_typ l (Type_error.string_of_type_error err)) in (* Rewrite the inst using orig_kid so that each type variable has it's original name rather than a mangled typechecker name *) @@ -475,7 +475,7 @@ let rewrite_sizeof (Defs defs) = | Some (A_aux (A_nexp nexp, _)) -> let sizeof = E_aux (E_sizeof nexp, (l, mk_tannot env (atom_typ nexp) no_effect)) in (try rewrite_trivial_sizeof_exp sizeof with - | Type_error (l, err) -> + | Type_error (_, l, err) -> raise (Reporting.err_typ l (Type_error.string_of_type_error err))) (* If the type variable is Not_found then it was probably introduced by a P_var pattern, so it likely exists as @@ -2474,7 +2474,7 @@ let rewrite_vector_concat_assignments defs = mk_exp (E_assign (lexp, tup)))) in begin try check_exp env e_aux unit_typ with - | Type_error (l, err) -> + | Type_error (_, l, err) -> raise (Reporting.err_typ l (Type_error.string_of_type_error err)) end else E_aux (e_aux, annot) @@ -2503,7 +2503,7 @@ let rewrite_tuple_assignments defs = let let_exp = mk_exp (E_let (letbind, block)) in begin try check_exp env let_exp unit_typ with - | Type_error (l, err) -> + | Type_error (_, l, err) -> raise (Reporting.err_typ l (Type_error.string_of_type_error err)) end | _ -> E_aux (e_aux, annot) @@ -3126,7 +3126,7 @@ let construct_toplevel_string_append_func env f_id pat = let mapping_inner_typ = match Env.get_val_spec (mk_id mapping_prefix_func) env with | (_, Typ_aux (Typ_fn (_, Typ_aux (Typ_app (_, [A_aux (A_typ typ, _)]), _), _), _)) -> typ - | _ -> typ_error Parse_ast.Unknown "mapping prefix func without correct function type?" + | _ -> raise (Reporting.err_unreachable Parse_ast.Unknown __POS__ "mapping prefix func without correct function type?") in let s_id = fresh_stringappend_id () in @@ -3302,7 +3302,7 @@ let rec rewrite_defs_pat_string_append = let mapping_inner_typ = match Env.get_val_spec (mk_id mapping_prefix_func) env with | (_, Typ_aux (Typ_fn (_, Typ_aux (Typ_app (_, [A_aux (A_typ typ, _)]), _), _), _)) -> typ - | _ -> typ_error Parse_ast.Unknown "mapping prefix func without correct function type?" + | _ -> typ_error env Parse_ast.Unknown "mapping prefix func without correct function type?" in let s_id = fresh_stringappend_id () in @@ -4304,12 +4304,12 @@ let rewrite_defs_realise_mappings (Defs defs) = (* We need to make sure we get the environment for the last mapping clause *) let env = match List.rev mapcls with | MCL_aux (_, mapcl_annot) :: _ -> env_of_annot mapcl_annot - | _ -> Type_check.typ_error l "mapping with no clauses?" + | _ -> raise (Reporting.err_unreachable l __POS__ "mapping with no clauses?") in let (typq, bidir_typ) = Env.get_val_spec id env in let (typ1, typ2, l) = match bidir_typ with | Typ_aux (Typ_bidir (typ1, typ2), l) -> typ1, typ2, l - | _ -> Type_check.typ_error l "non-bidir type of mapping?" + | _ -> raise (Reporting.err_unreachable l __POS__ "non-bidir type of mapping?") in let forwards_typ = Typ_aux (Typ_fn ([typ1], typ2, no_effect), l) in let forwards_matches_typ = Typ_aux (Typ_fn ([typ1], bool_typ, no_effect), l) in @@ -5144,7 +5144,7 @@ let rewrite_check_annot = else ()); exp with - Type_error (l, err) -> raise (Reporting.err_typ l (Type_error.string_of_type_error err)) + Type_error (_, l, err) -> raise (Reporting.err_typ l (Type_error.string_of_type_error err)) in let check_pat pat = prerr_endline ("CHECKING PAT: " ^ string_of_pat pat ^ " : " ^ string_of_typ (typ_of_pat pat)); diff --git a/src/sail.ml b/src/sail.ml index 247cae25..2777b7a5 100644 --- a/src/sail.ml +++ b/src/sail.ml @@ -54,7 +54,6 @@ module Big_int = Nat_big_num let lib = ref ([] : string list) let opt_file_out : string option ref = ref None -let opt_interactive = ref false let opt_interactive_script : string option ref = ref None let opt_print_version = ref false let opt_print_initial_env = ref false @@ -79,10 +78,10 @@ let options = Arg.align ([ Arg.String (fun f -> opt_file_out := Some f), "<prefix> select output filename prefix"); ( "-i", - Arg.Tuple [Arg.Set opt_interactive; Arg.Set Initial_check.opt_undefined_gen], + Arg.Tuple [Arg.Set Interactive.opt_interactive; Arg.Set Initial_check.opt_undefined_gen], " start interactive interpreter"); ( "-is", - Arg.Tuple [Arg.Set opt_interactive; Arg.Set Initial_check.opt_undefined_gen; + Arg.Tuple [Arg.Set Interactive.opt_interactive; Arg.Set Initial_check.opt_undefined_gen; Arg.String (fun s -> opt_interactive_script := Some s)], "<filename> start interactive interpreter and execute commands in script"); ( "-iout", @@ -273,8 +272,6 @@ let _ = opt_file_arguments := (!opt_file_arguments) @ [s]) usage_msg -let interactive_ast = ref (Ast.Defs []) -let interactive_env = ref Type_check.initial_env let load_files type_envs files = if !opt_memo_z3 then Constraint.load_digests () else (); @@ -349,9 +346,9 @@ let main() = (*let _ = Printf.eprintf "Type checked, next to pretty print" in*) begin - (if !(opt_interactive) + (if !(Interactive.opt_interactive) then - (interactive_ast := Process_file.rewrite_ast_interpreter ast; interactive_env := type_envs) + (Interactive.ast := Process_file.rewrite_ast_interpreter ast; Interactive.env := type_envs) else ()); (if !(opt_sanity) then @@ -414,7 +411,10 @@ let main() = let _ = try begin - try ignore(main ()) - with Failure(s) -> raise (Reporting.err_general Parse_ast.Unknown ("Failure "^s)) + try ignore (main ()) + with Failure s -> raise (Reporting.err_general Parse_ast.Unknown ("Failure " ^ s)) end - with Reporting.Fatal_error e -> Reporting.report_error e + with Reporting.Fatal_error e -> + Reporting.report_error e; + Interactive.opt_suppress_banner := true; + if !Interactive.opt_interactive then () else exit 1 diff --git a/src/type_check.ml b/src/type_check.ml index 1dfc5957..b362e813 100644 --- a/src/type_check.ml +++ b/src/type_check.ml @@ -96,13 +96,42 @@ type type_error = | Err_subtype of typ * typ * n_constraint list * Ast.l KBindings.t | Err_no_num_ident of id | Err_other of string - | Err_because of type_error * type_error + | Err_because of type_error * Parse_ast.l * type_error + +type env = + { top_val_specs : (typquant * typ) Bindings.t; + defined_val_specs : IdSet.t; + locals : (mut * typ) Bindings.t; + union_ids : (typquant * typ) Bindings.t; + registers : (effect * effect * typ) Bindings.t; + variants : (typquant * type_union list) Bindings.t; + mappings : (typquant * typ * typ) Bindings.t; + typ_vars : (Ast.l * kind_aux) KBindings.t; + shadow_vars : int KBindings.t; + typ_synonyms : (env -> typ_arg list -> typ_arg) Bindings.t; + num_defs : nexp Bindings.t; + overloads : (id list) Bindings.t; + flow : (typ -> typ) Bindings.t; + enums : IdSet.t Bindings.t; + records : (typquant * (typ * id) list) Bindings.t; + accessors : (typquant * typ) Bindings.t; + externs : (string -> string option) Bindings.t; + casts : id list; + allow_casts : bool; + allow_bindings : bool; + constraints : n_constraint list; + default_order : order option; + ret_typ : typ option; + poly_undefineds : bool; + prove : env -> n_constraint -> bool; + allow_unknowns : bool; + } -exception Type_error of l * type_error;; +exception Type_error of env * l * type_error;; -let typ_error l m = raise (Type_error (l, Err_other m)) +let typ_error env l m = raise (Type_error (env, l, Err_other m)) -let typ_raise l err = raise (Type_error (l, err)) +let typ_raise env l err = raise (Type_error (env, l, err)) let deinfix = function | Id_aux (Id v, l) -> Id_aux (DeIid v, l) @@ -225,7 +254,7 @@ let rec name_pat (P_aux (aux, _)) = | P_id id | P_as (_, id) -> Some ("_" ^ string_of_id id) | P_typ (_, pat) | P_var (pat, _) -> name_pat pat | _ -> None - + let ex_counter = ref 0 let fresh_existential k = @@ -299,7 +328,7 @@ let adding = Util.("Adding " |> darkgray |> clear) (**************************************************************************) module Env : sig - type t + type t = env val add_val_spec : id -> typquant * typ -> t -> t val update_val_spec : id -> typquant * typ -> t -> t val define_val_spec : id -> t -> t @@ -389,34 +418,7 @@ module Env : sig val builtin_typs : typquant Bindings.t end = struct - type t = - { top_val_specs : (typquant * typ) Bindings.t; - defined_val_specs : IdSet.t; - locals : (mut * typ) Bindings.t; - union_ids : (typquant * typ) Bindings.t; - registers : (effect * effect * typ) Bindings.t; - variants : (typquant * type_union list) Bindings.t; - mappings : (typquant * typ * typ) Bindings.t; - typ_vars : (Ast.l * kind_aux) KBindings.t; - shadow_vars : int KBindings.t; - typ_synonyms : (t -> typ_arg list -> typ_arg) Bindings.t; - num_defs : nexp Bindings.t; - overloads : (id list) Bindings.t; - flow : (typ -> typ) Bindings.t; - enums : IdSet.t Bindings.t; - records : (typquant * (typ * id) list) Bindings.t; - accessors : (typquant * typ) Bindings.t; - externs : (string -> string option) Bindings.t; - casts : id list; - allow_casts : bool; - allow_bindings : bool; - constraints : n_constraint list; - default_order : order option; - ret_typ : typ option; - poly_undefineds : bool; - prove : t -> n_constraint -> bool; - allow_unknowns : bool; - } + type t = env let empty = { top_val_specs = Bindings.empty; @@ -454,11 +456,11 @@ end = struct let get_typ_var kid env = try snd (KBindings.find kid env.typ_vars) with - | Not_found -> typ_error (kid_loc kid) ("No type variable " ^ string_of_kid kid) + | Not_found -> typ_error env (kid_loc kid) ("No type variable " ^ string_of_kid kid) let get_typ_var_loc kid env = try fst (KBindings.find kid env.typ_vars) with - | Not_found -> typ_error (kid_loc kid) ("No type variable " ^ string_of_kid kid) + | Not_found -> typ_error env (kid_loc kid) ("No type variable " ^ string_of_kid kid) let get_typ_vars env = KBindings.map snd env.typ_vars let get_typ_var_locs env = KBindings.map fst env.typ_vars @@ -519,9 +521,9 @@ end = struct else if Bindings.mem id env.enums then mk_typquant [] else if Bindings.mem id env.typ_synonyms then - typ_error (id_loc id) ("Cannot infer kind of type synonym " ^ string_of_id id) + typ_error env (id_loc id) ("Cannot infer kind of type synonym " ^ string_of_id id) else - typ_error (id_loc id) ("Cannot infer kind of " ^ string_of_id id) + typ_error env (id_loc id) ("Cannot infer kind of " ^ string_of_id id) let check_args_typquant id env args typq = let kopts, ncs = quant_split typq in @@ -536,13 +538,13 @@ end = struct | kopt :: kopts, A_aux (A_bool arg, _) :: args when is_bool_kopt kopt -> subst_args kopts args | [], [] -> ncs - | _, A_aux (_, l) :: _ -> typ_error l ("Error when processing type quantifer arguments " ^ string_of_typquant typq) - | _, _ -> typ_error Parse_ast.Unknown ("Error when processing type quantifer arguments " ^ string_of_typquant typq) + | _, A_aux (_, l) :: _ -> typ_error env l ("Error when processing type quantifer arguments " ^ string_of_typquant typq) + | _, _ -> typ_error env Parse_ast.Unknown ("Error when processing type quantifer arguments " ^ string_of_typquant typq) in let ncs = subst_args kopts args in if List.for_all (env.prove env) ncs then () - else typ_error (id_loc id) ("Could not prove " ^ string_of_list ", " string_of_n_constraint ncs ^ " for type constructor " ^ string_of_id id) + else typ_error env (id_loc id) ("Could not prove " ^ string_of_list ", " string_of_n_constraint ncs ^ " for type constructor " ^ string_of_id id) let rec expand_constraint_synonyms env (NC_aux (aux, l) as nc) = typ_debug ~level:2 (lazy ("Expanding " ^ string_of_n_constraint nc)); @@ -553,7 +555,7 @@ end = struct (try begin match Bindings.find id env.typ_synonyms env args with | A_aux (A_bool nc, _) -> expand_constraint_synonyms env nc - | arg -> typ_error l ("Expected Bool when expanding synonym " ^ string_of_id id ^ " got " ^ string_of_typ_arg arg) + | arg -> typ_error env l ("Expected Bool when expanding synonym " ^ string_of_id id ^ " got " ^ string_of_typ_arg arg) end with Not_found -> NC_aux (NC_app (id, List.map (expand_synonyms_arg env) args), l)) | NC_true | NC_false | NC_equal _ | NC_not_equal _ | NC_bounded_le _ | NC_bounded_ge _ | NC_var _ | NC_set _ -> nc @@ -568,7 +570,7 @@ end = struct (try begin match Bindings.find id env.typ_synonyms env args with | A_aux (A_typ typ, _) -> expand_synonyms env typ - | _ -> typ_error l ("Expected Type when expanding synonym " ^ string_of_id id) + | _ -> typ_error env l ("Expected Type when expanding synonym " ^ string_of_id id) end with | Not_found -> Typ_aux (Typ_app (id, List.map (expand_synonyms_arg env) args), l)) @@ -576,7 +578,7 @@ end = struct (try begin match Bindings.find id env.typ_synonyms env [] with | A_aux (A_typ typ, _) -> expand_synonyms env typ - | _ -> typ_error l ("Expected Type when expanding synonym " ^ string_of_id id) + | _ -> typ_error env l ("Expected Type when expanding synonym " ^ string_of_id id) end with | Not_found -> Typ_aux (Typ_id id, l)) @@ -644,31 +646,31 @@ end = struct | Typ_id id when bound_typ_id env id -> let typq = infer_kind env id in if quant_kopts typq != [] - then typ_error l ("Type constructor " ^ string_of_id id ^ " expected " ^ string_of_typquant typq) + then typ_error env l ("Type constructor " ^ string_of_id id ^ " expected " ^ string_of_typquant typq) else () - | Typ_id id -> typ_error l ("Undefined type " ^ string_of_id id) + | Typ_id id -> typ_error env l ("Undefined type " ^ string_of_id id) | Typ_var kid -> begin match KBindings.find kid env.typ_vars with | (_, K_type) -> () - | (_, k) -> typ_error l ("Kind identifier " ^ string_of_kid kid ^ " in type " ^ string_of_typ typ + | (_, k) -> typ_error env l ("Kind identifier " ^ string_of_kid kid ^ " in type " ^ string_of_typ typ ^ " is " ^ string_of_kind_aux k ^ " rather than Type") | exception Not_found -> - typ_error l ("Unbound kind identifier " ^ string_of_kid kid ^ " in type " ^ string_of_typ typ) + typ_error env l ("Unbound kind identifier " ^ string_of_kid kid ^ " in type " ^ string_of_typ typ) end | Typ_fn (arg_typs, ret_typ, effs) -> List.iter (wf_typ ~exs:exs env) arg_typs; wf_typ ~exs:exs env ret_typ | Typ_bidir (typ1, typ2) when strip_typ typ1 = strip_typ typ2 -> - typ_error l "Bidirectional types cannot be the same on both sides" + typ_error env l "Bidirectional types cannot be the same on both sides" | Typ_bidir (typ1, typ2) -> wf_typ ~exs:exs env typ1; wf_typ ~exs:exs env typ2 | Typ_tup typs -> List.iter (wf_typ ~exs:exs env) typs | Typ_app (id, args) when bound_typ_id env id -> List.iter (wf_typ_arg ~exs:exs env) args; check_args_typquant id env args (infer_kind env id) - | Typ_app (id, _) -> typ_error l ("Undefined type " ^ string_of_id id) - | Typ_exist ([], _, _) -> typ_error l ("Existential must have some type variables") + | Typ_app (id, _) -> typ_error env l ("Undefined type " ^ string_of_id id) + | Typ_exist ([], _, _) -> typ_error env l ("Existential must have some type variables") | Typ_exist (kopts, nc, typ) when KidSet.is_empty exs -> wf_constraint ~exs:(KidSet.of_list (List.map kopt_kid kopts)) env nc; wf_typ ~exs:(KidSet.of_list (List.map kopt_kid kopts)) { env with constraints = nc :: env.constraints } typ - | Typ_exist (_, _, _) -> typ_error l ("Nested existentials are not allowed") + | Typ_exist (_, _, _) -> typ_error env l ("Nested existentials are not allowed") | Typ_internal_unknown -> unreachable l __POS__ "escaped Typ_internal_unknown" and wf_typ_arg ?exs:(exs=KidSet.empty) env (A_aux (typ_arg_aux, _)) = match typ_arg_aux with @@ -684,7 +686,7 @@ end = struct | Nexp_var kid -> begin match get_typ_var kid env with | K_int -> () - | kind -> typ_error l ("Constraint is badly formed, " + | kind -> typ_error env l ("Constraint is badly formed, " ^ string_of_kid kid ^ " has kind " ^ string_of_kind_aux kind ^ " but should have kind Int") end @@ -701,7 +703,7 @@ end = struct | Ord_var kid -> begin match get_typ_var kid env with | K_order -> () - | kind -> typ_error l ("Order is badly formed, " + | kind -> typ_error env l ("Order is badly formed, " ^ string_of_kid kid ^ " has kind " ^ string_of_kind_aux kind ^ " but should have kind Order") end @@ -717,7 +719,7 @@ end = struct | NC_set (kid, _) -> begin match get_typ_var kid env with | K_int -> () - | kind -> typ_error l ("Set constraint is badly formed, " + | kind -> typ_error env l ("Set constraint is badly formed, " ^ string_of_kid kid ^ " has kind " ^ string_of_kind_aux kind ^ " but should have kind Int") end @@ -728,7 +730,7 @@ end = struct | NC_var kid -> begin match get_typ_var kid env with | K_bool -> () - | kind -> typ_error l (string_of_kid kid ^ " has kind " + | kind -> typ_error env l (string_of_kid kid ^ " has kind " ^ string_of_kind_aux kind ^ " but should have kind Bool") end | NC_true | NC_false -> () @@ -754,7 +756,7 @@ end = struct try Bindings.find id env.top_val_specs with - | Not_found -> typ_error (id_loc id) ("No val spec found for " ^ string_of_id id) + | Not_found -> typ_error env (id_loc id) ("No val spec found for " ^ string_of_id id) let get_val_spec id env = try @@ -764,7 +766,7 @@ end = struct typ_debug (lazy ("get_val_spec: freshened to " ^ string_of_bind bind')); bind' with - | Not_found -> typ_error (id_loc id) ("No val spec found for " ^ string_of_id id) + | Not_found -> typ_error env (id_loc id) ("No val spec found for " ^ string_of_id id) let add_union_id id bind env = typ_print (lazy (adding ^ "union identifier " ^ string_of_id id ^ " : " ^ string_of_bind bind)); @@ -775,7 +777,7 @@ end = struct let bind = Bindings.find id env.union_ids in List.fold_left (fun bind (kid, _) -> freshen_kid env kid bind) bind (KBindings.bindings env.typ_vars) with - | Not_found -> typ_error (id_loc id) ("No union constructor found for " ^ string_of_id id) + | Not_found -> typ_error env (id_loc id) ("No union constructor found for " ^ string_of_id id) let rec update_val_spec id (typq, typ) env = begin match expand_synonyms env typ with @@ -803,7 +805,7 @@ end = struct typ_print (lazy (adding ^ "mapping " ^ string_of_id id ^ " : " ^ string_of_bind (typq, typ))); { env with top_val_specs = Bindings.add id (typq, typ) env.top_val_specs } - | _ -> typ_error (id_loc id) "val definition must have a mapping or function type" + | _ -> typ_error env (id_loc id) "val definition must have a mapping or function type" end and add_val_spec id (bind_typq, bind_typ) env = @@ -816,7 +818,7 @@ end = struct let existing_cmp = (strip_typq existing_typq, strip_typ existing_typ) in let bind_cmp = (strip_typq bind_typq, strip_typ bind_typ) in if existing_cmp <> bind_cmp then - typ_error (id_loc id) ("Identifier " ^ string_of_id id ^ " is already bound as " ^ string_of_bind (existing_typq, existing_typ) ^ ", cannot rebind as " ^ string_of_bind (bind_typq, bind_typ)) + typ_error env (id_loc id) ("Identifier " ^ string_of_id id ^ " is already bound as " ^ string_of_bind (existing_typq, existing_typ) ^ ", cannot rebind as " ^ string_of_bind (bind_typq, bind_typ)) else env *) @@ -850,7 +852,7 @@ end = struct let define_val_spec id env = if IdSet.mem id env.defined_val_specs - then typ_error (id_loc id) ("Function " ^ string_of_id id ^ " has already been declared") + then typ_error env (id_loc id) ("Function " ^ string_of_id id ^ " has already been declared") else { env with defined_val_specs = IdSet.add id env.defined_val_specs } let is_union_constructor id env = @@ -875,7 +877,7 @@ end = struct let add_enum id ids env = if bound_typ_id env id - then typ_error (id_loc id) ("Cannot create enum " ^ string_of_id id ^ ", type name is already bound") + then typ_error env (id_loc id) ("Cannot create enum " ^ string_of_id id ^ ", type name is already bound") else begin typ_print (lazy (adding ^ "enum " ^ string_of_id id)); @@ -885,7 +887,7 @@ end = struct let get_enum id env = try IdSet.elements (Bindings.find id env.enums) with - | Not_found -> typ_error (id_loc id) ("Enumeration " ^ string_of_id id ^ " does not exist") + | Not_found -> typ_error env (id_loc id) ("Enumeration " ^ string_of_id id ^ " does not exist") let is_record id env = Bindings.mem id env.records @@ -893,7 +895,7 @@ end = struct let add_record id typq fields env = if bound_typ_id env id - then typ_error (id_loc id) ("Cannot create record " ^ string_of_id id ^ ", type name is already bound") + then typ_error env (id_loc id) ("Cannot create record " ^ string_of_id id ^ ", type name is already bound") else begin typ_print (lazy (adding ^ "record " ^ string_of_id id)); @@ -924,14 +926,14 @@ end = struct let freshen_bind bind = List.fold_left (fun bind (kid, _) -> freshen_kid env kid bind) bind (KBindings.bindings env.typ_vars) in try freshen_bind (Bindings.find (field_name rec_id id) env.accessors) with - | Not_found -> typ_error (id_loc id) ("No accessor found for " ^ string_of_id (field_name rec_id id)) + | Not_found -> typ_error env (id_loc id) ("No accessor found for " ^ string_of_id (field_name rec_id id)) let get_accessor rec_id id env = match get_accessor_fn rec_id id env with (* All accessors should have a single argument (the record itself) *) | (typq, Typ_aux (Typ_fn ([rec_typ], field_typ, effect), _)) -> (typq, rec_typ, field_typ, effect) - | _ -> typ_error (id_loc id) ("Accessor with non-function type found for " ^ string_of_id (field_name rec_id id)) + | _ -> typ_error env (id_loc id) ("Accessor with non-function type found for " ^ string_of_id (field_name rec_id id)) let is_mutable id env = try @@ -948,10 +950,10 @@ end = struct let add_local id mtyp env = begin - if not env.allow_bindings then typ_error (id_loc id) "Bindings are not allowed in this context" else (); + if not env.allow_bindings then typ_error env (id_loc id) "Bindings are not allowed in this context" else (); wf_typ env (snd mtyp); if Bindings.mem id env.top_val_specs then - typ_error (id_loc id) ("Local variable " ^ string_of_id id ^ " is already bound as a function name") + typ_error env (id_loc id) ("Local variable " ^ string_of_id id ^ " is already bound as a function name") else (); typ_print (lazy (adding ^ "local binding " ^ string_of_id id ^ " : " ^ string_of_mtyp mtyp)); { env with locals = Bindings.add id mtyp env.locals } @@ -968,12 +970,12 @@ end = struct let add_variant_clause id tu env = match Bindings.find_opt id env.variants with | Some (typq, tus) -> { env with variants = Bindings.add id (typq, tus @ [tu]) env.variants } - | None -> typ_error (id_loc id) ("scattered union " ^ string_of_id id ^ " not found") + | None -> typ_error env (id_loc id) ("scattered union " ^ string_of_id id ^ " not found") let get_variant id env = match Bindings.find_opt id env.variants with | Some (typq, tus) -> typq, tus - | None -> typ_error (id_loc id) ("union " ^ string_of_id id ^ " not found") + | None -> typ_error env (id_loc id) ("union " ^ string_of_id id ^ " not found") let get_flow id env = try Bindings.find id env.flow with | Not_found -> fun typ -> typ @@ -991,7 +993,7 @@ end = struct let get_register id env = try Bindings.find id env.registers with - | Not_found -> typ_error (id_loc id) ("No register binding found for " ^ string_of_id id) + | Not_found -> typ_error env (id_loc id) ("No register binding found for " ^ string_of_id id) let is_extern id env backend = try not (Bindings.find id env.externs backend = None) with @@ -1005,16 +1007,16 @@ end = struct try match Bindings.find id env.externs backend with | Some ext -> ext - | None -> typ_error (id_loc id) ("No extern binding found for " ^ string_of_id id) + | None -> typ_error env (id_loc id) ("No extern binding found for " ^ string_of_id id) with - | Not_found -> typ_error (id_loc id) ("No extern binding found for " ^ string_of_id id) + | Not_found -> typ_error env (id_loc id) ("No extern binding found for " ^ string_of_id id) let get_casts env = env.casts let add_register id reff weff typ env = wf_typ env typ; if Bindings.mem id env.registers - then typ_error (id_loc id) ("Register " ^ string_of_id id ^ " is already bound") + then typ_error env (id_loc id) ("Register " ^ string_of_id id ^ " is already bound") else begin typ_print (lazy (adding ^ "register binding " ^ string_of_id id ^ " :: " ^ string_of_typ typ)); @@ -1060,7 +1062,7 @@ end = struct let add_num_def id nexp env = if Bindings.mem id env.num_defs - then typ_error (id_loc id) ("Num identifier " ^ string_of_id id ^ " is already bound") + then typ_error env (id_loc id) ("Num identifier " ^ string_of_id id ^ " is already bound") else begin typ_print (lazy (adding ^ "Num identifier " ^ string_of_id id ^ " : " ^ string_of_nexp nexp)); @@ -1069,7 +1071,7 @@ end = struct let get_num_def id env = try Bindings.find id env.num_defs with - | Not_found -> typ_raise (id_loc id) (Err_no_num_ident id) + | Not_found -> typ_raise env (id_loc id) (Err_no_num_ident id) let get_constraints env = env.constraints @@ -1099,7 +1101,7 @@ end = struct let add_typ_synonym id synonym env = if Bindings.mem id env.typ_synonyms - then typ_error (id_loc id) ("Type synonym " ^ string_of_id id ^ " already exists") + then typ_error env (id_loc id) ("Type synonym " ^ string_of_id id ^ " already exists") else begin typ_print (lazy (adding ^ "type synonym " ^ string_of_id id)); @@ -1110,13 +1112,13 @@ end = struct let get_default_order env = match env.default_order with - | None -> typ_error Parse_ast.Unknown ("No default order has been set") + | None -> typ_error env Parse_ast.Unknown ("No default order has been set") | Some ord -> ord let set_default_order o env = match env.default_order with | None -> { env with default_order = Some (Ord_aux (o, Parse_ast.Unknown)) } - | Some _ -> typ_error Parse_ast.Unknown ("Cannot change default order once already set") + | Some _ -> typ_error env Parse_ast.Unknown ("Cannot change default order once already set") let set_default_order_inc = set_default_order Ord_inc let set_default_order_dec = set_default_order Ord_dec @@ -1192,7 +1194,7 @@ let bind_numeric l typ env = match destruct_numeric (Env.expand_synonyms env typ) with | Some (kids, nc, nexp) -> nexp, add_existential l (List.map (mk_kopt K_int) kids) nc env - | None -> typ_error l ("Expected " ^ string_of_typ typ ^ " to be numeric") + | None -> typ_error env l ("Expected " ^ string_of_typ typ ^ " to be numeric") (** Pull an (potentially)-existentially qualified type into the global typing environment **) @@ -1597,7 +1599,7 @@ let unify l env goals typ1 typ2 = ^ " for " ^ Util.string_of_list ", " string_of_kid (KidSet.elements goals))); let typ1, typ2 = Env.expand_synonyms env typ1, Env.expand_synonyms env typ2 in if not (KidSet.is_empty (KidSet.inter goals (tyvars_of_typ typ2))) then - typ_error l ("Occurs check failed: " ^ string_of_typ typ2 ^ " contains " + typ_error env l ("Occurs check failed: " ^ string_of_typ typ2 ^ " contains " ^ Util.string_of_list ", " string_of_kid (KidSet.elements goals)) else unify_typ l env goals typ1 typ2 @@ -1675,7 +1677,7 @@ let rec kid_order kind_map (Typ_aux (aux, l) as typ) = List.fold_left (fun (ord, kids) typ -> let (ord', kids) = kid_order kids typ in (ord @ ord', kids)) ([], kind_map) typs | Typ_app (_, args) -> List.fold_left (fun (ord, kids) arg -> let (ord', kids) = kid_order_arg kids arg in (ord @ ord', kids)) ([], kind_map) args - | Typ_fn _ | Typ_bidir _ | Typ_exist _ -> typ_error l ("Existential or function type cannot appear within existential type: " ^ string_of_typ typ) + | Typ_fn _ | Typ_bidir _ | Typ_exist _ -> typ_error Env.empty l ("Existential or function type cannot appear within existential type: " ^ string_of_typ typ) | Typ_internal_unknown -> unreachable l __POS__ "escaped Typ_internal_unknown" and kid_order_arg kind_map (A_aux (aux, l) as arg) = match aux with @@ -1801,15 +1803,15 @@ let rec subtyp l env typ1 typ2 = (* Special cases for two numeric (atom) types *) | Some (kids1, nc1, nexp1), Some ([], _, nexp2) -> let env = add_existential l (List.map (mk_kopt K_int) kids1) nc1 env in - if prove __POS__ env (nc_eq nexp1 nexp2) then () else typ_raise l (Err_subtype (typ1, typ2, Env.get_constraints env, Env.get_typ_var_locs env)) + if prove __POS__ env (nc_eq nexp1 nexp2) then () else typ_raise env l (Err_subtype (typ1, typ2, Env.get_constraints env, Env.get_typ_var_locs env)) | Some (kids1, nc1, nexp1), Some (kids2, nc2, nexp2) -> let env = add_existential l (List.map (mk_kopt K_int) kids1) nc1 env in let env = add_typ_vars l (List.map (mk_kopt K_int) (KidSet.elements (KidSet.inter (nexp_frees nexp2) (KidSet.of_list kids2)))) env in let kids2 = KidSet.elements (KidSet.diff (KidSet.of_list kids2) (nexp_frees nexp2)) in - if not (kids2 = []) then typ_error l ("Universally quantified constraint generated: " ^ Util.string_of_list ", " string_of_kid kids2) else (); + if not (kids2 = []) then typ_error env l ("Universally quantified constraint generated: " ^ Util.string_of_list ", " string_of_kid kids2) else (); let env = Env.add_constraint (nc_eq nexp1 nexp2) env in if prove __POS__ env nc2 then () - else typ_raise l (Err_subtype (typ1, typ2, Env.get_constraints env, Env.get_typ_var_locs env)) + else typ_raise env l (Err_subtype (typ1, typ2, Env.get_constraints env, Env.get_typ_var_locs env)) | _, _ -> match typ_aux1, typ_aux2 with | _, Typ_internal_unknown when Env.allow_unknowns env -> () @@ -1837,16 +1839,16 @@ let rec subtyp l env typ1 typ2 = let typ1 = canonicalize env typ1 in let env = add_typ_vars l kopts env in let kids' = KidSet.elements (KidSet.diff (KidSet.of_list (List.map kopt_kid kopts)) (tyvars_of_typ typ2)) in - if not (kids' = []) then typ_error l "Universally quantified constraint generated" else (); + if not (kids' = []) then typ_error env l "Universally quantified constraint generated" else (); let unifiers = try unify l env (KidSet.diff (tyvars_of_typ typ2) (tyvars_of_typ typ1)) typ2 typ1 with - | Unification_error (_, m) -> typ_error l m + | Unification_error (_, m) -> typ_error env l m in let nc = List.fold_left (fun nc (kid, uvar) -> constraint_subst kid uvar nc) nc (KBindings.bindings unifiers) in let env = List.fold_left unifier_constraint env (KBindings.bindings unifiers) in if prove __POS__ env nc then () - else typ_raise l (Err_subtype (typ1, typ2, Env.get_constraints env, Env.get_typ_var_locs env)) - | None, None -> typ_raise l (Err_subtype (typ1, typ2, Env.get_constraints env, Env.get_typ_var_locs env)) + else typ_raise env l (Err_subtype (typ1, typ2, Env.get_constraints env, Env.get_typ_var_locs env)) + | None, None -> typ_raise env l (Err_subtype (typ1, typ2, Env.get_constraints env, Env.get_typ_var_locs env)) and subtyp_arg l env (A_aux (aux1, _) as arg1) (A_aux (aux2, _) as arg2) = typ_print (lazy (("Subtype arg " |> Util.green |> Util.clear) ^ string_of_typ_arg arg1 ^ " and " ^ string_of_typ_arg arg2)); @@ -1855,7 +1857,7 @@ and subtyp_arg l env (A_aux (aux1, _) as arg1) (A_aux (aux2, _) as arg2) = | A_typ typ1, A_typ typ2 -> subtyp l env typ1 typ2 | A_order ord1, A_order ord2 when ord_identical ord1 ord2 -> () | A_bool nc1, A_bool nc2 when prove __POS__ env (nc_and (nc_or (nc_not nc1) nc2) (nc_or (nc_not nc2) nc1)) -> () - | _, _ -> typ_error l "Mismatched argument types in subtype check" + | _, _ -> typ_error env l "Mismatched argument types in subtype check" let typ_equality l env typ1 typ2 = subtyp l env typ1 typ2; subtyp l env typ2 typ1 @@ -1936,16 +1938,16 @@ let infer_lit env (L_aux (lit_aux, l) as lit) = match Env.get_default_order env with | Ord_aux (Ord_inc, _) | Ord_aux (Ord_dec, _) -> dvector_typ env (nint (String.length str)) (mk_typ (Typ_id (mk_id "bit"))) - | Ord_aux (Ord_var _, _) -> typ_error l default_order_error_string + | Ord_aux (Ord_var _, _) -> typ_error env l default_order_error_string end | L_hex str -> begin match Env.get_default_order env with | Ord_aux (Ord_inc, _) | Ord_aux (Ord_dec, _) -> dvector_typ env (nint (String.length str * 4)) (mk_typ (Typ_id (mk_id "bit"))) - | Ord_aux (Ord_var _, _) -> typ_error l default_order_error_string + | Ord_aux (Ord_var _, _) -> typ_error env l default_order_error_string end - | L_undef -> typ_error l "Cannot infer the type of undefined" + | L_undef -> typ_error env l "Cannot infer the type of undefined" let is_nat_kid kid = function | KOpt_aux (KOpt_kind (K_aux (K_int, _), kid'), _) -> Kid.compare kid kid' = 0 @@ -1995,7 +1997,7 @@ let destruct_vec_typ l env typ = A_aux (A_order o, _); A_aux (A_typ vtyp, _)] ), _) when string_of_id id = "vector" -> (n1, o, vtyp) - | typ -> typ_error l ("Expected vector type, got " ^ string_of_typ typ) + | typ -> typ_error env l ("Expected vector type, got " ^ string_of_typ typ) in destruct_vec_typ' l (Env.expand_synonyms env typ) @@ -2052,7 +2054,7 @@ let to_simple_numeric l kids nc (Nexp_aux (aux, _) as n) = | _, [] -> Equal n | _ -> - typ_error l "Numeric type is non-simple" + typ_error Env.empty l "Numeric type is non-simple" let union_simple_numeric ex1 ex2 = match ex1, ex2 with @@ -2205,7 +2207,7 @@ let crule r env exp typ = Env.wf_typ env (typ_of checked_exp); decr depth; checked_exp with - | Type_error (l, err) -> decr depth; typ_raise l err + | Type_error (env, l, err) -> decr depth; typ_raise env l err let irule r env exp = incr depth; @@ -2216,7 +2218,7 @@ let irule r env exp = decr depth; inferred_exp with - | Type_error (l, err) -> decr depth; typ_raise l err + | Type_error (env, l, err) -> decr depth; typ_raise env l err (* This function adds useful assertion messages to asserts missing them *) @@ -2266,7 +2268,7 @@ let rec check_exp env (E_aux (exp_aux, (l, ())) as exp : unit exp) (Typ_aux (typ let checked_xs = crule check_exp env xs typ in let checked_x = crule check_exp env x elem_typ in annot_exp (E_cons (checked_x, checked_xs)) typ - | None -> typ_error l ("Cons " ^ string_of_exp exp ^ " must have list type, got " ^ string_of_typ typ) + | None -> typ_error env l ("Cons " ^ string_of_exp exp ^ " must have list type, got " ^ string_of_typ typ) end | E_list xs, _ -> begin @@ -2274,7 +2276,7 @@ let rec check_exp env (E_aux (exp_aux, (l, ())) as exp : unit exp) (Typ_aux (typ | Some elem_typ -> let checked_xs = List.map (fun x -> crule check_exp env x elem_typ) xs in annot_exp (E_list checked_xs) typ - | None -> typ_error l ("List " ^ string_of_exp exp ^ " must have list type, got " ^ string_of_typ typ) + | None -> typ_error env l ("List " ^ string_of_exp exp ^ " must have list type, got " ^ string_of_typ typ) end | E_record_update (exp, fexps), _ -> (* TODO: this could also infer exp - also fix code duplication with E_record below *) @@ -2282,11 +2284,11 @@ let rec check_exp env (E_aux (exp_aux, (l, ())) as exp : unit exp) (Typ_aux (typ let rectyp_id = match Env.expand_synonyms env typ with | Typ_aux (Typ_id rectyp_id, _) | Typ_aux (Typ_app (rectyp_id, _), _) when Env.is_record rectyp_id env -> rectyp_id - | _ -> typ_error l ("The type " ^ string_of_typ typ ^ " is not a record") + | _ -> typ_error env l ("The type " ^ string_of_typ typ ^ " is not a record") in let check_fexp (FE_aux (FE_Fexp (field, exp), (l, ()))) = let (typq, rectyp_q, field_typ, _) = Env.get_accessor rectyp_id field env in - let unifiers = try unify l env (tyvars_of_typ rectyp_q) rectyp_q typ with Unification_error (l, m) -> typ_error l ("Unification error: " ^ m) in + let unifiers = try unify l env (tyvars_of_typ rectyp_q) rectyp_q typ with Unification_error (l, m) -> typ_error env l ("Unification error: " ^ m) in let field_typ' = subst_unifiers unifiers field_typ in let checked_exp = crule check_exp env exp field_typ' in FE_aux (FE_Fexp (field, checked_exp), (l, None)) @@ -2297,11 +2299,11 @@ let rec check_exp env (E_aux (exp_aux, (l, ())) as exp : unit exp) (Typ_aux (typ let rectyp_id = match Env.expand_synonyms env typ with | Typ_aux (Typ_id rectyp_id, _) | Typ_aux (Typ_app (rectyp_id, _), _) when Env.is_record rectyp_id env -> rectyp_id - | _ -> typ_error l ("The type " ^ string_of_typ typ ^ " is not a record") + | _ -> typ_error env l ("The type " ^ string_of_typ typ ^ " is not a record") in let check_fexp (FE_aux (FE_Fexp (field, exp), (l, ()))) = let (typq, rectyp_q, field_typ, _) = Env.get_accessor rectyp_id field env in - let unifiers = try unify l env (tyvars_of_typ rectyp_q) rectyp_q typ with Unification_error (l, m) -> typ_error l ("Unification error: " ^ m) in + let unifiers = try unify l env (tyvars_of_typ rectyp_q) rectyp_q typ with Unification_error (l, m) -> typ_error env l ("Unification error: " ^ m) in let field_typ' = subst_unifiers unifiers field_typ in let checked_exp = crule check_exp env exp field_typ' in FE_aux (FE_Fexp (field, checked_exp), (l, None)) @@ -2326,11 +2328,11 @@ let rec check_exp env (E_aux (exp_aux, (l, ())) as exp : unit exp) (Typ_aux (typ Env.wf_constraint env nc; if prove __POS__ env nc then annot_exp (E_lit (L_aux (L_unit, Parse_ast.Unknown))) unit_typ - else typ_error l ("Cannot prove " ^ string_of_n_constraint nc) + else typ_error env l ("Cannot prove " ^ string_of_n_constraint nc) | E_app (f, [E_aux (E_constraint nc, _)]), _ when string_of_id f = "_not_prove" -> Env.wf_constraint env nc; if prove __POS__ env nc - then typ_error l ("Can prove " ^ string_of_n_constraint nc) + then typ_error env l ("Can prove " ^ string_of_n_constraint nc) else annot_exp (E_lit (L_aux (L_unit, Parse_ast.Unknown))) unit_typ | E_app (f, [E_aux (E_cast (typ, exp), _)]), _ when string_of_id f = "_check" -> Env.wf_typ env typ; @@ -2340,7 +2342,7 @@ let rec check_exp env (E_aux (exp_aux, (l, ())) as exp : unit exp) (Typ_aux (typ Env.wf_typ env typ; if (try (ignore (crule check_exp env exp typ); false) with Type_error _ -> true) then annot_exp (E_lit (L_aux (L_unit, Parse_ast.Unknown))) unit_typ - else typ_error l (Printf.sprintf "Expected _not_check(%s : %s) to fail" (string_of_exp exp) (string_of_typ typ)) + else typ_error env l (Printf.sprintf "Expected _not_check(%s : %s) to fail" (string_of_exp exp) (string_of_typ typ)) (* All constructors and mappings are treated as having one argument so Ctor(x, y) is checked as Ctor((x, y)) *) | E_app (f, x :: y :: zs), _ when Env.is_union_constructor f env || Env.is_mapping f env -> @@ -2351,22 +2353,22 @@ let rec check_exp env (E_aux (exp_aux, (l, ())) as exp : unit exp) (Typ_aux (typ let backwards_id = mk_id (string_of_id mapping ^ "_backwards") in typ_print (lazy("Trying forwards direction for mapping " ^ string_of_id mapping ^ "(" ^ string_of_list ", " string_of_exp xs ^ ")")); begin try crule check_exp env (E_aux (E_app (forwards_id, xs), (l, ()))) typ with - | Type_error (_, err1) -> + | Type_error (_, _, err1) -> (* typ_print (lazy ("Error in forwards direction: " ^ string_of_type_error err1)); *) typ_print (lazy ("Trying backwards direction for mapping " ^ string_of_id mapping ^ "(" ^ string_of_list ", " string_of_exp xs ^ ")")); begin try crule check_exp env (E_aux (E_app (backwards_id, xs), (l, ()))) typ with - | Type_error (_, err2) -> + | Type_error (_, _, err2) -> (* typ_print (lazy ("Error in backwards direction: " ^ string_of_type_error err2)); *) - typ_raise l (Err_no_overloading (mapping, [(forwards_id, err1); (backwards_id, err2)])) + typ_raise env l (Err_no_overloading (mapping, [(forwards_id, err1); (backwards_id, err2)])) end end | E_app (f, xs), _ when List.length (Env.get_overloads f env) > 0 -> let rec try_overload = function - | (errs, []) -> typ_raise l (Err_no_overloading (f, errs)) + | (errs, []) -> typ_raise env l (Err_no_overloading (f, errs)) | (errs, (f :: fs)) -> begin typ_print (lazy ("Overload: " ^ string_of_id f ^ "(" ^ string_of_list ", " string_of_exp xs ^ ")")); try crule check_exp env (E_aux (E_app (f, xs), (l, ()))) typ with - | Type_error (_, err) -> + | Type_error (_, _, err) -> typ_debug (lazy "Error"); try_overload (errs @ [(f, err)], fs) end @@ -2375,7 +2377,7 @@ let rec check_exp env (E_aux (exp_aux, (l, ())) as exp : unit exp) (Typ_aux (typ | E_return exp, _ -> let checked_exp = match Env.get_ret_typ env with | Some ret_typ -> crule check_exp env exp ret_typ - | None -> typ_error l "Cannot use return outside a function" + | None -> typ_error env l "Cannot use return outside a function" in annot_exp (E_return checked_exp) typ | E_tuple exps, Typ_tup typs when List.length exps = List.length typs -> @@ -2441,11 +2443,11 @@ let rec check_exp env (E_aux (exp_aux, (l, ())) as exp : unit exp) (Typ_aux (typ let (len, ord, vtyp) = destruct_vec_typ l env typ in let checked_items = List.map (fun i -> crule check_exp env i vtyp) vec in if prove __POS__ env (nc_eq (nint (List.length vec)) (nexp_simp len)) then annot_exp (E_vector checked_items) typ - else typ_error l "List length didn't match" (* FIXME: improve error message *) + else typ_error env l "List length didn't match" (* FIXME: improve error message *) | E_lit (L_aux (L_undef, _) as lit), _ -> if is_typ_monomorphic typ || Env.polymorphic_undefineds env then annot_exp_effect (E_lit lit) typ (mk_effect [BE_undef]) - else typ_error l ("Type " ^ string_of_typ typ ^ " failed undefined monomorphism restriction") + else typ_error env l ("Type " ^ string_of_typ typ ^ " failed undefined monomorphism restriction") | _, _ -> let inferred_exp = irule infer_exp env exp in type_coercion env inferred_exp typ @@ -2554,14 +2556,14 @@ and type_coercion env (E_aux (_, (l, _)) as annotated_exp) typ = | _ -> failwith "Cannot switch type for unannotated function" in let rec try_casts trigger errs = function - | [] -> typ_raise l (Err_no_casts (strip_exp annotated_exp, typ_of annotated_exp, typ, trigger, errs)) + | [] -> typ_raise env l (Err_no_casts (strip_exp annotated_exp, typ_of annotated_exp, typ, trigger, errs)) | (cast :: casts) -> begin typ_print (lazy ("Casting with " ^ string_of_id cast ^ " expression " ^ string_of_exp annotated_exp ^ " to " ^ string_of_typ typ)); try let checked_cast = crule check_exp (Env.no_casts env) (strip (E_app (cast, [annotated_exp]))) typ in annot_exp (E_cast (typ, checked_cast)) typ with - | Type_error (_, err) -> try_casts trigger (err :: errs) casts + | Type_error (_, _, err) -> try_casts trigger (err :: errs) casts end in begin @@ -2569,10 +2571,10 @@ and type_coercion env (E_aux (_, (l, _)) as annotated_exp) typ = typ_debug (lazy ("Performing type coercion: from " ^ string_of_typ (typ_of annotated_exp) ^ " to " ^ string_of_typ typ)); subtyp l env (typ_of annotated_exp) typ; switch_exp_typ annotated_exp with - | Type_error (_, trigger) when Env.allow_casts env -> + | Type_error (_, _, trigger) when Env.allow_casts env -> let casts = filter_casts env (typ_of annotated_exp) typ (Env.get_casts env) in try_casts trigger [] casts - | Type_error (l, err) -> typ_raise l err + | Type_error (env, l, err) -> typ_raise env l err end (* type_coercion_unify env exp typ attempts to coerce exp to a type @@ -2596,7 +2598,7 @@ and type_coercion_unify env goals (E_aux (_, (l, _)) as annotated_exp) typ = let ityp, env = bind_existential l None (typ_of inferred_cast) env in inferred_cast, unify l env goals typ ityp, env with - | Type_error (_, err) -> try_casts casts + | Type_error (_, _, err) -> try_casts casts | Unification_error (_, err) -> try_casts casts end in @@ -2613,7 +2615,7 @@ and type_coercion_unify env goals (E_aux (_, (l, _)) as annotated_exp) typ = and bind_pat_no_guard env (P_aux (_,(l,_)) as pat) typ = match bind_pat env pat typ with - | _, _, _::_ -> typ_error l "Literal patterns not supported here" + | _, _, _::_ -> typ_error env l "Literal patterns not supported here" | tpat, env, [] -> tpat, env and bind_pat env (P_aux (pat_aux, (l, ())) as pat) (Typ_aux (typ_aux, _) as typ) = @@ -2622,7 +2624,7 @@ and bind_pat env (P_aux (pat_aux, (l, ())) as pat) (Typ_aux (typ_aux, _) as typ) let annot_pat pat typ' = P_aux (pat, (l, mk_expected_tannot env typ' no_effect (Some typ))) in let switch_typ pat typ = match pat with | P_aux (pat_aux, (l, Some tannot)) -> P_aux (pat_aux, (l, Some { tannot with typ = typ })) - | _ -> typ_error l "Cannot switch type for unannotated pattern" + | _ -> typ_error env l "Cannot switch type for unannotated pattern" in let bind_tuple_pat (tpats, env, guards) pat typ = let tpat, env, guards' = bind_pat env pat typ in tpat :: tpats, env, guards' @ guards @@ -2640,7 +2642,7 @@ and bind_pat env (P_aux (pat_aux, (l, ())) as pat) (Typ_aux (typ_aux, _) as typ) match Env.lookup_id v env with | Local _ | Unbound -> annot_pat (P_id v) typ, Env.add_local v (Immutable, typ) env, [] | Register _ -> - typ_error l ("Cannot shadow register in pattern " ^ string_of_pat pat) + typ_error env l ("Cannot shadow register in pattern " ^ string_of_pat pat) | Enum enum -> subtyp l env enum typ; annot_pat (P_id v) typ, env, [] end | P_var (pat, typ_pat) -> @@ -2662,7 +2664,7 @@ and bind_pat env (P_aux (pat_aux, (l, ())) as pat) (Typ_aux (typ_aux, _) as typ) let hd_pat, env, hd_guards = bind_pat env hd_pat ltyp in let tl_pat, env, tl_guards = bind_pat env tl_pat typ in annot_pat (P_cons (hd_pat, tl_pat)) typ, env, hd_guards @ tl_guards - | _ -> typ_error l "Cannot match cons pattern against non-list type" + | _ -> typ_error env l "Cannot match cons pattern against non-list type" end | P_string_append pats -> begin @@ -2677,7 +2679,7 @@ and bind_pat env (P_aux (pat_aux, (l, ())) as pat) (Typ_aux (typ_aux, _) as typ) in let pats, env, guards = process_pats env pats in annot_pat (P_string_append pats) typ, env, guards - | _ -> typ_error l "Cannot match string-append pattern against non-string type" + | _ -> typ_error env l "Cannot match string-append pattern against non-string type" end | P_list pats -> begin @@ -2692,14 +2694,14 @@ and bind_pat env (P_aux (pat_aux, (l, ())) as pat) (Typ_aux (typ_aux, _) as typ) in let pats, env, guards = process_pats env pats in annot_pat (P_list pats) typ, env, guards - | _ -> typ_error l ("Cannot match list pattern " ^ string_of_pat pat ^ " against non-list type " ^ string_of_typ typ) + | _ -> typ_error env l ("Cannot match list pattern " ^ string_of_pat pat ^ " against non-list type " ^ string_of_typ typ) end | P_tup [] -> begin match Env.expand_synonyms env typ with | Typ_aux (Typ_id typ_id, _) when string_of_id typ_id = "unit" -> annot_pat (P_tup []) typ, env, [] - | _ -> typ_error l "Cannot match unit pattern against non-unit type" + | _ -> typ_error env l "Cannot match unit pattern against non-unit type" end | P_tup pats -> begin @@ -2707,11 +2709,11 @@ and bind_pat env (P_aux (pat_aux, (l, ())) as pat) (Typ_aux (typ_aux, _) as typ) | Typ_aux (Typ_tup typs, _) -> let tpats, env, guards = try List.fold_left2 bind_tuple_pat ([], env, []) pats typs with - | Invalid_argument _ -> typ_error l "Tuple pattern and tuple type have different length" + | Invalid_argument _ -> typ_error env l "Tuple pattern and tuple type have different length" in annot_pat (P_tup (List.rev tpats)) typ, env, guards | _ -> - typ_error l (Printf.sprintf "Cannot bind tuple pattern %s against non tuple type %s" + typ_error env l (Printf.sprintf "Cannot bind tuple pattern %s against non tuple type %s" (string_of_pat pat) (string_of_typ typ)) end | P_app (f, pats) when Env.is_union_constructor f env -> @@ -2732,18 +2734,18 @@ and bind_pat env (P_aux (pat_aux, (l, ())) as pat) (Typ_aux (typ_aux, _) as typ) let arg_typ' = subst_unifiers unifiers arg_typ in let quants' = List.fold_left instantiate_quants quants (KBindings.bindings unifiers) in if not (List.for_all (solve_quant env) quants') then - typ_raise l (Err_unresolved_quants (f, quants', Env.get_locals env, Env.get_constraints env)) + typ_raise env l (Err_unresolved_quants (f, quants', Env.get_locals env, Env.get_constraints env)) else (); let ret_typ' = subst_unifiers unifiers ret_typ in let tpats, env, guards = try List.fold_left2 bind_tuple_pat ([], env, []) pats (untuple arg_typ') with - | Invalid_argument _ -> typ_error l "Union constructor pattern arguments have incorrect length" + | Invalid_argument _ -> typ_error env l "Union constructor pattern arguments have incorrect length" in annot_pat (P_app (f, List.rev tpats)) typ, env, guards with - | Unification_error (l, m) -> typ_error l ("Unification error when pattern matching against union constructor: " ^ m) + | Unification_error (l, m) -> typ_error env l ("Unification error when pattern matching against union constructor: " ^ m) end - | _ -> typ_error l ("Mal-formed constructor " ^ string_of_id f ^ " with type " ^ string_of_typ ctor_typ) + | _ -> typ_error env l ("Mal-formed constructor " ^ string_of_id f ^ " with type " ^ string_of_typ ctor_typ) end | P_app (f, pats) when Env.is_mapping f env -> @@ -2765,13 +2767,13 @@ and bind_pat env (P_aux (pat_aux, (l, ())) as pat) (Typ_aux (typ_aux, _) as typ) let arg_typ' = subst_unifiers unifiers typ1 in let quants' = List.fold_left instantiate_quants quants (KBindings.bindings unifiers) in if (match quants' with [] -> false | _ -> true) - then typ_error l ("Quantifiers " ^ string_of_list ", " string_of_quant_item quants' ^ " not resolved in pattern " ^ string_of_pat pat) + then typ_error env l ("Quantifiers " ^ string_of_list ", " string_of_quant_item quants' ^ " not resolved in pattern " ^ string_of_pat pat) else (); let ret_typ' = subst_unifiers unifiers typ2 in let tpats, env, guards = try List.fold_left2 bind_tuple_pat ([], env, []) pats (untuple arg_typ') with - | Invalid_argument _ -> typ_error l "Mapping pattern arguments have incorrect length" + | Invalid_argument _ -> typ_error env l "Mapping pattern arguments have incorrect length" in annot_pat (P_app (f, List.rev tpats)) typ, env, guards with @@ -2783,22 +2785,22 @@ and bind_pat env (P_aux (pat_aux, (l, ())) as pat) (Typ_aux (typ_aux, _) as typ) let arg_typ' = subst_unifiers unifiers typ2 in let quants' = List.fold_left instantiate_quants quants (KBindings.bindings unifiers) in if (match quants' with [] -> false | _ -> true) - then typ_error l ("Quantifiers " ^ string_of_list ", " string_of_quant_item quants' ^ " not resolved in pattern " ^ string_of_pat pat) + then typ_error env l ("Quantifiers " ^ string_of_list ", " string_of_quant_item quants' ^ " not resolved in pattern " ^ string_of_pat pat) else (); let ret_typ' = subst_unifiers unifiers typ1 in let tpats, env, guards = try List.fold_left2 bind_tuple_pat ([], env, []) pats (untuple arg_typ') with - | Invalid_argument _ -> typ_error l "Mapping pattern arguments have incorrect length" + | Invalid_argument _ -> typ_error env l "Mapping pattern arguments have incorrect length" in annot_pat (P_app (f, List.rev tpats)) typ, env, guards with - | Unification_error (l, m) -> typ_error l ("Unification error when pattern matching against mapping constructor: " ^ m) + | Unification_error (l, m) -> typ_error env l ("Unification error when pattern matching against mapping constructor: " ^ m) end - | _ -> typ_error l ("Mal-formed mapping " ^ string_of_id f) + | _ -> typ_error env l ("Mal-formed mapping " ^ string_of_id f) end | P_app (f, _) when (not (Env.is_union_constructor f env) && not (Env.is_mapping f env)) -> - typ_error l (string_of_id f ^ " is not a union constructor or mapping in pattern " ^ string_of_pat pat) + typ_error env l (string_of_id f ^ " is not a union constructor or mapping in pattern " ^ string_of_pat pat) | P_as (pat, id) -> let (typed_pat, env, guards) = bind_pat env pat typ in annot_pat (P_as (typed_pat, id)) (typ_of_pat typed_pat), Env.add_local id (Immutable, typ_of_pat typed_pat) env, guards @@ -2832,9 +2834,9 @@ and infer_pat env (P_aux (pat_aux, (l, ())) as pat) = begin match Env.lookup_id v env with | Local (Immutable, _) | Unbound -> - typ_error l ("Cannot infer identifier in pattern " ^ string_of_pat pat ^ " - try adding a type annotation") + typ_error env l ("Cannot infer identifier in pattern " ^ string_of_pat pat ^ " - try adding a type annotation") | Local (Mutable, _) | Register _ -> - typ_error l ("Cannot shadow mutable local or register in switch statement pattern " ^ string_of_pat pat) + typ_error env l ("Cannot shadow mutable local or register in switch statement pattern " ^ string_of_pat pat) | Enum enum -> annot_pat (P_id v) enum, env, [] end | P_app (f, mpats) when Env.is_union_constructor f env -> @@ -2843,7 +2845,7 @@ and infer_pat env (P_aux (pat_aux, (l, ())) as pat) = match Env.expand_synonyms env ctor_typ with | Typ_aux (Typ_fn (arg_typ, ret_typ, _), _) -> bind_pat env pat ret_typ - | _ -> typ_error l ("Mal-formed constructor " ^ string_of_id f) + | _ -> typ_error env l ("Mal-formed constructor " ^ string_of_id f) end | P_app (f, mpats) when Env.is_mapping f env -> begin @@ -2857,7 +2859,7 @@ and infer_pat env (P_aux (pat_aux, (l, ())) as pat) = | Type_error _ -> bind_pat env pat typ1 end - | _ -> typ_error l ("Malformed mapping type " ^ string_of_id f) + | _ -> typ_error env l ("Malformed mapping type " ^ string_of_id f) end | P_typ (typ_annot, pat) -> Env.wf_typ env typ_annot; @@ -2905,7 +2907,7 @@ and infer_pat env (P_aux (pat_aux, (l, ())) as pat) = annot_pat (P_as (typed_pat, id)) (typ_of_pat typed_pat), Env.add_local id (Immutable, typ_of_pat typed_pat) env, guards - | _ -> typ_error l ("Couldn't infer type of pattern " ^ string_of_pat pat) + | _ -> typ_error env l ("Couldn't infer type of pattern " ^ string_of_pat pat) and bind_typ_pat env (TP_aux (typ_pat_aux, l) as typ_pat) (Typ_aux (typ_aux, _) as typ) = match typ_pat_aux, typ_aux with @@ -2916,21 +2918,21 @@ and bind_typ_pat env (TP_aux (typ_pat_aux, l) as typ_pat) (Typ_aux (typ_aux, _) | [nexp] -> Env.add_constraint (nc_eq (nvar kid) nexp) (Env.add_typ_var l (mk_kopt K_int kid) env) | [] -> - typ_error l ("No numeric expressions in " ^ string_of_typ typ ^ " to bind " ^ string_of_kid kid ^ " to") + typ_error env l ("No numeric expressions in " ^ string_of_typ typ ^ " to bind " ^ string_of_kid kid ^ " to") | nexps -> - typ_error l ("Type " ^ string_of_typ typ ^ " has multiple numeric expressions. Cannot bind " ^ string_of_kid kid) + typ_error env l ("Type " ^ string_of_typ typ ^ " has multiple numeric expressions. Cannot bind " ^ string_of_kid kid) end | TP_app (f1, tpats), Typ_app (f2, typs) when Id.compare f1 f2 = 0 -> List.fold_left2 bind_typ_pat_arg env tpats typs - | _, _ -> typ_error l ("Couldn't bind type " ^ string_of_typ typ ^ " with " ^ string_of_typ_pat typ_pat) + | _, _ -> typ_error env l ("Couldn't bind type " ^ string_of_typ typ ^ " with " ^ string_of_typ_pat typ_pat) and bind_typ_pat_arg env (TP_aux (typ_pat_aux, l) as typ_pat) (A_aux (typ_arg_aux, _) as typ_arg) = match typ_pat_aux, typ_arg_aux with | TP_wild, _ -> env | TP_var kid, A_nexp nexp -> Env.add_constraint (nc_eq (nvar kid) nexp) (Env.add_typ_var l (mk_kopt K_int kid) env) | _, A_typ typ -> bind_typ_pat env typ_pat typ - | _, A_order _ -> typ_error l "Cannot bind type pattern against order" - | _, _ -> typ_error l ("Couldn't bind type argument " ^ string_of_typ_arg typ_arg ^ " with " ^ string_of_typ_pat typ_pat) + | _, A_order _ -> typ_error env l "Cannot bind type pattern against order" + | _, _ -> typ_error env l ("Couldn't bind type argument " ^ string_of_typ_arg typ_arg ^ " with " ^ string_of_typ_pat typ_pat) and bind_assignment env (LEXP_aux (lexp_aux, _) as lexp) (E_aux (_, (l, ())) as exp) = let annot_assign lexp exp = E_aux (E_assign (lexp, exp), (l, mk_tannot env (mk_typ (Typ_id (mk_id "unit"))) no_effect)) in @@ -2949,14 +2951,14 @@ and bind_assignment env (LEXP_aux (lexp_aux, _) as lexp) (E_aux (_, (l, ())) as begin match Env.lookup_id v env with | Register (_, _, typ) -> typ, LEXP_id v, true | Local (Mutable, typ) -> typ, LEXP_id v, false - | _ -> typ_error l "l-expression field is not a register or a local mutable type" + | _ -> typ_error env l "l-expression field is not a register or a local mutable type" end | LEXP_vector (LEXP_aux (LEXP_id v, _), exp) -> begin (* Check: is this ok if the vector is immutable? *) let is_immutable, vtyp, is_register = match Env.lookup_id v env with - | Unbound -> typ_error l "Cannot assign to element of unbound vector" - | Enum _ -> typ_error l "Cannot vector assign to enumeration element" + | Unbound -> typ_error env l "Cannot assign to element of unbound vector" + | Enum _ -> typ_error env l "Cannot vector assign to enumeration element" | Local (Immutable, vtyp) -> true, vtyp, false | Local (Mutable, vtyp) -> false, vtyp, false | Register (_, _, vtyp) -> false, vtyp, true @@ -2968,7 +2970,7 @@ and bind_assignment env (LEXP_aux (lexp_aux, _) as lexp) (E_aux (_, (l, ())) as in typ_of access, LEXP_vector (annot_lexp (LEXP_id v) vtyp, inferred_exp), is_register end - | _ -> typ_error l "Field l-expression must be either a vector or an identifier" + | _ -> typ_error env l "Field l-expression must be either a vector or an identifier" in let regtyp, inferred_flexp, is_register = infer_flexp flexp in typ_debug (lazy ("REGTYP: " ^ string_of_typ regtyp ^ " / " ^ string_of_typ (Env.expand_synonyms env regtyp))); @@ -2976,11 +2978,11 @@ and bind_assignment env (LEXP_aux (lexp_aux, _) as lexp) (E_aux (_, (l, ())) as | Typ_aux (Typ_id rectyp_id, _) | Typ_aux (Typ_app (rectyp_id, _), _) when Env.is_record rectyp_id env -> let eff = if is_register then mk_effect [BE_wreg] else no_effect in let (typq, rectyp_q, field_typ, _) = Env.get_accessor rectyp_id field env in - let unifiers = try unify l env (tyvars_of_typ rectyp_q) rectyp_q regtyp with Unification_error (l, m) -> typ_error l ("Unification error: " ^ m) in + let unifiers = try unify l env (tyvars_of_typ rectyp_q) rectyp_q regtyp with Unification_error (l, m) -> typ_error env l ("Unification error: " ^ m) in let field_typ' = subst_unifiers unifiers field_typ in let checked_exp = crule check_exp env exp field_typ' in annot_assign (annot_lexp (LEXP_field (annot_lexp_effect inferred_flexp regtyp eff, field)) field_typ') checked_exp, env - | _ -> typ_error l "Field l-expression has invalid type" + | _ -> typ_error env l "Field l-expression has invalid type" end | LEXP_memory (f, xs) -> check_exp env (E_aux (E_app (f, xs @ [exp]), (l, ()))) unit_typ, env @@ -3006,12 +3008,12 @@ and bind_assignment env (LEXP_aux (lexp_aux, _) as lexp) (E_aux (_, (l, ())) as let tlexp, env' = bind_lexp env lexp (typ_of inferred_exp) in annot_assign tlexp inferred_exp, env' with - | Type_error (l, err) -> + | Type_error (_, l, err) -> try let inferred_lexp = infer_lexp env lexp in let checked_exp = crule check_exp env exp (lexp_typ_of inferred_lexp) in annot_assign inferred_lexp checked_exp, env - with Type_error (l, err') -> typ_raise l (Err_because (err', err)) + with Type_error (env, l', err') -> typ_raise env l' (Err_because (err', l, err)) and bind_lexp env (LEXP_aux (lexp_aux, (l, ())) as lexp) typ = typ_print (lazy ("Binding mutable " ^ string_of_lexp lexp ^ " to " ^ string_of_typ typ)); @@ -3021,7 +3023,7 @@ and bind_lexp env (LEXP_aux (lexp_aux, (l, ())) as lexp) typ = | LEXP_cast (typ_annot, v) -> begin match Env.lookup_id ~raw:true v env with | Local (Immutable, _) | Enum _ -> - typ_error l ("Cannot modify let-bound constant or enumeration constructor " ^ string_of_id v) + typ_error env l ("Cannot modify let-bound constant or enumeration constructor " ^ string_of_id v) | Local (Mutable, vtyp) -> subtyp l env typ typ_annot; subtyp l env typ_annot vtyp; @@ -3040,12 +3042,12 @@ and bind_lexp env (LEXP_aux (lexp_aux, (l, ())) as lexp) typ = | Typ_aux (Typ_app (r, [A_aux (A_typ vtyp, _)]), _) when string_of_id r = "register" -> subtyp l env typ vtyp; annot_lexp_effect (LEXP_deref inferred_exp) typ (mk_effect [BE_wreg]), env | _ -> - typ_error l (string_of_typ typ ^ " must be a register type in " ^ string_of_exp exp ^ ")") + typ_error env l (string_of_typ typ ^ " must be a register type in " ^ string_of_exp exp ^ ")") end | LEXP_id v -> begin match Env.lookup_id ~raw:true v env with | Local (Immutable, _) | Enum _ -> - typ_error l ("Cannot modify let-bound constant or enumeration constructor " ^ string_of_id v) + typ_error env l ("Cannot modify let-bound constant or enumeration constructor " ^ string_of_id v) | Local (Mutable, vtyp) -> subtyp l env typ vtyp; annot_lexp (LEXP_id v) typ, Env.remove_flow v env | Register (_, weff, vtyp) -> subtyp l env typ vtyp; annot_lexp_effect (LEXP_id v) typ weff, env | Unbound -> annot_lexp (LEXP_id v) typ, Env.add_local v (Mutable, typ) env @@ -3061,10 +3063,10 @@ and bind_lexp env (LEXP_aux (lexp_aux, (l, ())) as lexp) typ = in let tlexps, env = try List.fold_right2 bind_tuple_lexp lexps typs ([], env) with - | Invalid_argument _ -> typ_error l "Tuple l-expression and tuple type have different length" + | Invalid_argument _ -> typ_error env l "Tuple l-expression and tuple type have different length" in annot_lexp (LEXP_tup tlexps) typ, env - | _ -> typ_error l ("Cannot bind tuple l-expression against non tuple type " ^ string_of_typ typ) + | _ -> typ_error env l ("Cannot bind tuple l-expression against non tuple type " ^ string_of_typ typ) end | _ -> let inferred_lexp = infer_lexp env lexp in @@ -3081,9 +3083,9 @@ and infer_lexp env (LEXP_aux (lexp_aux, (l, ())) as lexp) = (* Probably need to remove flows here *) | Register (_, weff, typ) -> annot_lexp_effect (LEXP_id v) typ weff | Local (Immutable, _) | Enum _ -> - typ_error l ("Cannot modify let-bound constant or enumeration constructor " ^ string_of_id v) + typ_error env l ("Cannot modify let-bound constant or enumeration constructor " ^ string_of_id v) | Unbound -> - typ_error l ("Cannot create a new identifier in this l-expression " ^ string_of_lexp lexp) + typ_error env l ("Cannot create a new identifier in this l-expression " ^ string_of_lexp lexp) end | LEXP_vector_range (v_lexp, exp1, exp2) -> begin @@ -3103,9 +3105,9 @@ and infer_lexp env (LEXP_aux (lexp_aux, (l, ())) as lexp) = | Ord_aux (Ord_dec, _) when !opt_no_lexp_bounds_check || prove __POS__ env (nc_gteq nexp1 nexp2) -> let len = nexp_simp (nsum (nminus nexp1 nexp2) (nint 1)) in annot_lexp (LEXP_vector_range (inferred_v_lexp, inferred_exp1, inferred_exp2)) (vector_typ len ord elem_typ) - | _ -> typ_error l ("Could not infer length of vector slice assignment " ^ string_of_lexp lexp) + | _ -> typ_error env l ("Could not infer length of vector slice assignment " ^ string_of_lexp lexp) end - | _ -> typ_error l "Cannot assign slice of non vector type" + | _ -> typ_error env l "Cannot assign slice of non vector type" end | LEXP_vector (v_lexp, exp) -> begin @@ -3119,10 +3121,10 @@ and infer_lexp env (LEXP_aux (lexp_aux, (l, ())) as lexp) = if !opt_no_lexp_bounds_check || prove __POS__ env (nc_and (nc_lteq (nint 0) nexp) (nc_lteq nexp (nexp_simp (nminus len (nint 1))))) then annot_lexp (LEXP_vector (inferred_v_lexp, inferred_exp)) elem_typ else - typ_error l ("Vector assignment not provably in bounds " ^ string_of_lexp lexp) - | _ -> typ_error l "Cannot assign vector element of non vector type" + typ_error env l ("Vector assignment not provably in bounds " ^ string_of_lexp lexp) + | _ -> typ_error env l "Cannot assign vector element of non vector type" end - | LEXP_vector_concat [] -> typ_error l "Cannot have empty vector concatenation l-expression" + | LEXP_vector_concat [] -> typ_error env l "Cannot have empty vector concatenation l-expression" | LEXP_vector_concat (v_lexp :: v_lexps) -> begin let sum_lengths first_ord first_elem_typ acc (Typ_aux (v_typ_aux, _) as v_typ) = @@ -3131,7 +3133,7 @@ and infer_lexp env (LEXP_aux (lexp_aux, (l, ())) as lexp) = when Id.compare id (mk_id "vector") = 0 && ord_identical ord first_ord -> typ_equality l env elem_typ first_elem_typ; nsum acc len - | _ -> typ_error l "Vector concatentation l-expression must only contain vector types of the same order" + | _ -> typ_error env l "Vector concatentation l-expression must only contain vector types of the same order" in let inferred_v_lexp = infer_lexp env v_lexp in let inferred_v_lexps = List.map (infer_lexp env) v_lexps in @@ -3142,21 +3144,21 @@ and infer_lexp env (LEXP_aux (lexp_aux, (l, ())) as lexp) = when Id.compare id (mk_id "vector") = 0 -> let len = List.fold_left (sum_lengths ord elem_typ) len v_typs in annot_lexp (LEXP_vector_concat (inferred_v_lexp :: inferred_v_lexps)) (vector_typ (nexp_simp len) ord elem_typ) - | _ -> typ_error l ("Vector concatentation l-expression must only contain vector types, found " ^ string_of_typ v_typ) + | _ -> typ_error env l ("Vector concatentation l-expression must only contain vector types, found " ^ string_of_typ v_typ) end | LEXP_field (LEXP_aux (LEXP_id v, _), fid) -> (* FIXME: will only work for ASL *) let rec_id, weff = match Env.lookup_id v env with | Register (_, weff, Typ_aux (Typ_id rec_id, _)) -> rec_id, weff - | _ -> typ_error l (string_of_lexp lexp ^ " must be a record register here") + | _ -> typ_error env l (string_of_lexp lexp ^ " must be a record register here") in let typq, _, ret_typ, _ = Env.get_accessor rec_id fid env in annot_lexp_effect (LEXP_field (annot_lexp (LEXP_id v) (mk_id_typ rec_id), fid)) ret_typ weff | LEXP_tup lexps -> let inferred_lexps = List.map (infer_lexp env) lexps in annot_lexp (LEXP_tup inferred_lexps) (tuple_typ (List.map lexp_typ_of inferred_lexps)) - | _ -> typ_error l ("Could not infer the type of " ^ string_of_lexp lexp) + | _ -> typ_error env l ("Could not infer the type of " ^ string_of_lexp lexp) and infer_exp env (E_aux (exp_aux, (l, ())) as exp) = let annot_exp_effect exp typ eff = E_aux (exp, (l, mk_tannot env typ eff)) in @@ -3173,7 +3175,7 @@ and infer_exp env (E_aux (exp_aux, (l, ())) as exp) = match Env.lookup_id v env with | Local (_, typ) | Enum typ -> annot_exp (E_id v) typ | Register (reff, _, typ) -> annot_exp_effect (E_id v) typ reff - | Unbound -> typ_error l ("Identifier " ^ string_of_id v ^ " is unbound") + | Unbound -> typ_error env l ("Identifier " ^ string_of_id v ^ " is unbound") end | E_lit lit -> annot_exp (E_lit lit) (infer_lit env lit) | E_sizeof nexp -> @@ -3201,7 +3203,7 @@ and infer_exp env (E_aux (exp_aux, (l, ())) as exp) = | E_aux (E_app (field, [inferred_exp]) ,_) -> annot_exp (E_field (inferred_exp, field)) (typ_of inferred_acc) | _ -> assert false (* Unreachable *) end - | _ -> typ_error l ("Field expression " ^ string_of_exp exp ^ " :: " ^ string_of_typ (typ_of inferred_exp) ^ " is not valid") + | _ -> typ_error env l ("Field expression " ^ string_of_exp exp ^ " :: " ^ string_of_typ (typ_of inferred_exp) ^ " is not valid") end | E_tuple exps -> let inferred_exps = List.map (irule infer_exp env) exps in @@ -3214,11 +3216,11 @@ and infer_exp env (E_aux (exp_aux, (l, ())) as exp) = let rectyp_id = match Env.expand_synonyms env typ with | Typ_aux (Typ_id rectyp_id, _) | Typ_aux (Typ_app (rectyp_id, _), _) when Env.is_record rectyp_id env -> rectyp_id - | _ -> typ_error l ("The type " ^ string_of_typ typ ^ " is not a record") + | _ -> typ_error env l ("The type " ^ string_of_typ typ ^ " is not a record") in let check_fexp (FE_aux (FE_Fexp (field, exp), (l, ()))) = let (typq, rectyp_q, field_typ, _) = Env.get_accessor rectyp_id field env in - let unifiers = try unify l env (tyvars_of_typ rectyp_q) rectyp_q typ with Unification_error (l, m) -> typ_error l ("Unification error: " ^ m) in + let unifiers = try unify l env (tyvars_of_typ rectyp_q) rectyp_q typ with Unification_error (l, m) -> typ_error env l ("Unification error: " ^ m) in let field_typ' = subst_unifiers unifiers field_typ in let inferred_exp = crule check_exp env exp field_typ' in FE_aux (FE_Fexp (field, inferred_exp), (l, None)) @@ -3237,22 +3239,22 @@ and infer_exp env (E_aux (exp_aux, (l, ())) as exp) = let backwards_id = mk_id (string_of_id mapping ^ "_backwards") in typ_print (lazy ("Trying forwards direction for mapping " ^ string_of_id mapping ^ "(" ^ string_of_list ", " string_of_exp xs ^ ")")); begin try irule infer_exp env (E_aux (E_app (forwards_id, xs), (l, ()))) with - | Type_error (_, err1) -> + | Type_error (_, _, err1) -> (* typ_print (lazy ("Error in forwards direction: " ^ string_of_type_error err1)); *) typ_print (lazy ("Trying backwards direction for mapping " ^ string_of_id mapping ^ "(" ^ string_of_list ", " string_of_exp xs ^ ")")); begin try irule infer_exp env (E_aux (E_app (backwards_id, xs), (l, ()))) with - | Type_error (_, err2) -> + | Type_error (env, _, err2) -> (* typ_print (lazy ("Error in backwards direction: " ^ string_of_type_error err2)); *) - typ_raise l (Err_no_overloading (mapping, [(forwards_id, err1); (backwards_id, err2)])) + typ_raise env l (Err_no_overloading (mapping, [(forwards_id, err1); (backwards_id, err2)])) end end | E_app (f, xs) when List.length (Env.get_overloads f env) > 0 -> let rec try_overload = function - | (errs, []) -> typ_raise l (Err_no_overloading (f, errs)) + | (errs, []) -> typ_raise env l (Err_no_overloading (f, errs)) | (errs, (f :: fs)) -> begin typ_print (lazy ("Overload: " ^ string_of_id f ^ "(" ^ string_of_list ", " string_of_exp xs ^ ")")); try irule infer_exp env (E_aux (E_app (f, xs), (l, ()))) with - | Type_error (_, err) -> + | Type_error (_, _, err) -> typ_debug (lazy "Error"); try_overload (errs @ [(f, err)], fs) end @@ -3268,7 +3270,7 @@ and infer_exp env (E_aux (exp_aux, (l, ())) as exp) = let f, t, is_dec = match ord with | Ord_aux (Ord_inc, _) -> f, t, false | Ord_aux (Ord_dec, _) -> t, f, true (* reverse direction to typechecking downto as upto loop *) - | Ord_aux (Ord_var _, _) -> typ_error l "Cannot check a loop with variable direction!" (* This should never happen *) + | Ord_aux (Ord_var _, _) -> typ_error env l "Cannot check a loop with variable direction!" (* This should never happen *) in let inferred_f = irule infer_exp env f in let inferred_t = irule infer_exp env t in @@ -3284,7 +3286,7 @@ and infer_exp env (E_aux (exp_aux, (l, ())) as exp) = if not is_dec (* undo reverse direction in annotated ast for downto loop *) then annot_exp (E_for (v, inferred_f, inferred_t, checked_step, ord, checked_body)) unit_typ else annot_exp (E_for (v, inferred_t, inferred_f, checked_step, ord, checked_body)) unit_typ - | _, _ -> typ_error l "Ranges in foreach overlap" + | _, _ -> typ_error env l "Ranges in foreach overlap" end | E_if (cond, then_branch, else_branch) -> let cond' = crule check_exp env cond (mk_typ (Typ_id (mk_id "bool"))) in @@ -3299,7 +3301,7 @@ and infer_exp env (E_aux (exp_aux, (l, ())) as exp) = let else_sn = to_simple_numeric l kids nc else_nexp in let typ = typ_of_simple_numeric (union_simple_numeric then_sn else_sn) in annot_exp (E_if (cond', then_branch', else_branch')) typ - | None -> typ_error l ("Could not infer type of " ^ string_of_exp else_branch) + | None -> typ_error env l ("Could not infer type of " ^ string_of_exp else_branch) end | None -> begin match typ_of then_branch' with @@ -3317,7 +3319,7 @@ and infer_exp env (E_aux (exp_aux, (l, ())) as exp) = | E_vector_append (v1, E_aux (E_vector [], _)) -> infer_exp env v1 | E_vector_append (v1, v2) -> infer_exp env (E_aux (E_app (mk_id "append", [v1; v2]), (l, ()))) | E_vector_subrange (v, n, m) -> infer_exp env (E_aux (E_app (mk_id "vector_subrange", [v; n; m]), (l, ()))) - | E_vector [] -> typ_error l "Cannot infer type of empty vector" + | E_vector [] -> typ_error env l "Cannot infer type of empty vector" | E_vector ((item :: items) as vec) -> let inferred_item = irule infer_exp env item in let checked_items = List.map (fun i -> crule check_exp env i (typ_of inferred_item)) items in @@ -3369,7 +3371,7 @@ and infer_exp env (E_aux (exp_aux, (l, ())) as exp) = | E_ref id when Env.is_register id env -> let _, _, typ = Env.get_register id env in annot_exp (E_ref id) (register_typ typ) - | _ -> typ_error l ("Cannot infer type of: " ^ string_of_exp exp) + | _ -> typ_error env l ("Cannot infer type of: " ^ string_of_exp exp) and infer_funapp l env f xs ret_ctx_typ = infer_funapp' l env f (Env.get_val_spec f env) xs ret_ctx_typ @@ -3412,7 +3414,7 @@ and infer_funapp' l env f (typq, f_typ) xs expected_ret_typ = let quants, typ_args, typ_ret, eff = match Env.expand_synonyms env f_typ with | Typ_aux (Typ_fn (typ_args, typ_ret, eff), _) -> ref (quant_items typq), typ_args, ref typ_ret, eff - | _ -> typ_error l (string_of_typ f_typ ^ " is not a function type") + | _ -> typ_error env l (string_of_typ f_typ ^ " is not a function type") in let unifiers = instantiate_simple_equations !quants in @@ -3426,7 +3428,7 @@ and infer_funapp' l env f (typq, f_typ) xs expected_ret_typ = typ_debug (lazy ("Quantifiers " ^ Util.string_of_list ", " string_of_quant_item !quants)); if not (List.length typ_args = List.length xs) then - typ_error l (Printf.sprintf "Function %s applied to %d args, expected %d" (string_of_id f) (List.length xs) (List.length typ_args)) + typ_error env l (Printf.sprintf "Function %s applied to %d args, expected %d" (string_of_id f) (List.length xs) (List.length typ_args)) else (); let instantiate_quant (v, arg) (QI_aux (aux, l) as qi) = @@ -3464,7 +3466,7 @@ and infer_funapp' l env f (typq, f_typ) xs expected_ret_typ = let inferred_arg = irule infer_exp env arg in let inferred_arg, unifiers, env = try type_coercion_unify env goals inferred_arg typ with - | Unification_error (l, m) -> typ_error l m + | Unification_error (l, m) -> typ_error env l m in record_unifiers unifiers; let unifiers = KBindings.bindings unifiers in @@ -3488,7 +3490,7 @@ and infer_funapp' l env f (typq, f_typ) xs expected_ret_typ = let xs = List.rev xs in if not (List.for_all (solve_quant env) !quants) then - typ_raise l (Err_unresolved_quants (f, !quants, Env.get_locals env, Env.get_constraints env)) + typ_raise env l (Err_unresolved_quants (f, !quants, Env.get_locals env, Env.get_constraints env)) else (); let ty_vars = KBindings.bindings (Env.get_typ_vars env) |> List.map (fun (v, k) -> mk_kopt k v) in @@ -3516,7 +3518,7 @@ and bind_mpat allow_unknown other_env env (MP_aux (mpat_aux, (l, ())) as mpat) ( let annot_mpat mpat typ' = MP_aux (mpat, (l, mk_expected_tannot env typ' no_effect (Some typ))) in let switch_typ mpat typ = match mpat with | MP_aux (pat_aux, (l, Some tannot)) -> MP_aux (pat_aux, (l, Some { tannot with typ = typ })) - | _ -> typ_error l "Cannot switch type for unannotated mapping-pattern" + | _ -> typ_error env l "Cannot switch type for unannotated mapping-pattern" in let bind_tuple_mpat (tpats, env, guards) mpat typ = let tpat, env, guards' = bind_mpat allow_unknown other_env env mpat typ in tpat :: tpats, env, guards' @ guards @@ -3534,7 +3536,7 @@ and bind_mpat allow_unknown other_env env (MP_aux (mpat_aux, (l, ())) as mpat) ( match Env.lookup_id v env with | Local (Immutable, _) | Unbound -> annot_mpat (MP_id v) typ, Env.add_local v (Immutable, typ) env, [] | Local (Mutable, _) | Register _ -> - typ_error l ("Cannot shadow mutable local or register in switch statement mapping-pattern " ^ string_of_mpat mpat) + typ_error env l ("Cannot shadow mutable local or register in switch statement mapping-pattern " ^ string_of_mpat mpat) | Enum enum -> subtyp l env enum typ; annot_mpat (MP_id v) typ, env, [] end | MP_cons (hd_mpat, tl_mpat) -> @@ -3544,7 +3546,7 @@ and bind_mpat allow_unknown other_env env (MP_aux (mpat_aux, (l, ())) as mpat) ( let hd_mpat, env, hd_guards = bind_mpat allow_unknown other_env env hd_mpat ltyp in let tl_mpat, env, tl_guards = bind_mpat allow_unknown other_env env tl_mpat typ in annot_mpat (MP_cons (hd_mpat, tl_mpat)) typ, env, hd_guards @ tl_guards - | _ -> typ_error l "Cannot match cons mapping-pattern against non-list type" + | _ -> typ_error env l "Cannot match cons mapping-pattern against non-list type" end | MP_string_append mpats -> begin @@ -3559,7 +3561,7 @@ and bind_mpat allow_unknown other_env env (MP_aux (mpat_aux, (l, ())) as mpat) ( in let pats, env, guards = process_mpats env mpats in annot_mpat (MP_string_append pats) typ, env, guards - | _ -> typ_error l "Cannot match string-append pattern against non-string type" + | _ -> typ_error env l "Cannot match string-append pattern against non-string type" end | MP_list mpats -> begin @@ -3574,14 +3576,14 @@ and bind_mpat allow_unknown other_env env (MP_aux (mpat_aux, (l, ())) as mpat) ( in let mpats, env, guards = process_mpats env mpats in annot_mpat (MP_list mpats) typ, env, guards - | _ -> typ_error l ("Cannot match list mapping-pattern " ^ string_of_mpat mpat ^ " against non-list type " ^ string_of_typ typ) + | _ -> typ_error env l ("Cannot match list mapping-pattern " ^ string_of_mpat mpat ^ " against non-list type " ^ string_of_typ typ) end | MP_tup [] -> begin match Env.expand_synonyms env typ with | Typ_aux (Typ_id typ_id, _) when string_of_id typ_id = "unit" -> annot_mpat (MP_tup []) typ, env, [] - | _ -> typ_error l "Cannot match unit mapping-pattern against non-unit type" + | _ -> typ_error env l "Cannot match unit mapping-pattern against non-unit type" end | MP_tup mpats -> begin @@ -3589,10 +3591,10 @@ and bind_mpat allow_unknown other_env env (MP_aux (mpat_aux, (l, ())) as mpat) ( | Typ_aux (Typ_tup typs, _) -> let tpats, env, guards = try List.fold_left2 bind_tuple_mpat ([], env, []) mpats typs with - | Invalid_argument _ -> typ_error l "Tuple mapping-pattern and tuple type have different length" + | Invalid_argument _ -> typ_error env l "Tuple mapping-pattern and tuple type have different length" in annot_mpat (MP_tup (List.rev tpats)) typ, env, guards - | _ -> typ_error l "Cannot bind tuple mapping-pattern against non tuple type" + | _ -> typ_error env l "Cannot bind tuple mapping-pattern against non tuple type" end | MP_app (f, mpats) when Env.is_union_constructor f env -> begin @@ -3611,18 +3613,18 @@ and bind_mpat allow_unknown other_env env (MP_aux (mpat_aux, (l, ())) as mpat) ( let arg_typ' = subst_unifiers unifiers arg_typ in let quants' = List.fold_left instantiate_quants quants (KBindings.bindings unifiers) in if (match quants' with [] -> false | _ -> true) - then typ_error l ("Quantifiers " ^ string_of_list ", " string_of_quant_item quants' ^ " not resolved in mapping-pattern " ^ string_of_mpat mpat) + then typ_error env l ("Quantifiers " ^ string_of_list ", " string_of_quant_item quants' ^ " not resolved in mapping-pattern " ^ string_of_mpat mpat) else (); let ret_typ' = subst_unifiers unifiers ret_typ in let tpats, env, guards = try List.fold_left2 bind_tuple_mpat ([], env, []) mpats (untuple arg_typ') with - | Invalid_argument _ -> typ_error l "Union constructor mapping-pattern arguments have incorrect length" + | Invalid_argument _ -> typ_error env l "Union constructor mapping-pattern arguments have incorrect length" in annot_mpat (MP_app (f, List.rev tpats)) typ, env, guards with - | Unification_error (l, m) -> typ_error l ("Unification error when mapping-pattern matching against union constructor: " ^ m) + | Unification_error (l, m) -> typ_error env l ("Unification error when mapping-pattern matching against union constructor: " ^ m) end - | _ -> typ_error l ("Mal-formed constructor " ^ string_of_id f ^ " with type " ^ string_of_typ ctor_typ) + | _ -> typ_error env l ("Mal-formed constructor " ^ string_of_id f ^ " with type " ^ string_of_typ ctor_typ) end | MP_app (other, mpats) when Env.is_mapping other env -> begin @@ -3641,12 +3643,12 @@ and bind_mpat allow_unknown other_env env (MP_aux (mpat_aux, (l, ())) as mpat) ( let arg_typ' = subst_unifiers unifiers typ1 in let quants' = List.fold_left instantiate_quants quants (KBindings.bindings unifiers) in if (match quants' with [] -> false | _ -> true) - then typ_error l ("Quantifiers " ^ string_of_list ", " string_of_quant_item quants' ^ " not resolved in mapping-pattern " ^ string_of_mpat mpat) + then typ_error env l ("Quantifiers " ^ string_of_list ", " string_of_quant_item quants' ^ " not resolved in mapping-pattern " ^ string_of_mpat mpat) else (); let ret_typ' = subst_unifiers unifiers typ2 in let tpats, env, guards = try List.fold_left2 bind_tuple_mpat ([], env, []) mpats (untuple arg_typ') with - | Invalid_argument _ -> typ_error l "Mapping pattern arguments have incorrect length" + | Invalid_argument _ -> typ_error env l "Mapping pattern arguments have incorrect length" in annot_mpat (MP_app (other, List.rev tpats)) typ, env, guards with @@ -3658,22 +3660,22 @@ and bind_mpat allow_unknown other_env env (MP_aux (mpat_aux, (l, ())) as mpat) ( let arg_typ' = subst_unifiers unifiers typ2 in let quants' = List.fold_left instantiate_quants quants (KBindings.bindings unifiers) in if (match quants' with [] -> false | _ -> true) - then typ_error l ("Quantifiers " ^ string_of_list ", " string_of_quant_item quants' ^ " not resolved in mapping-pattern " ^ string_of_mpat mpat) + then typ_error env l ("Quantifiers " ^ string_of_list ", " string_of_quant_item quants' ^ " not resolved in mapping-pattern " ^ string_of_mpat mpat) else (); let ret_typ' = subst_unifiers unifiers typ1 in let tpats, env, guards = try List.fold_left2 bind_tuple_mpat ([], env, []) mpats (untuple arg_typ') with - | Invalid_argument _ -> typ_error l "Mapping pattern arguments have incorrect length" + | Invalid_argument _ -> typ_error env l "Mapping pattern arguments have incorrect length" in annot_mpat (MP_app (other, List.rev tpats)) typ, env, guards with - | Unification_error (l, m) -> typ_error l ("Unification error when pattern matching against mapping constructor: " ^ m) + | Unification_error (l, m) -> typ_error env l ("Unification error when pattern matching against mapping constructor: " ^ m) end | Typ_aux (typ, _) -> - typ_error l ("unifying mapping type, expanded synonyms to non-mapping type??") + typ_error env l ("unifying mapping type, expanded synonyms to non-mapping type??") end | MP_app (f, _) when not (Env.is_union_constructor f env || Env.is_mapping f env) -> - typ_error l (string_of_id f ^ " is not a union constructor or mapping in mapping-pattern " ^ string_of_mpat mpat) + typ_error env l (string_of_id f ^ " is not a union constructor or mapping in mapping-pattern " ^ string_of_mpat mpat) | MP_as (mpat, id) -> let (typed_mpat, env, guards) = bind_mpat allow_unknown other_env env mpat typ in (annot_mpat (MP_as (typed_mpat, id)) (typ_of_mpat typed_mpat), @@ -3713,11 +3715,11 @@ and infer_mpat allow_unknown other_env env (MP_aux (mpat_aux, (l, ())) as mpat) | Local (Immutable, typ) -> bind_mpat allow_unknown other_env env (mk_mpat (MP_typ (mk_mpat (MP_id v), typ))) typ | Unbound -> if allow_unknown then annot_mpat (MP_id v) unknown_typ, env, [] else - typ_error l ("Cannot infer identifier in mapping-pattern " ^ string_of_mpat mpat ^ " - try adding a type annotation") + typ_error env l ("Cannot infer identifier in mapping-pattern " ^ string_of_mpat mpat ^ " - try adding a type annotation") | _ -> assert false end | Local (Mutable, _) | Register _ -> - typ_error l ("Cannot shadow mutable local or register in mapping-pattern " ^ string_of_mpat mpat) + typ_error env l ("Cannot shadow mutable local or register in mapping-pattern " ^ string_of_mpat mpat) | Enum enum -> annot_mpat (MP_id v) enum, env, [] end | MP_app (f, mpats) when Env.is_union_constructor f env -> @@ -3726,7 +3728,7 @@ and infer_mpat allow_unknown other_env env (MP_aux (mpat_aux, (l, ())) as mpat) match Env.expand_synonyms env ctor_typ with | Typ_aux (Typ_fn (arg_typ, ret_typ, _), _) -> bind_mpat allow_unknown other_env env mpat ret_typ - | _ -> typ_error l ("Mal-formed constructor " ^ string_of_id f) + | _ -> typ_error env l ("Mal-formed constructor " ^ string_of_id f) end | MP_app (f, mpats) when Env.is_mapping f env -> begin @@ -3740,7 +3742,7 @@ and infer_mpat allow_unknown other_env env (MP_aux (mpat_aux, (l, ())) as mpat) | Type_error _ -> bind_mpat allow_unknown other_env env mpat typ1 end - | _ -> typ_error l ("Malformed mapping type " ^ string_of_id f) + | _ -> typ_error env l ("Malformed mapping type " ^ string_of_id f) end | MP_lit lit -> annot_mpat (MP_lit lit) (infer_lit env lit), env, [] @@ -3793,7 +3795,7 @@ and infer_mpat allow_unknown other_env env (MP_aux (mpat_aux, (l, ())) as mpat) guards) | _ -> - typ_error l ("Couldn't infer type of mapping-pattern " ^ string_of_mpat mpat) + typ_error env l ("Couldn't infer type of mapping-pattern " ^ string_of_mpat mpat) (**************************************************************************) (* 5. Effect system *) @@ -3967,8 +3969,8 @@ and propagate_exp_effect_aux = function | E_internal_return exp -> let p_exp = propagate_exp_effect exp in E_internal_return p_exp, effect_of p_exp - | exp_aux -> typ_error Parse_ast.Unknown ("Unimplemented: Cannot propagate effect in expression " - ^ string_of_exp (E_aux (exp_aux, (Parse_ast.Unknown, None)))) + | exp_aux -> typ_error Env.empty Parse_ast.Unknown ("Unimplemented: Cannot propagate effect in expression " + ^ string_of_exp (E_aux (exp_aux, (Parse_ast.Unknown, None)))) and propagate_fexp_effect (FE_aux (FE_Fexp (id, exp), (l, _))) = let p_exp = propagate_exp_effect exp in @@ -4070,7 +4072,7 @@ and propagate_pat_effect_aux = function | P_vector pats -> let p_pats = List.map propagate_pat_effect pats in P_vector p_pats, collect_effects_pat p_pats - | _ -> typ_error Parse_ast.Unknown "Unimplemented: Cannot propagate effect in pat" + | _ -> raise (Reporting.err_unreachable Parse_ast.Unknown __POS__ "Unimplemented: Cannot propagate effect in pat") and propagate_mpat_effect (MP_aux (mpat, annot)) = let p_mpat, eff = propagate_mpat_effect_aux mpat in @@ -4106,7 +4108,7 @@ and propagate_mpat_effect_aux = function | MP_as (mpat, id) -> let p_mpat = propagate_mpat_effect mpat in MP_as (p_mpat, id), effect_of_mpat mpat - | _ -> typ_error Parse_ast.Unknown "Unimplemented: Cannot propagate effect in mpat" + | _ -> raise (Reporting.err_unreachable Parse_ast.Unknown __POS__ "Unimplemented: Cannot propagate effect in mpat") and propagate_letbind_effect (LB_aux (lb, (l, annot))) = let p_lb, eff = propagate_letbind_effect_aux lb in @@ -4166,14 +4168,14 @@ let check_letdef orig_env (LB_aux (letbind, (l, _))) = if (BESet.is_empty (effect_set (effect_of checked_bind)) || !opt_no_effects) then [DEF_val (LB_aux (LB_val (tpat, checked_bind), (l, None)))], env - else typ_error l ("Top-level definition with effects " ^ string_of_effect (effect_of checked_bind)) + else typ_error env l ("Top-level definition with effects " ^ string_of_effect (effect_of checked_bind)) | LB_val (pat, bind) -> let inferred_bind = propagate_exp_effect (irule infer_exp orig_env (strip_exp bind)) in let tpat, env = bind_pat_no_guard orig_env (strip_pat pat) (typ_of inferred_bind) in if (BESet.is_empty (effect_set (effect_of inferred_bind)) || !opt_no_effects) then [DEF_val (LB_aux (LB_val (tpat, inferred_bind), (l, None)))], env - else typ_error l ("Top-level definition with effects " ^ string_of_effect (effect_of inferred_bind)) + else typ_error env l ("Top-level definition with effects " ^ string_of_effect (effect_of inferred_bind)) end let check_funcl env (FCL_aux (FCL_Funcl (id, pexp), (l, _))) typ = @@ -4204,7 +4206,7 @@ let check_funcl env (FCL_aux (FCL_Funcl (id, pexp), (l, _))) typ = in FCL_aux (FCL_Funcl (id, typed_pexp), (l, mk_expected_tannot env typ prop_eff (Some typ))) end - | _ -> typ_error l ("Function clause must have function type: " ^ string_of_typ typ ^ " is not a function type") + | _ -> typ_error env l ("Function clause must have function type: " ^ string_of_typ typ ^ " is not a function type") let check_mapcl : 'a. Env.t -> 'a mapcl -> typ -> tannot mapcl = @@ -4240,7 +4242,7 @@ let check_mapcl : 'a. Env.t -> 'a mapcl -> typ -> tannot mapcl = MCL_aux (MCL_backwards (typed_mpexp, typed_exp), (l, mk_expected_tannot env typ prop_effs (Some typ))) end end - | _ -> typ_error l ("Mapping clause must have mapping type: " ^ string_of_typ typ ^ " is not a mapping type") + | _ -> typ_error env l ("Mapping clause must have mapping type: " ^ string_of_typ typ ^ " is not a mapping type") let funcl_effect (FCL_aux (FCL_Funcl (id, typed_pexp), (l, annot))) = match annot with @@ -4261,7 +4263,7 @@ let infer_funtyp l env tannotopt funcls = | P_lit lit -> infer_lit env lit | P_typ (typ, _) -> typ | P_tup pats -> mk_typ (Typ_tup (List.map typ_from_pat pats)) - | _ -> typ_error l ("Cannot infer type from pattern " ^ string_of_pat pat) + | _ -> typ_error env l ("Cannot infer type from pattern " ^ string_of_pat pat) in match funcls with | [FCL_aux (FCL_Funcl (_, Pat_aux (pexp,_)), _)] -> @@ -4276,9 +4278,9 @@ let infer_funtyp l env tannotopt funcls = in let fn_typ = mk_typ (Typ_fn (arg_typs, ret_typ, Effect_aux (Effect_set [], Parse_ast.Unknown))) in (quant, fn_typ) - | _ -> typ_error l "Cannot infer function type for function with multiple clauses" + | _ -> typ_error env l "Cannot infer function type for function with multiple clauses" end - | Typ_annot_opt_aux (Typ_annot_opt_none, _) -> typ_error l "Cannot infer function type for unannotated function" + | Typ_annot_opt_aux (Typ_annot_opt_none, _) -> typ_error env l "Cannot infer function type for unannotated function" let mk_val_spec env typq typ id = let eff = @@ -4293,7 +4295,7 @@ let check_tannotopt env typq ret_typ = function | Typ_annot_opt_aux (Typ_annot_opt_some (annot_typq, annot_ret_typ), l) -> if typ_identical env ret_typ annot_ret_typ then () - else typ_error l (string_of_bind (typq, ret_typ) ^ " and " ^ string_of_bind (annot_typq, annot_ret_typ) ^ " do not match between function and val spec") + else typ_error env l (string_of_bind (typq, ret_typ) ^ " and " ^ string_of_bind (annot_typq, annot_ret_typ) ^ " do not match between function and val spec") let check_fundef env (FD_aux (FD_function (recopt, tannotopt, effectopt, funcls), (l, _)) as fd_aux) = let id = @@ -4301,23 +4303,23 @@ let check_fundef env (FD_aux (FD_function (recopt, tannotopt, effectopt, funcls) (fun (FCL_aux (FCL_Funcl (id, _), _)) id' -> match id' with | Some id' -> if string_of_id id' = string_of_id id then Some id' - else typ_error l ("Function declaration expects all definitions to have the same name, " + else typ_error env l ("Function declaration expects all definitions to have the same name, " ^ string_of_id id ^ " differs from other definitions of " ^ string_of_id id') | None -> Some id) funcls None) with | Some id -> id - | None -> typ_error l "funcl list is empty" + | None -> typ_error env l "funcl list is empty" in typ_print (lazy ("\n" ^ Util.("Check function " |> cyan |> clear) ^ string_of_id id)); let have_val_spec, (quant, typ), env = try true, Env.get_val_spec id env, env with - | Type_error (l, _) -> + | Type_error (_, l, _) -> let (quant, typ) = infer_funtyp l env tannotopt funcls in false, (quant, typ), env in let vtyp_args, vtyp_ret, declared_eff, vl = match typ with | Typ_aux (Typ_fn (vtyp_args, vtyp_ret, declared_eff), vl) -> vtyp_args, vtyp_ret, declared_eff, vl - | _ -> typ_error l "Function val spec is not a function type" + | _ -> typ_error env l "Function val spec is not a function type" in check_tannotopt env quant vtyp_ret tannotopt; typ_debug (lazy ("Checking fundef " ^ string_of_id id ^ " has type " ^ string_of_bind (quant, typ))); @@ -4345,14 +4347,14 @@ let check_fundef env (FD_aux (FD_function (recopt, tannotopt, effectopt, funcls) if (equal_effects eff declared_eff || !opt_no_effects) then vs_def @ [DEF_fundef (FD_aux (FD_function (recopt, tannotopt, effectopt, funcls), (l, None)))], env - else typ_error l ("Effects do not match: " ^ string_of_effect declared_eff ^ " declared and " ^ string_of_effect eff ^ " found") + else typ_error env l ("Effects do not match: " ^ string_of_effect declared_eff ^ " declared and " ^ string_of_effect eff ^ " found") let check_mapdef env (MD_aux (MD_mapping (id, tannot_opt, mapcls), (l, _)) as md_aux) = typ_print (lazy ("\nChecking mapping " ^ string_of_id id)); let have_val_spec, (quant, typ), env = try true, Env.get_val_spec id env, env with - | Type_error (l, _) as err -> + | Type_error (_, l, _) as err -> match tannot_opt with | Typ_annot_opt_aux (Typ_annot_opt_some (quant, typ), _) -> false, (quant, typ), env @@ -4361,13 +4363,13 @@ let check_mapdef env (MD_aux (MD_mapping (id, tannot_opt, mapcls), (l, _)) as md in let vtyp1, vtyp2, vl = match typ with | Typ_aux (Typ_bidir (vtyp1, vtyp2), vl) -> vtyp1, vtyp2, vl - | _ -> typ_error l "Mapping val spec was not a mapping type" + | _ -> typ_error env l "Mapping val spec was not a mapping type" in begin match tannot_opt with | Typ_annot_opt_aux (Typ_annot_opt_none, _) -> () | Typ_annot_opt_aux (Typ_annot_opt_some (annot_typq, annot_typ), l) -> if typ_identical env typ annot_typ then () - else typ_error l (string_of_bind (quant, typ) ^ " and " ^ string_of_bind (annot_typq, annot_typ) ^ " do not match between mapping and val spec") + else typ_error env l (string_of_bind (quant, typ) ^ " and " ^ string_of_bind (annot_typq, annot_typ) ^ " do not match between mapping and val spec") end; typ_debug (lazy ("Checking mapdef " ^ string_of_id id ^ " has type " ^ string_of_bind (quant, typ))); let vs_def, env = @@ -4383,7 +4385,7 @@ let check_mapdef env (MD_aux (MD_mapping (id, tannot_opt, mapcls), (l, _)) as md if equal_effects eff no_effect || equal_effects eff (mk_effect [BE_escape]) || !opt_no_effects then vs_def @ [DEF_mapdef (MD_aux (MD_mapping (id, tannot_opt, mapcls), (l, None)))], env else - typ_error l ("Mapping not pure (or escape only): " ^ string_of_effect eff ^ " found") + typ_error env l ("Mapping not pure (or escape only): " ^ string_of_effect eff ^ " found") (* Checking a val spec simply adds the type as a binding in the context. We have to destructure the various kinds of val specs, but @@ -4415,7 +4417,7 @@ let check_default env (DT_aux (ds, l)) = match ds with | DT_order (Ord_aux (Ord_inc, _)) -> [DEF_default (DT_aux (ds, l))], Env.set_default_order_inc env | DT_order (Ord_aux (Ord_dec, _)) -> [DEF_default (DT_aux (ds, l))], Env.set_default_order_dec env - | DT_order (Ord_aux (Ord_var _, _)) -> typ_error l "Cannot have variable default order" + | DT_order (Ord_aux (Ord_var _, _)) -> typ_error env l "Cannot have variable default order" let kinded_id_arg kind_id = let typ_arg arg = A_aux (arg, Parse_ast.Unknown) in @@ -4471,14 +4473,14 @@ let mk_synonym typq typ_arg = let typ_arg, ncs = subst_args kopts args in typ_arg_subst (kopt_kid kopt) (arg_bool arg) typ_arg, ncs | [], [] -> typ_arg, ncs - | _, A_aux (_, l) :: _ -> typ_error l "Synonym applied to bad arguments" - | _, _ -> typ_error Parse_ast.Unknown "Synonym applied to bad arguments" + | _, A_aux (_, l) :: _ -> typ_error Env.empty l "Synonym applied to bad arguments" + | _, _ -> typ_error Env.empty Parse_ast.Unknown "Synonym applied to bad arguments" in fun env args -> let typ_arg, ncs = subst_args kopts args in if List.for_all (prove __POS__ env) ncs then typ_arg - else typ_error Parse_ast.Unknown ("Could not prove constraints " ^ string_of_list ", " string_of_n_constraint ncs + else typ_error env Parse_ast.Unknown ("Could not prove constraints " ^ string_of_list ", " string_of_n_constraint ncs ^ " in type synonym " ^ string_of_typ_arg typ_arg ^ " with " ^ string_of_list ", " string_of_n_constraint (Env.get_constraints env)) @@ -4520,7 +4522,7 @@ let rec check_typedef : 'a. Env.t -> 'a type_def -> (tannot def) list * Env.t = let (Defs defs), env = check env (Bitfield.macro id size order ranges) in defs, env | _ -> - typ_error l "Bad bitfield type" + typ_error env l "Bad bitfield type" end and check_scattered : 'a. Env.t -> 'a scattered_def -> (tannot def) list * Env.t = diff --git a/src/type_check.mli b/src/type_check.mli index d1061826..e3a22c8d 100644 --- a/src/type_check.mli +++ b/src/type_check.mli @@ -80,9 +80,11 @@ type type_error = | Err_subtype of typ * typ * n_constraint list * Ast.l KBindings.t | Err_no_num_ident of id | Err_other of string - | Err_because of type_error * type_error + | Err_because of type_error * Ast.l * type_error -exception Type_error of l * type_error;; +type env + +exception Type_error of env * l * type_error;; val typ_debug : ?level:int -> string Lazy.t -> unit val typ_print : string Lazy.t -> unit @@ -93,7 +95,7 @@ val typ_print : string Lazy.t -> unit contains functions that operate on that state. *) module Env : sig (** Env.t is the type of environments *) - type t + type t = env (** Note: Most get_ functions assume the identifiers exist, and throw type errors if they don't. *) @@ -316,7 +318,7 @@ val bind_pat : Env.t -> unit pat -> typ -> tannot pat * Env.t * unit Ast.exp lis on patterns that have previously been type checked. *) val bind_pat_no_guard : Env.t -> unit pat -> typ -> tannot pat * Env.t -val typ_error : Ast.l -> string -> 'a +val typ_error : Env.t -> Ast.l -> string -> 'a (** {2 Destructuring type annotations} Partial functions: The expressions and patterns passed to these functions must be diff --git a/src/type_error.ml b/src/type_error.ml index f28e4de8..6f856480 100644 --- a/src/type_error.ml +++ b/src/type_error.ml @@ -48,31 +48,16 @@ (* SUCH DAMAGE. *) (**************************************************************************) -open PPrint open Util open Ast open Ast_util open Type_check -let bullet f xs = - group (separate_map hardline (fun x -> string "* " ^^ nest 2 (f x)) xs) - -let pp_nexp, pp_n_constraint = - let pp_nexp' nexp = - string (string_of_nexp nexp) - in - - let pp_n_constraint' nc = - string (string_of_n_constraint nc) - in - pp_nexp', pp_n_constraint' - type suggestion = | Suggest_add_constraint of n_constraint | Suggest_none -(* Temporary hack while I work on using these suggestions in asl_parser *) -let rec analyze_unresolved_quant2 locals ncs = function +let rec analyze_unresolved_quant locals ncs = function | QI_aux (QI_const nc, _) -> let gen_kids = List.filter is_kid_generated (KidSet.elements (tyvars_of_constraint nc)) in if gen_kids = [] then @@ -117,104 +102,53 @@ let rec analyze_unresolved_quant2 locals ncs = function | QI_aux (QI_id kopt, _) -> Suggest_none -let rec analyze_unresolved_quant locals ncs = function - | QI_aux (QI_const nc, _) -> - let gen_kids = List.filter is_kid_generated (KidSet.elements (tyvars_of_constraint nc)) in - if gen_kids = [] then - string ("Try adding the constraint: " ^ string_of_n_constraint nc) - else - (* If there are generated kind-identifiers in the constraint, - we don't want to make a suggestion based on them, so try to - look for generated kid free nexps in the set of constraints - that are equal to the generated identifier. This often - occurs due to how the type-checker introduces new type - variables. *) - let is_subst v = function - | NC_aux (NC_equal (Nexp_aux (Nexp_var v', _), nexp), _) - when Kid.compare v v' = 0 && not (KidSet.exists is_kid_generated (tyvars_of_nexp nexp)) -> - [(v, nexp)] - | NC_aux (NC_equal (nexp, Nexp_aux (Nexp_var v', _)), _) - when Kid.compare v v' = 0 && not (KidSet.exists is_kid_generated (tyvars_of_nexp nexp)) -> - [(v, nexp)] - | _ -> [] - in - let substs = List.concat (List.map (fun v -> List.concat (List.map (fun nc -> is_subst v nc) ncs)) gen_kids) in - let nc = List.fold_left (fun nc (v, nexp) -> constraint_subst v (arg_nexp nexp) nc) nc substs in - if not (KidSet.exists is_kid_generated (tyvars_of_constraint nc)) then - string ("Try adding the constraint " ^ string_of_n_constraint nc) - else - (* If we have a really anonymous type-variable, try to find a - regular variable that corresponds to it. *) - let is_linked v = function - | (id, (Immutable, (Typ_aux (Typ_app (ty_id, [A_aux (A_nexp (Nexp_aux (Nexp_var v', _)), _)]), _) as typ))) - when Id.compare ty_id (mk_id "atom") = 0 && Kid.compare v v' = 0 -> - [(v, nid id, typ)] - | (id, (mut, typ)) -> - [] - in - let substs = List.concat (List.map (fun v -> List.concat (List.map (fun nc -> is_linked v nc) (Bindings.bindings locals))) gen_kids) in - (string "Try adding named type variables for" - ^//^ string (Util.string_of_list ", " (fun (_, nexp, typ) -> string_of_nexp nexp ^ " : " ^ string_of_typ typ) substs)) - ^^ twice hardline ^^ - let nc = List.fold_left (fun nc (v, nexp, _) -> constraint_subst v (arg_nexp nexp) nc) nc substs in - if not (KidSet.exists is_kid_generated (tyvars_of_constraint nc)) then - string ("The property " ^ string_of_n_constraint nc ^ " must hold") - else - empty +let message_of_type_error = + let open Error_format in + let rec msg = function + | Err_because (err, l', err') -> + Seq [msg err; + Line "This error occured because of a previous error:"; + Location (l', msg err')] - | QI_aux (QI_id kopt, _) -> - empty + | Err_other str -> Line str -let rec pp_type_error = function - | Err_no_casts (exp, typ_from, typ_to, trigger, reasons) -> - let coercion = - group (string "Tried performing type coercion from" ^/^ Pretty_print_sail.doc_typ typ_from - ^/^ string "to" ^/^ Pretty_print_sail.doc_typ typ_to - ^/^ string "on" ^/^ Pretty_print_sail.doc_exp exp) - in - coercion ^^ hardline - ^^ (string "Coercion failed because:" ^//^ pp_type_error trigger) - ^^ if not (reasons = []) then - hardline - ^^ (string "Possible reasons:" ^//^ separate_map hardline pp_type_error reasons) - else - empty + | Err_no_overloading (id, errs) -> + Seq [Line ("No overloading for " ^ string_of_id id ^ ", tried:"); + List (List.map (fun (id, err) -> string_of_id id, msg err) errs)] - | Err_no_overloading (id, errs) -> - string ("No overloadings for " ^ string_of_id id ^ ", tried:") ^//^ - group (separate_map hardline (fun (id, err) -> string (string_of_id id) ^^ colon ^//^ pp_type_error err) errs) + | Err_unresolved_quants (id, quants, locals, ncs) -> + Seq [Line ("Could not resolve quantifiers for " ^ string_of_id id); + Line (bullet ^ " " ^ Util.string_of_list ("\n" ^ bullet ^ " ") string_of_quant_item quants)] - | Err_subtype (typ1, typ2, constrs, locs) -> - (separate space [ string (string_of_typ typ1); - string "is not a subtype of"; - string (string_of_typ typ2) ]) - ^/^ string "in context" - ^/^ bullet pp_n_constraint constrs - ^/^ string "where" - ^/^ bullet (fun (kid, l) -> string (string_of_kid kid ^ " bound at " ^ Reporting.loc_to_string l ^ "\n")) (KBindings.bindings locs) + | Err_subtype (typ1, typ2, _, vars) -> + let vars = KBindings.bindings vars in + let vars = List.filter (fun (v, _) -> KidSet.mem v (KidSet.union (tyvars_of_typ typ1) (tyvars_of_typ typ2))) vars in + With ((fun ppf -> { ppf with loc_color = Util.yellow }), + Seq (Line (string_of_typ typ1 ^ " is not a subtype of " ^ string_of_typ typ2) + :: List.map (fun (kid, l) -> Location (l, Line (string_of_kid kid ^ " bound here"))) vars)) | Err_no_num_ident id -> - string "No num identifier" ^^ space ^^ string (string_of_id id) + Line ("No num identifier " ^ string_of_id id) - | Err_unresolved_quants (id, quants, locals, ncs) -> - (string "Could not resolve quantifiers for" ^^ space ^^ string (string_of_id id) - ^//^ group (separate_map hardline (fun quant -> string (string_of_quant_item quant)) quants)) - ^^ twice hardline - ^^ group (separate_map hardline (analyze_unresolved_quant locals ncs) quants) - - (* We only got err, because of previous error, err' *) - | Err_because (err, err') -> - pp_type_error err - ^^ hardline ^^ string "This error occured because of a previous error:" - ^//^ pp_type_error err' - - | Err_other str -> string str + | Err_no_casts (exp, typ_from, typ_to, trigger, reasons) -> + let coercion = + Line ("Tried performing type coercion from " ^ string_of_typ typ_from + ^ " to " ^ string_of_typ typ_to + ^ " on " ^ string_of_exp exp) + in + Seq ([coercion; Line "Coercion failed because:"; msg trigger] + @ if not (reasons = []) then + Line "Possible reasons:" :: List.map msg reasons + else + []) + in + msg let rec string_of_type_error err = - let open PPrint in + let open Error_format in let b = Buffer.create 20 in - ToBuffer.pretty 1. 400 b (pp_type_error err); - "\n" ^ Buffer.contents b + format_message (message_of_type_error err) (buffer_formatter b); + Buffer.contents b let rec collapse_errors = function | (Err_no_overloading (_, (err :: errs)) as no_collapse) -> @@ -232,16 +166,18 @@ let rec collapse_errors = function | Some _ -> err | None -> no_collapse end - | Err_because (err1, err2) as no_collapse -> + | Err_because (err1, l, err2) as no_collapse -> let err1 = collapse_errors err1 in let err2 = collapse_errors err2 in if string_of_type_error err1 = string_of_type_error err2 then err1 else - Err_because (err1, err2) + Err_because (err1, l, err2) | err -> err let check : 'a. Env.t -> 'a defs -> tannot defs * Env.t = fun env defs -> try Type_check.check env defs with - | Type_error (l, err) -> raise (Reporting.err_typ l (string_of_type_error err)) + | Type_error (env, l, err) -> + Interactive.env := env; + raise (Reporting.err_typ l (string_of_type_error err)) |
