diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/ast_util.ml | 1 | ||||
| -rw-r--r-- | src/ast_util.mli | 5 | ||||
| -rw-r--r-- | src/nl_flow.ml | 2 | ||||
| -rw-r--r-- | src/type_check.ml | 54 | ||||
| -rw-r--r-- | src/type_error.ml | 49 |
5 files changed, 58 insertions, 53 deletions
diff --git a/src/ast_util.ml b/src/ast_util.ml index a771291e..795a41fe 100644 --- a/src/ast_util.ml +++ b/src/ast_util.ml @@ -365,6 +365,7 @@ let range_typ nexp1 nexp2 = mk_typ (Typ_app (mk_id "range", [mk_typ_arg (A_nexp (nexp_simp nexp1)); mk_typ_arg (A_nexp (nexp_simp nexp2))])) let bool_typ = mk_id_typ (mk_id "bool") +let atom_bool_typ nc = mk_typ (Typ_app (mk_id "atom_bool", [mk_typ_arg (A_bool nc)])) let string_typ = mk_id_typ (mk_id "string") let list_typ typ = mk_typ (Typ_app (mk_id "list", [mk_typ_arg (A_typ typ)])) let tuple_typ typs = mk_typ (Typ_tup typs) diff --git a/src/ast_util.mli b/src/ast_util.mli index ca3a9598..7a44322d 100644 --- a/src/ast_util.mli +++ b/src/ast_util.mli @@ -113,7 +113,7 @@ val is_nat_kopt : kinded_id -> bool val is_order_kopt : kinded_id -> bool val is_typ_kopt : kinded_id -> bool val is_bool_kopt : kinded_id -> bool - + (* Some handy utility functions for constructing types. *) val mk_typ : typ_aux -> typ val mk_typ_arg : typ_arg_aux -> typ_arg @@ -127,6 +127,7 @@ val atom_typ : nexp -> typ val range_typ : nexp -> nexp -> typ val bit_typ : typ val bool_typ : typ +val atom_bool_typ : n_constraint -> typ val app_typ : id -> typ_arg list -> typ val register_typ : typ -> typ val unit_typ : typ @@ -191,7 +192,7 @@ val quant_map_items : (quant_item -> quant_item) -> typquant -> typquant val is_quant_kopt : quant_item -> bool val is_quant_constraint : quant_item -> bool - + (* Functions to map over the annotations in sub-expressions *) val map_exp_annot : ('a annot -> 'b annot) -> 'a exp -> 'b exp val map_pat_annot : ('a annot -> 'b annot) -> 'a pat -> 'b pat diff --git a/src/nl_flow.ml b/src/nl_flow.ml index e38e5fa5..6196f23b 100644 --- a/src/nl_flow.ml +++ b/src/nl_flow.ml @@ -91,7 +91,7 @@ let add_assert cond (E_aux (aux, (l, ())) as exp) = let modify_unsigned id value (E_aux (aux, annot) as exp) = match aux with | E_let (LB_aux (LB_val (pat, E_aux (E_app (f, [E_aux (E_id id', _)]), _)), _) as lb, exp') - when string_of_id f = "unsigned" && Id.compare id id' = 0 -> + when (string_of_id f = "unsigned" || string_of_id f = "UInt") && Id.compare id id' = 0 -> begin match pat_id pat with | None -> exp | Some uid -> diff --git a/src/type_check.ml b/src/type_check.ml index 53d87a05..09ee3380 100644 --- a/src/type_check.ml +++ b/src/type_check.ml @@ -259,10 +259,19 @@ let destruct_numeric typ = Some ([kid], nc_true, nvar kid) | _, _ -> None +let destruct_boolean = function + | Typ_aux (Typ_id (Id_aux (Id "bool", _)), _) -> + let kid = kopt_kid (fresh_existential K_bool) in + Some (kid, nc_var kid) + | _ -> None + let destruct_exist typ = match destruct_numeric typ with | Some (kids, nc, nexp) -> Some (List.map (mk_kopt K_int) kids, nc, atom_typ nexp) - | None -> destruct_exist_plain typ + | None -> + match destruct_boolean typ with + | Some (kid, nc) -> Some ([mk_kopt K_bool kid], nc_true, atom_bool_typ nc) + | None -> destruct_exist_plain typ let adding = Util.("Adding " |> darkgray |> clear) @@ -700,8 +709,7 @@ end = struct | NC_var kid -> begin match get_typ_var kid env with | K_bool -> () - | kind -> typ_error l ("Set constraint is badly formed, " - ^ string_of_kid kid ^ " has kind " + | kind -> typ_error l (string_of_kid kid ^ " has kind " ^ string_of_kind_aux kind ^ " but should have kind Bool") end | NC_true | NC_false -> () @@ -1243,7 +1251,7 @@ let prove_z3 env (NC_aux (_, l) as nc) = | Constraint.Sat -> typ_debug (lazy "sat"); false | Constraint.Unknown -> typ_debug (lazy "unknown"); false -let solve env (Nexp_aux (_, l) as nexp) = +let solve env (Nexp_aux (_, l) as nexp) = typ_print (lazy (Util.("Solve " |> red |> clear) ^ string_of_list ", " string_of_n_constraint (Env.get_constraints env) ^ " |- " ^ string_of_nexp nexp ^ " = ?")); match nexp with @@ -1621,10 +1629,21 @@ and kid_order_arg kind_map (A_aux (aux, l) as arg) = | A_order _ -> ([], kind_map) and kid_order_constraint kind_map (NC_aux (aux, l) as nc) = match aux with - | NC_var kid when KBindings.mem kid kind_map -> + | NC_var kid | NC_set (kid, _) when KBindings.mem kid kind_map -> ([mk_kopt (unaux_kind (KBindings.find kid kind_map)) kid], KBindings.remove kid kind_map) - | NC_var _ -> ([], kind_map) - | _ -> unreachable l __POS__ "bad constraint type" + | NC_var _ | NC_set _ -> ([], kind_map) + | NC_true | NC_false -> ([], kind_map) + | NC_equal (n1, n2) | NC_not_equal (n1, n2) | NC_bounded_le (n1, n2) | NC_bounded_ge (n1, n2) -> + let ord1, kind_map = kid_order_nexp kind_map n1 in + let ord2, kind_map = kid_order_nexp kind_map n2 in + (ord1 @ ord2, kind_map) + | NC_app (_, args) -> + List.fold_left (fun (ord, kind_map) arg -> let ord', kind_map = kid_order_arg kind_map arg in (ord @ ord', kind_map)) + ([], kind_map) args + | NC_and (nc1, nc2) | NC_or (nc1, nc2) -> + let ord1, kind_map = kid_order_constraint kind_map nc1 in + let ord2, kind_map = kid_order_constraint kind_map nc2 in + (ord1 @ ord2, kind_map) let rec alpha_equivalent env typ1 typ2 = let counter = ref 0 in @@ -1779,7 +1798,7 @@ and subtyp_arg l env (A_aux (aux1, _) as arg1) (A_aux (aux2, _) as arg2) = | A_nexp n1, A_nexp n2 when prove env (nc_eq n1 n2) -> () | 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 nc_identical nc1 nc2 -> () + | A_bool nc1, A_bool nc2 when prove env (nc_and (nc_or (nc_not nc1) nc2) (nc_or (nc_not nc2) nc1)) -> () | _, _ -> typ_error l "Mismatched argument types in subtype check" let typ_equality l env typ1 typ2 = @@ -1827,8 +1846,8 @@ let infer_lit env (L_aux (lit_aux, l) as lit) = | L_zero -> bit_typ | L_one -> bit_typ | L_num n -> atom_typ (nconstant n) - | L_true -> bool_typ - | L_false -> bool_typ + | L_true -> atom_bool_typ nc_true + | L_false -> atom_bool_typ nc_false | L_string _ -> string_typ | L_real _ -> real_typ | L_bin str -> @@ -2256,16 +2275,25 @@ let rec check_exp env (E_aux (exp_aux, (l, ())) as exp : unit exp) (Typ_aux (typ end | E_app_infix (x, op, y), _ -> check_exp env (E_aux (E_app (deinfix op, [x; y]), (l, ()))) typ - | E_app (f, [E_aux (E_constraint nc, _)]), _ when Id.compare f (mk_id "_prove") = 0 -> + | E_app (f, [E_aux (E_constraint nc, _)]), _ when string_of_id f = "_prove" -> Env.wf_constraint env nc; if prove 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) - | E_app (f, [E_aux (E_constraint nc, _)]), _ when Id.compare f (mk_id "_not_prove") = 0 -> + | E_app (f, [E_aux (E_constraint nc, _)]), _ when string_of_id f = "_not_prove" -> Env.wf_constraint env nc; if prove env nc then typ_error 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; + let _ = crule check_exp env exp typ in + 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 = "_not_check" -> + 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)) (* 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 -> @@ -3060,7 +3088,7 @@ and infer_exp env (E_aux (exp_aux, (l, ())) as exp) = | E_sizeof nexp -> annot_exp (E_sizeof nexp) (mk_typ (Typ_app (mk_id "atom", [mk_typ_arg (A_nexp nexp)]))) | E_constraint nc -> Env.wf_constraint env nc; - annot_exp (E_constraint nc) bool_typ + annot_exp (E_constraint nc) (atom_bool_typ nc) | E_field (exp, field) -> begin let inferred_exp = irule infer_exp env exp in diff --git a/src/type_error.ml b/src/type_error.ml index 9144e993..f28e4de8 100644 --- a/src/type_error.ml +++ b/src/type_error.ml @@ -67,38 +67,6 @@ let pp_nexp, pp_n_constraint = in pp_nexp', pp_n_constraint' -let rec nexp_subst sv subst (Nexp_aux (nexp, l)) = Nexp_aux (nexp_subst_aux sv subst nexp, l) -and nexp_subst_aux sv subst = function - | Nexp_id v -> Nexp_id v - | Nexp_var kid -> if Kid.compare kid sv = 0 then subst else Nexp_var kid - | Nexp_constant c -> Nexp_constant c - | Nexp_times (nexp1, nexp2) -> Nexp_times (nexp_subst sv subst nexp1, nexp_subst sv subst nexp2) - | Nexp_sum (nexp1, nexp2) -> Nexp_sum (nexp_subst sv subst nexp1, nexp_subst sv subst nexp2) - | Nexp_minus (nexp1, nexp2) -> Nexp_minus (nexp_subst sv subst nexp1, nexp_subst sv subst nexp2) - | Nexp_app (id, nexps) -> Nexp_app (id, List.map (nexp_subst sv subst) nexps) - | Nexp_exp nexp -> Nexp_exp (nexp_subst sv subst nexp) - | Nexp_neg nexp -> Nexp_neg (nexp_subst sv subst nexp) - -let rec nexp_set_to_or l subst = function - | [] -> typ_error l "Cannot substitute into empty nexp set" - | [int] -> NC_equal (subst, nconstant int) - | (int :: ints) -> NC_or (mk_nc (NC_equal (subst, nconstant int)), mk_nc (nexp_set_to_or l subst ints)) - -let rec nc_subst_nexp sv subst (NC_aux (nc, l)) = NC_aux (nc_subst_nexp_aux l sv subst nc, l) -and nc_subst_nexp_aux l sv subst = function - | NC_equal (n1, n2) -> NC_equal (nexp_subst sv subst n1, nexp_subst sv subst n2) - | NC_bounded_ge (n1, n2) -> NC_bounded_ge (nexp_subst sv subst n1, nexp_subst sv subst n2) - | NC_bounded_le (n1, n2) -> NC_bounded_le (nexp_subst sv subst n1, nexp_subst sv subst n2) - | NC_not_equal (n1, n2) -> NC_not_equal (nexp_subst sv subst n1, nexp_subst sv subst n2) - | NC_set (kid, ints) as set_nc -> - if Kid.compare kid sv = 0 - then nexp_set_to_or l (mk_nexp subst) ints - else set_nc - | NC_or (nc1, nc2) -> NC_or (nc_subst_nexp sv subst nc1, nc_subst_nexp sv subst nc2) - | NC_and (nc1, nc2) -> NC_and (nc_subst_nexp sv subst nc1, nc_subst_nexp sv subst nc2) - | NC_false -> NC_false - | NC_true -> NC_true - type suggestion = | Suggest_add_constraint of n_constraint | Suggest_none @@ -126,7 +94,7 @@ let rec analyze_unresolved_quant2 locals ncs = function | _ -> [] 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) -> nc_subst_nexp v (unaux_nexp nexp) nc) nc substs 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 Suggest_add_constraint nc else @@ -140,7 +108,7 @@ let rec analyze_unresolved_quant2 locals ncs = function [] 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 - let nc = List.fold_left (fun nc (v, nexp, _) -> nc_subst_nexp v (unaux_nexp nexp) nc) nc substs 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 Suggest_none else @@ -171,7 +139,7 @@ let rec analyze_unresolved_quant locals ncs = function | _ -> [] 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) -> nc_subst_nexp v (unaux_nexp nexp) nc) nc substs 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 @@ -188,7 +156,7 @@ let rec analyze_unresolved_quant locals ncs = function (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, _) -> nc_subst_nexp v (unaux_nexp nexp) nc) nc substs 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 ("The property " ^ string_of_n_constraint nc ^ " must hold") else @@ -239,7 +207,7 @@ let rec pp_type_error = function pp_type_error err ^^ hardline ^^ string "This error occured because of a previous error:" ^//^ pp_type_error err' - + | Err_other str -> string str let rec string_of_type_error err = @@ -264,6 +232,13 @@ let rec collapse_errors = function | Some _ -> err | None -> no_collapse end + | Err_because (err1, 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 -> err let check : 'a. Env.t -> 'a defs -> tannot defs * Env.t = |
