diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/type_check.ml | 162 |
1 files changed, 83 insertions, 79 deletions
diff --git a/src/type_check.ml b/src/type_check.ml index 71ed80fa..52db43da 100644 --- a/src/type_check.ml +++ b/src/type_check.ml @@ -51,6 +51,7 @@ open Ast open Util open Ast_util +open Lazy module Big_int = Nat_big_num (* opt_tc_debug controls the verbosity of the type checker. 0 is @@ -68,9 +69,12 @@ let rec indent n = match n with | 0 -> "" | n -> "| " ^ indent (n - 1) -let typ_debug m = if !opt_tc_debug > 1 then prerr_endline (indent !depth ^ m) else () +(* Lazily evaluate debugging message. This can make a big performance + difference; for example, repeated calls to string_of_exp can be costly for + deeply nested expressions, e.g. with long sequences of monadic binds. *) +let typ_debug m = if !opt_tc_debug > 1 then prerr_endline (indent !depth ^ Lazy.force m) else () -let typ_print m = if !opt_tc_debug > 0 then prerr_endline (indent !depth ^ m) else () +let typ_print m = if !opt_tc_debug > 0 then prerr_endline (indent !depth ^ Lazy.force m) else () type type_error = (* First parameter is the error that caused us to start doing type @@ -461,12 +465,12 @@ end = struct | Not_found -> [] let add_overloads id ids env = - typ_print ("Adding overloads for " ^ string_of_id id ^ " [" ^ string_of_list ", " string_of_id ids ^ "]"); + typ_print (lazy ("Adding overloads for " ^ string_of_id id ^ " [" ^ string_of_list ", " string_of_id ids ^ "]")); let existing = try Bindings.find id env.overloads with Not_found -> [] in { env with overloads = Bindings.add id (existing @ ids) env.overloads } let add_smt_op id str env = - typ_print ("Adding smt binding " ^ string_of_id id ^ " to " ^ str); + typ_print (lazy ("Adding smt binding " ^ string_of_id id ^ " to " ^ str)); { env with smt_ops = Bindings.add id str env.smt_ops } let get_smt_op (Id_aux (_, l) as id) env = @@ -514,7 +518,7 @@ end = struct else typ_error (id_loc id) ("Could not prove " ^ string_of_list ", " string_of_n_constraint ncs ^ " for type constructor " ^ string_of_id id) let rec expand_synonyms env (Typ_aux (typ, l) as t) = - (* typ_debug ("Expanding synonyms for " ^ string_of_typ t); *) + (* typ_debug (lazy ("Expanding synonyms for " ^ string_of_typ t)); *) match typ with | Typ_tup typs -> Typ_aux (Typ_tup (List.map (expand_synonyms env) typs), l) | Typ_fn (typ1, typ2, effs) -> Typ_aux (Typ_fn (expand_synonyms env typ1, expand_synonyms env typ2, effs), l) @@ -555,7 +559,7 @@ end = struct let kids = List.map rename_kid kids in let nc = List.fold_left (fun nc kid -> nc_subst_nexp kid (Nexp_var (prepend_kid "syn#" kid)) nc) nc !rebindings in let typ = List.fold_left (fun typ kid -> typ_subst_nexp kid (Nexp_var (prepend_kid "syn#" kid)) typ) typ !rebindings in - typ_print ("Synonym existential: {" ^ string_of_list " " string_of_kid kids ^ ", " ^ string_of_n_constraint nc ^ ". " ^ string_of_typ typ ^ "}"); + typ_print (lazy ("Synonym existential: {" ^ string_of_list " " string_of_kid kids ^ ", " ^ string_of_n_constraint nc ^ ". " ^ string_of_typ typ ^ "}")); let env = { env with constraints = nc :: env.constraints } in Typ_aux (Typ_exist (kids, nc, expand_synonyms env typ), l) | Typ_var v -> Typ_aux (Typ_var v, l) @@ -626,7 +630,7 @@ end = struct (* Check if a type, order, n-expression or constraint is well-formed. Throws a type error if the type is badly formed. *) let rec wf_typ ?exs:(exs=KidSet.empty) env typ = - typ_debug ("Well-formed " ^ string_of_typ typ); + typ_debug (lazy ("Well-formed " ^ string_of_typ typ)); let (Typ_aux (typ_aux, l)) = expand_synonyms env typ in match typ_aux with | Typ_id id when bound_typ_id env id -> @@ -716,9 +720,9 @@ end = struct let get_val_spec id env = try let bind = Bindings.find id env.top_val_specs in - typ_debug ("get_val_spec: Env has " ^ string_of_list ", " (fun (kid, bk) -> string_of_kid kid ^ " => " ^ string_of_base_kind_aux bk) (KBindings.bindings env.typ_vars)); + typ_debug (lazy ("get_val_spec: Env has " ^ string_of_list ", " (fun (kid, bk) -> string_of_kid kid ^ " => " ^ string_of_base_kind_aux bk) (KBindings.bindings env.typ_vars))); let bind' = List.fold_left (fun bind (kid, _) -> freshen_kid env kid bind) bind (KBindings.bindings env.typ_vars) in - typ_debug ("get_val_spec: freshened to " ^ string_of_bind bind'); + 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) @@ -726,7 +730,7 @@ end = struct let update_val_spec id (typq, typ) env = begin let typ = expand_synonyms env typ in - typ_print ("Adding val spec binding " ^ string_of_id id ^ " :: " ^ string_of_bind (typq, typ)); + typ_print (lazy ("Adding val spec binding " ^ string_of_id id ^ " :: " ^ string_of_bind (typq, typ))); { env with top_val_specs = Bindings.add id (typq, typ) env.top_val_specs } end @@ -753,7 +757,7 @@ end = struct then typ_error (id_loc id) ("Cannot create enum " ^ string_of_id id ^ ", type name is already bound") else begin - typ_print ("Adding enum " ^ string_of_id id); + typ_print (lazy ("Adding enum " ^ string_of_id id)); { env with enums = Bindings.add id (IdSet.of_list ids) env.enums } end @@ -769,7 +773,7 @@ end = struct then typ_error (id_loc id) ("Cannot create record " ^ string_of_id id ^ ", type name is already bound") else begin - typ_print ("Adding record " ^ string_of_id id); + typ_print (lazy ("Adding record " ^ string_of_id id)); let rec record_typ_args = function | [] -> [] | ((QI_aux (QI_id kopt, _)) :: qis) when is_nat_kopt kopt -> @@ -786,7 +790,7 @@ end = struct in let fold_accessors accs (typ, fid) = let acc_typ = mk_typ (Typ_fn (rectyp, typ, Effect_aux (Effect_set [], Parse_ast.Unknown))) in - typ_print (indent 1 ^ "Adding accessor " ^ string_of_id id ^ "." ^ string_of_id fid ^ " :: " ^ string_of_bind (typq, acc_typ)); + typ_print (lazy (indent 1 ^ "Adding accessor " ^ string_of_id id ^ "." ^ string_of_id fid ^ " :: " ^ string_of_bind (typq, acc_typ))); Bindings.add (field_name id fid) (typq, acc_typ) accs in { env with records = Bindings.add id (typq, fields) env.records; @@ -824,19 +828,19 @@ end = struct 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") else (); - typ_print ("Adding local binding " ^ string_of_id id ^ " :: " ^ string_of_mtyp mtyp); + typ_print (lazy ("Adding local binding " ^ string_of_id id ^ " :: " ^ string_of_mtyp mtyp)); { env with locals = Bindings.add id mtyp env.locals } end let add_variant id variant env = begin - typ_print ("Adding variant " ^ string_of_id id); + typ_print (lazy ("Adding variant " ^ string_of_id id)); { env with variants = Bindings.add id variant env.variants } end let add_union_id id bind env = begin - typ_print ("Adding union identifier binding " ^ string_of_id id ^ " :: " ^ string_of_bind bind); + typ_print (lazy ("Adding union identifier binding " ^ string_of_id id ^ " :: " ^ string_of_bind bind)); { env with union_ids = Bindings.add id bind env.union_ids } end @@ -846,7 +850,7 @@ end = struct let add_flow id f env = begin - typ_print ("Adding flow constraints for " ^ string_of_id id); + typ_print (lazy ("Adding flow constraints for " ^ string_of_id id)); { env with flow = Bindings.add id (fun typ -> f (get_flow id env typ)) env.flow } end @@ -881,7 +885,7 @@ end = struct then typ_error (id_loc id) ("Register " ^ string_of_id id ^ " is already bound") else begin - typ_print ("Adding register binding " ^ string_of_id id ^ " :: " ^ string_of_typ typ); + typ_print (lazy ("Adding register binding " ^ string_of_id id ^ " :: " ^ string_of_typ typ)); { env with registers = Bindings.add id typ env.registers } end @@ -911,7 +915,7 @@ end = struct then typ_error (kid_loc kid) ("Kind identifier " ^ string_of_kid kid ^ " is already bound") else begin - typ_print ("Adding kind identifier " ^ string_of_kid kid ^ " :: " ^ string_of_base_kind_aux k); + typ_print (lazy ("Adding kind identifier " ^ string_of_kid kid ^ " :: " ^ string_of_base_kind_aux k)); { env with typ_vars = KBindings.add kid k env.typ_vars } end @@ -920,7 +924,7 @@ end = struct then typ_error (id_loc id) ("Num identifier " ^ string_of_id id ^ " is already bound") else begin - typ_print ("Adding Num identifier " ^ string_of_id id ^ " :: " ^ string_of_nexp nexp); + typ_print (lazy ("Adding Num identifier " ^ string_of_id id ^ " :: " ^ string_of_nexp nexp)); { env with num_defs = Bindings.add id nexp env.num_defs } end @@ -933,7 +937,7 @@ end = struct let add_constraint (NC_aux (nc_aux, l) as constr) env = wf_constraint env constr; begin - typ_print ("Adding constraint " ^ string_of_n_constraint constr); + typ_print (lazy ("Adding constraint " ^ string_of_n_constraint constr)); match nc_aux with | NC_true -> env | _ -> { env with constraints = constr :: env.constraints } @@ -949,7 +953,7 @@ end = struct let enable_casts env = { env with allow_casts = true } let add_cast cast env = - typ_print ("Adding cast " ^ string_of_id cast); + typ_print (lazy ("Adding cast " ^ string_of_id cast)); { env with casts = cast :: env.casts } let add_typ_synonym id synonym env = @@ -957,7 +961,7 @@ end = struct then typ_error (id_loc id) ("Type synonym " ^ string_of_id id ^ " already exists") else begin - typ_print ("Adding type synonym " ^ string_of_id id); + typ_print (lazy ("Adding type synonym " ^ string_of_id id)); { env with typ_synonyms = Bindings.add id synonym env.typ_synonyms } end @@ -1197,16 +1201,16 @@ let prove_z3' env constr = in let constr = Constraint.conj (nc_constraints env var_of (Env.get_constraints env)) (constr var_of) in match Constraint.call_z3 constr with - | Constraint.Unsat -> typ_debug "unsat"; true - | Constraint.Sat -> typ_debug "sat"; false - | Constraint.Unknown -> typ_debug "unknown"; false + | Constraint.Unsat -> typ_debug (lazy "unsat"); true + | Constraint.Sat -> typ_debug (lazy "sat"); false + | Constraint.Unknown -> typ_debug (lazy "unknown"); false let prove_z3 env nc = - typ_print ("Prove " ^ string_of_list ", " string_of_n_constraint (Env.get_constraints env) ^ " |- " ^ string_of_n_constraint nc); + typ_print (lazy ("Prove " ^ string_of_list ", " string_of_n_constraint (Env.get_constraints env) ^ " |- " ^ string_of_n_constraint nc)); prove_z3' env (fun var_of -> Constraint.negate (nc_constraint env var_of nc)) let solve env nexp = - typ_print ("Solve " ^ string_of_list ", " string_of_n_constraint (Env.get_constraints env) ^ " |- " ^ string_of_nexp nexp ^ " = ?"); + typ_print (lazy ("Solve " ^ string_of_list ", " string_of_n_constraint (Env.get_constraints env) ^ " |- " ^ string_of_nexp nexp ^ " = ?")); match nexp with | Nexp_aux (Nexp_constant n,_) -> Some n | _ -> @@ -1381,7 +1385,7 @@ exception Unification_error of l * string;; let unify_error l str = raise (Unification_error (l, str)) let rec unify_nexps l env goals (Nexp_aux (nexp_aux1, _) as nexp1) (Nexp_aux (nexp_aux2, _) as nexp2) = - typ_debug ("UNIFYING NEXPS " ^ string_of_nexp nexp1 ^ " AND " ^ string_of_nexp nexp2 ^ " FOR GOALS " ^ string_of_list ", " string_of_kid (KidSet.elements goals)); + typ_debug (lazy ("UNIFYING NEXPS " ^ string_of_nexp nexp1 ^ " AND " ^ string_of_nexp nexp2 ^ " FOR GOALS " ^ string_of_list ", " string_of_kid (KidSet.elements goals))); if KidSet.is_empty (KidSet.inter (nexp_frees nexp1) goals) then begin @@ -1456,7 +1460,7 @@ let string_of_uvar = function | U_typ typ -> string_of_typ typ let unify_order l (Ord_aux (ord_aux1, _) as ord1) (Ord_aux (ord_aux2, _) as ord2) = - typ_debug ("UNIFYING ORDERS " ^ string_of_order ord1 ^ " AND " ^ string_of_order ord2); + typ_debug (lazy ("UNIFYING ORDERS " ^ string_of_order ord1 ^ " AND " ^ string_of_order ord2)); match ord_aux1, ord_aux2 with | Ord_var kid, _ -> KBindings.singleton kid (U_order ord2) | Ord_inc, Ord_inc -> KBindings.empty @@ -1505,11 +1509,11 @@ let merge_unifiers l kid uvar1 uvar2 = | None, None -> None let rec unify l env typ1 typ2 = - typ_print ("Unify " ^ string_of_typ typ1 ^ " with " ^ string_of_typ typ2); + typ_print (lazy ("Unify " ^ string_of_typ typ1 ^ " with " ^ string_of_typ typ2)); let goals = KidSet.inter (KidSet.diff (typ_frees typ1) (typ_frees typ2)) (typ_frees typ1) in let rec unify_typ l (Typ_aux (typ1_aux, _) as typ1) (Typ_aux (typ2_aux, _) as typ2) = - typ_debug ("UNIFYING TYPES " ^ string_of_typ typ1 ^ " AND " ^ string_of_typ typ2); + typ_debug (lazy ("UNIFYING TYPES " ^ string_of_typ typ1 ^ " AND " ^ string_of_typ typ2)); match typ1_aux, typ2_aux with | Typ_id v1, Typ_id v2 -> if Id.compare v1 v2 = 0 then KBindings.empty @@ -1577,7 +1581,7 @@ let rec unify l env typ1 typ2 = | Some (kids, nc, typ2) -> let typ1, typ2 = Env.expand_synonyms env typ1, Env.expand_synonyms env typ2 in let (unifiers, _, _) = unify l env typ1 typ2 in - typ_debug (string_of_list ", " (fun (kid, uvar) -> string_of_kid kid ^ " => " ^ string_of_uvar uvar) (KBindings.bindings unifiers)); + typ_debug (lazy (string_of_list ", " (fun (kid, uvar) -> string_of_kid kid ^ " => " ^ string_of_uvar uvar) (KBindings.bindings unifiers))); unifiers, kids, Some nc | None -> let typ1, typ2 = Env.expand_synonyms env typ1, Env.expand_synonyms env typ2 in @@ -1682,10 +1686,10 @@ let rec alpha_equivalent env typ1 typ2 = let typ1 = relabel (Env.expand_synonyms env typ1) in counter := 0; let typ2 = relabel (Env.expand_synonyms env typ2) in - typ_debug ("Alpha equivalence for " ^ string_of_typ typ1 ^ " and " ^ string_of_typ typ2); + typ_debug (lazy ("Alpha equivalence for " ^ string_of_typ typ1 ^ " and " ^ string_of_typ typ2)); if typ_identical env typ1 typ2 - then (typ_debug "alpha-equivalent"; true) - else (typ_debug "Not alpha-equivalent"; false) + then (typ_debug (lazy "alpha-equivalent"); true) + else (typ_debug (lazy "Not alpha-equivalent"); false) let unwrap_exist env typ = match destruct_exist env typ with @@ -1693,7 +1697,7 @@ let unwrap_exist env typ = | None -> ([], nc_true, typ) let rec subtyp l env (Typ_aux (typ_aux1, _) as typ1) (Typ_aux (typ_aux2, _) as typ2) = - typ_print (("Subtype " |> Util.green |> Util.clear) ^ string_of_typ typ1 ^ " and " ^ string_of_typ typ2); + typ_print (lazy (("Subtype " |> Util.green |> Util.clear) ^ string_of_typ typ1 ^ " and " ^ string_of_typ typ2)); match typ_aux1, typ_aux2 with | Typ_tup typs1, Typ_tup typs2 when List.length typs1 = List.length typs2 -> List.iter2 (subtyp l env) typs1 typs2 @@ -1803,7 +1807,7 @@ let is_typ_kid kid = function let rec instantiate_quants quants kid uvar = match quants with | [] -> [] | ((QI_aux (QI_id kinded_id, _) as quant) :: quants) -> - typ_debug ("instantiating quant " ^ string_of_quant_item quant); + typ_debug (lazy ("instantiating quant " ^ string_of_quant_item quant)); begin match uvar with | U_nexp nexp -> @@ -2066,7 +2070,7 @@ let rec filter_casts env from_typ to_typ casts = match cast_typ with | Typ_aux (Typ_fn (cast_from_typ, cast_to_typ, _), _) when match_typ env from_typ cast_from_typ && match_typ env to_typ cast_to_typ -> - typ_print ("Considering cast " ^ string_of_typ cast_typ ^ " for " ^ string_of_typ from_typ ^ " to " ^ string_of_typ to_typ); + typ_print (lazy ("Considering cast " ^ string_of_typ cast_typ ^ " for " ^ string_of_typ from_typ ^ " to " ^ string_of_typ to_typ)); cast :: filter_casts env from_typ to_typ casts | _ -> filter_casts env from_typ to_typ casts end @@ -2074,7 +2078,7 @@ let rec filter_casts env from_typ to_typ casts = let crule r env exp typ = incr depth; - typ_print ("Check " ^ string_of_exp exp ^ " <= " ^ string_of_typ typ); + typ_print (lazy ("Check " ^ string_of_exp exp ^ " <= " ^ string_of_typ typ)); try let checked_exp = r env exp typ in decr depth; checked_exp @@ -2085,7 +2089,7 @@ let irule r env exp = incr depth; try let inferred_exp = r env exp in - typ_print ("Infer " ^ string_of_exp exp ^ " => " ^ string_of_typ (typ_of inferred_exp)); + typ_print (lazy ("Infer " ^ string_of_exp exp ^ " => " ^ string_of_typ (typ_of inferred_exp))); decr depth; inferred_exp with @@ -2126,7 +2130,7 @@ let rec check_exp env (E_aux (exp_aux, (l, ())) as exp : unit exp) (Typ_aux (typ let checked_msg = crule check_exp env assert_msg string_typ in let env = match assert_constraint env constr_exp with | Some nc -> - typ_print ("Adding constraint " ^ string_of_n_constraint nc ^ " for assert"); + typ_print (lazy ("Adding constraint " ^ string_of_n_constraint nc ^ " for assert")); Env.add_constraint nc env | None -> env in @@ -2226,10 +2230,10 @@ let rec check_exp env (E_aux (exp_aux, (l, ())) as exp : unit exp) (Typ_aux (typ let rec try_overload = function | (errs, []) -> typ_raise l (Err_no_overloading (f, errs)) | (errs, (f :: fs)) -> begin - typ_print ("Overload: " ^ string_of_id f ^ "(" ^ string_of_list ", " string_of_exp xs ^ ")"); + 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) -> - typ_print ("Error : " ^ string_of_type_error err); + typ_print (lazy ("Error : " ^ string_of_type_error err)); try_overload (errs @ [(f, err)], fs) end in @@ -2281,7 +2285,7 @@ let rec check_exp env (E_aux (exp_aux, (l, ())) as exp : unit exp) (Typ_aux (typ begin match assert_constraint env constr_exp with | Some nc -> - typ_print ("Adding constraint " ^ string_of_n_constraint nc ^ " for assert"); + typ_print (lazy ("Adding constraint " ^ string_of_n_constraint nc ^ " for assert")); Env.add_constraint nc env | None -> env end @@ -2352,7 +2356,7 @@ and type_coercion env (E_aux (_, (l, _)) as annotated_exp) typ = let rec try_casts trigger errs = function | [] -> typ_raise l (Err_no_casts (strip_exp annotated_exp, trigger, errs)) | (cast :: casts) -> begin - typ_print ("Casting with " ^ string_of_id cast ^ " expression " ^ string_of_exp annotated_exp ^ " to " ^ string_of_typ typ); + 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 @@ -2362,7 +2366,7 @@ and type_coercion env (E_aux (_, (l, _)) as annotated_exp) typ = in begin try - typ_debug ("PERFORMING TYPE COERCION: from " ^ string_of_typ (typ_of annotated_exp) ^ " to " ^ string_of_typ 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_typ annotated_exp typ with | Type_error (_, trigger) when Env.allow_casts env -> @@ -2386,7 +2390,7 @@ and type_coercion_unify env (E_aux (_, (l, _)) as annotated_exp) typ = let rec try_casts = function | [] -> unify_error l "No valid casts resulted in unification" | (cast :: casts) -> begin - typ_print ("Casting with " ^ string_of_id cast ^ " expression " ^ string_of_exp annotated_exp ^ " for unification"); + typ_print (lazy ("Casting with " ^ string_of_id cast ^ " expression " ^ string_of_exp annotated_exp ^ " for unification")); try let inferred_cast = irule infer_exp (Env.no_casts env) (strip (E_app (cast, [annotated_exp]))) in let ityp = typ_of inferred_cast in @@ -2398,7 +2402,7 @@ and type_coercion_unify env (E_aux (_, (l, _)) as annotated_exp) typ = in begin try - typ_debug "PERFORMING COERCING UNIFICATION"; + typ_debug (lazy "PERFORMING COERCING UNIFICATION"); annotated_exp, unify l env typ (typ_of annotated_exp) with | Unification_error (_, m) when Env.allow_casts env -> @@ -2413,7 +2417,7 @@ and bind_pat_no_guard env (P_aux (_,(l,_)) as pat) typ = and bind_pat env (P_aux (pat_aux, (l, ())) as pat) (Typ_aux (typ_aux, _) as typ) = let (Typ_aux (typ_aux, _) as typ), env = bind_existential typ env in - typ_print ("Binding " ^ string_of_pat pat ^ " to " ^ string_of_typ typ); + typ_print (lazy ("Binding " ^ string_of_pat pat ^ " to " ^ string_of_typ typ)); let annot_pat pat typ = P_aux (pat, (l, Some (env, typ, no_effect))) in let switch_typ pat typ = match pat with | P_aux (pat_aux, (l, Some (env, _, eff))) -> P_aux (pat_aux, (l, Some (env, typ, eff))) @@ -2497,9 +2501,9 @@ and bind_pat env (P_aux (pat_aux, (l, ())) as pat) (Typ_aux (typ_aux, _) as typ) | Typ_aux (Typ_fn (arg_typ, ret_typ, _), _) -> begin try - typ_debug ("Unifying " ^ string_of_bind (typq, ctor_typ) ^ " for pattern " ^ string_of_typ typ); + typ_debug (lazy ("Unifying " ^ string_of_bind (typq, ctor_typ) ^ " for pattern " ^ string_of_typ typ)); let unifiers, _, _ (* FIXME! *) = unify l env ret_typ typ in - typ_debug (string_of_list ", " (fun (kid, uvar) -> string_of_kid kid ^ " => " ^ string_of_uvar uvar) (KBindings.bindings unifiers)); + typ_debug (lazy (string_of_list ", " (fun (kid, uvar) -> string_of_kid kid ^ " => " ^ string_of_uvar uvar) (KBindings.bindings unifiers))); let arg_typ' = subst_unifiers unifiers arg_typ in let quants' = List.fold_left (fun qs (kid, uvar) -> instantiate_quants qs kid uvar) quants (KBindings.bindings unifiers) in if (match quants' with [] -> false | _ -> true) @@ -2652,7 +2656,7 @@ and bind_assignment env (LEXP_aux (lexp_aux, _) as lexp) (E_aux (_, (l, ())) as | _ -> typ_error 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 ("REGTYP: " ^ string_of_typ regtyp ^ " / " ^ string_of_typ (Env.expand_synonyms env regtyp)); + typ_debug (lazy ("REGTYP: " ^ string_of_typ regtyp ^ " / " ^ string_of_typ (Env.expand_synonyms env regtyp))); match Env.expand_synonyms env regtyp with | 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 @@ -2915,10 +2919,10 @@ and infer_exp env (E_aux (exp_aux, (l, ())) as exp) = let rec try_overload = function | (errs, []) -> typ_raise l (Err_no_overloading (f, errs)) | (errs, (f :: fs)) -> begin - typ_print ("Overload: " ^ string_of_id f ^ "(" ^ string_of_list ", " string_of_exp xs ^ ")"); + 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) -> - typ_print ("Error : " ^ string_of_type_error err); + typ_print (lazy ("Error : " ^ string_of_type_error err)); try_overload (errs @ [(f, err)], fs) end in @@ -2991,7 +2995,7 @@ and infer_exp env (E_aux (exp_aux, (l, ())) as exp) = begin match assert_constraint env constr_exp with | Some nc -> - typ_print ("Adding constraint " ^ string_of_n_constraint nc ^ " for assert"); + typ_print (lazy ("Adding constraint " ^ string_of_n_constraint nc ^ " for assert")); Env.add_constraint nc env | None -> env end @@ -3059,7 +3063,7 @@ and infer_funapp' l env f (typq, f_typ) xs ret_ctx_typ = match typs, args with | (utyps, []), (uargs, []) -> begin - typ_debug ("Got unresolved args: " ^ string_of_list ", " (fun (_, exp) -> string_of_exp exp) uargs); + typ_debug (lazy ("Got unresolved args: " ^ string_of_list ", " (fun (_, exp) -> string_of_exp exp) uargs)); if List.for_all (solve_quant env) quants then let iuargs = List.map2 (fun utyp (n, uarg) -> (n, crule check_exp env uarg utyp)) utyps uargs in @@ -3076,9 +3080,9 @@ and infer_funapp' l env f (typq, f_typ) xs ret_ctx_typ = end | (utyps, (typ :: typs)), (uargs, ((n, arg) :: args)) -> begin - typ_debug ("INSTANTIATE: " ^ string_of_exp arg ^ " with " ^ string_of_typ typ); + typ_debug (lazy ("INSTANTIATE: " ^ string_of_exp arg ^ " with " ^ string_of_typ typ)); let iarg = irule infer_exp env arg in - typ_debug ("INFER: " ^ string_of_exp arg ^ " type " ^ string_of_typ (typ_of iarg)); + typ_debug (lazy ("INFER: " ^ string_of_exp arg ^ " type " ^ string_of_typ (typ_of iarg))); try (* If we get an existential when instantiating, we prepend the identifier of the exisitential with the tag argN# to @@ -3086,8 +3090,8 @@ and infer_funapp' l env f (typq, f_typ) xs ret_ctx_typ = function. *) let ex_tag = "arg" ^ string_of_int n ^ "#" in let iarg, (unifiers, ex_kids, ex_nc) = type_coercion_unify env iarg typ in - typ_debug (string_of_list ", " (fun (kid, uvar) -> string_of_kid kid ^ " => " ^ string_of_uvar uvar) (KBindings.bindings unifiers)); - typ_debug ("EX KIDS: " ^ string_of_list ", " string_of_kid ex_kids); + typ_debug (lazy (string_of_list ", " (fun (kid, uvar) -> string_of_kid kid ^ " => " ^ string_of_uvar uvar) (KBindings.bindings unifiers))); + typ_debug (lazy ("EX KIDS: " ^ string_of_list ", " string_of_kid ex_kids)); let env = match ex_kids, ex_nc with | [], None -> env | _, Some enc -> @@ -3107,7 +3111,7 @@ and infer_funapp' l env f (typq, f_typ) xs ret_ctx_typ = ((n, iarg) :: iargs, ret_typ'', env) with | Unification_error (l, str) -> - typ_print ("Unification error: " ^ str); + typ_print (lazy ("Unification error: " ^ str)); instantiate env quants (typ :: utyps, typs) ret_typ ((n, arg) :: uargs, args) end | (_, []), _ -> typ_error l ("Function " ^ string_of_id f ^ " applied to too many arguments") @@ -3119,14 +3123,14 @@ and infer_funapp' l env f (typq, f_typ) xs ret_ctx_typ = | Some rct when is_exist (Env.expand_synonyms env rct) -> (quants, typs, ret_typ, env) | Some rct -> begin - typ_debug ("RCT is " ^ string_of_typ rct); - typ_debug ("INSTANTIATE RETURN:" ^ string_of_typ ret_typ); + typ_debug (lazy ("RCT is " ^ string_of_typ rct)); + typ_debug (lazy ("INSTANTIATE RETURN:" ^ string_of_typ ret_typ)); let unifiers, ex_kids, ex_nc = try unify l env ret_typ rct with - | Unification_error _ -> typ_debug "UERROR"; KBindings.empty, [], None + | Unification_error _ -> typ_debug (lazy "UERROR"); KBindings.empty, [], None in - typ_debug (string_of_list ", " (fun (kid, uvar) -> string_of_kid kid ^ " => " ^ string_of_uvar uvar) (KBindings.bindings unifiers)); - if ex_kids = [] then () else (typ_debug ("EX GOAL: " ^ string_of_option string_of_n_constraint ex_nc); ex_goal := ex_nc); + typ_debug (lazy (string_of_list ", " (fun (kid, uvar) -> string_of_kid kid ^ " => " ^ string_of_uvar uvar) (KBindings.bindings unifiers))); + if ex_kids = [] then () else (typ_debug (lazy ("EX GOAL: " ^ string_of_option string_of_n_constraint ex_nc)); ex_goal := ex_nc); record_unifiers unifiers; let env = List.fold_left (fun env kid -> Env.add_typ_var kid BK_int env) env ex_kids in let typs' = List.map (subst_unifiers unifiers) typs in @@ -3148,8 +3152,8 @@ and infer_funapp' l env f (typq, f_typ) xs ret_ctx_typ = | _ -> typ_error l (string_of_typ f_typ ^ " is not a function type") in let unifiers = instantiate_simple_equations quants in - typ_debug "Instantiating from equations"; - typ_debug (string_of_list ", " (fun (kid, uvar) -> string_of_kid kid ^ " => " ^ string_of_uvar uvar) (KBindings.bindings unifiers)); all_unifiers := unifiers; + typ_debug (lazy "Instantiating from equations"); + typ_debug (lazy (string_of_list ", " (fun (kid, uvar) -> string_of_kid kid ^ " => " ^ string_of_uvar uvar) (KBindings.bindings unifiers))); all_unifiers := unifiers; let typ_args = List.map (subst_unifiers unifiers) typ_args in let quants = List.fold_left (fun qs (kid, uvar) -> instantiate_quants qs kid uvar) quants (KBindings.bindings unifiers) in let typ_ret = subst_unifiers unifiers typ_ret in @@ -3166,23 +3170,23 @@ and infer_funapp' l env f (typq, f_typ) xs ret_ctx_typ = let num_new_ncs = List.length (Env.get_constraints env) - List.length universal_constraints in let ex_constraints = take num_new_ncs (Env.get_constraints env) in - typ_debug ("Existentials: " ^ string_of_list ", " string_of_kid existentials); - typ_debug ("Existential constraints: " ^ string_of_list ", " string_of_n_constraint ex_constraints); + typ_debug (lazy ("Existentials: " ^ string_of_list ", " string_of_kid existentials)); + typ_debug (lazy ("Existential constraints: " ^ string_of_list ", " string_of_n_constraint ex_constraints)); let typ_ret = if KidSet.is_empty (KidSet.of_list existentials) || KidSet.is_empty (typ_frees typ_ret) - then (typ_debug "Returning Existential"; typ_ret) + then (typ_debug (lazy "Returning Existential"); typ_ret) else mk_typ (Typ_exist (existentials, List.fold_left nc_and nc_true ex_constraints, typ_ret)) in let typ_ret = simp_typ typ_ret in let exp = annot_exp (E_app (f, xs_reordered)) typ_ret eff in - typ_debug ("RETURNING: " ^ string_of_typ (typ_of exp)); + typ_debug (lazy ("RETURNING: " ^ string_of_typ (typ_of exp))); match ret_ctx_typ with | None -> exp, !all_unifiers | Some rct -> let exp = type_coercion env exp rct in - typ_debug ("RETURNING AFTER COERCION " ^ string_of_typ (typ_of exp)); + typ_debug (lazy ("RETURNING AFTER COERCION " ^ string_of_typ (typ_of exp))); exp, !all_unifiers (**************************************************************************) @@ -3469,7 +3473,7 @@ and propagate_lexp_effect_aux = function (**************************************************************************) let check_letdef orig_env (LB_aux (letbind, (l, _))) = - typ_print "\nChecking top-level let"; + typ_print (lazy "\nChecking top-level let"); begin match letbind with | LB_val (P_aux (P_typ (typ_annot, _), _) as pat, bind) -> @@ -3563,7 +3567,7 @@ let check_fundef env (FD_aux (FD_function (recopt, tannotopt, effectopt, funcls) | Some id -> id | None -> typ_error l "funcl list is empty" in - typ_print ("\nChecking function " ^ string_of_id id); + typ_print (lazy ("\nChecking function " ^ string_of_id id)); let have_val_spec, (quant, typ), env = try true, Env.get_val_spec id env, env with | Type_error (l, _) -> @@ -3575,7 +3579,7 @@ let check_fundef env (FD_aux (FD_function (recopt, tannotopt, effectopt, funcls) | _ -> typ_error l "Function val spec was not a function type" in check_tannotopt env quant vtyp_ret tannotopt; - typ_debug ("Checking fundef " ^ string_of_id id ^ " has type " ^ string_of_bind (quant, typ)); + typ_debug (lazy ("Checking fundef " ^ string_of_id id ^ " has type " ^ string_of_bind (quant, typ))); let funcl_env = add_typquant quant env in let funcls = List.map (fun funcl -> check_funcl funcl_env funcl typ) funcls in let eff = List.fold_left union_effects no_effect (List.map funcl_effect funcls) in @@ -3599,13 +3603,13 @@ let check_val_spec env (VS_aux (vs, (l, _))) = let annotate vs typ eff = DEF_spec (VS_aux (vs, (l, Some (env,typ,eff)))) in let (id, quants, typ, env) = match vs with | VS_val_spec (TypSchm_aux (TypSchm_ts (quants, typ), _) as typschm, id, ext_opt, is_cast) -> - typ_debug ("VS typschm: " ^ string_of_id id ^ ", " ^ string_of_typschm typschm); + typ_debug (lazy ("VS typschm: " ^ string_of_id id ^ ", " ^ string_of_typschm typschm)); let env = match (ext_opt "smt", ext_opt "#") with | Some op, None -> Env.add_smt_op id op env | _, _ -> env in Env.wf_typ (add_typquant quants env) typ; - typ_debug "CHECKED WELL-FORMED VAL SPEC"; + typ_debug (lazy "CHECKED WELL-FORMED VAL SPEC"); let env = (* match ext_opt with | None -> env |
