summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/c_backend.ml2
-rw-r--r--src/constant_fold.ml2
-rw-r--r--src/error_format.ml95
-rw-r--r--src/interactive.ml7
-rw-r--r--src/interactive.mli9
-rw-r--r--src/interpreter.ml2
-rw-r--r--src/isail.ml74
-rw-r--r--src/pretty_print_coq.ml2
-rw-r--r--src/process_file.ml2
-rw-r--r--src/reporting.ml24
-rw-r--r--src/reporting.mli8
-rw-r--r--src/rewrites.ml18
-rw-r--r--src/sail.ml20
-rw-r--r--src/type_check.ml486
-rw-r--r--src/type_check.mli10
-rw-r--r--src/type_error.ml150
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))