diff options
| author | Alasdair Armstrong | 2017-08-24 18:42:33 +0100 |
|---|---|---|
| committer | Alasdair Armstrong | 2017-08-24 18:42:33 +0100 |
| commit | 4b1b3f0e45d114592102d02fb668b6e11b526dbf (patch) | |
| tree | ae4715a5c1f9b813d54c39846b2485f04343c881 /src | |
| parent | b9810423d4eece710a276384a4664aaab6aed046 (diff) | |
More work on undefined elimination pass.
Also generate a function which initializes all the registers in a spec to undefined. This gives us the information we need post-rewriting to generate registers of any arbitrary type.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ast_util.ml | 120 | ||||
| -rw-r--r-- | src/ast_util.mli | 61 | ||||
| -rw-r--r-- | src/initial_check.ml | 68 | ||||
| -rw-r--r-- | src/parse_ast.ml | 1 | ||||
| -rw-r--r-- | src/rewriter.ml | 21 | ||||
| -rw-r--r-- | src/sail.ml | 1 | ||||
| -rw-r--r-- | src/type_check.ml | 113 | ||||
| -rw-r--r-- | src/type_check.mli | 50 |
8 files changed, 266 insertions, 169 deletions
diff --git a/src/ast_util.ml b/src/ast_util.ml index 7d8797f9..64bbc670 100644 --- a/src/ast_util.ml +++ b/src/ast_util.ml @@ -51,6 +51,8 @@ let no_annot = (Parse_ast.Unknown, ()) let inc_ord = Ord_aux (Ord_inc, Parse_ast.Unknown) let dec_ord = Ord_aux (Ord_dec, Parse_ast.Unknown) +let mk_id str = Id_aux (Id str, Parse_ast.Unknown) + let mk_nc nc_aux = NC_aux (nc_aux, Parse_ast.Unknown) let mk_nexp nexp_aux = Nexp_aux (nexp_aux, Parse_ast.Unknown) @@ -60,6 +62,8 @@ let unaux_exp (E_aux (exp_aux, _)) = exp_aux let mk_pat pat_aux = P_aux (pat_aux, no_annot) +let mk_lexp lexp_aux = LEXP_aux (lexp_aux, no_annot) + let mk_lit lit_aux = L_aux (lit_aux, Parse_ast.Unknown) let mk_lit_exp lit_aux = mk_exp (E_lit (mk_lit lit_aux)) @@ -76,6 +80,122 @@ let mk_fundef funcls = let mk_val_spec vs_aux = DEF_spec (VS_aux (vs_aux, no_annot)) +let kopt_kid (KOpt_aux (kopt_aux, _)) = + match kopt_aux with + | KOpt_none kid | KOpt_kind (_, kid) -> kid + +let is_nat_kopt = function + | KOpt_aux (KOpt_kind (K_aux (K_kind [BK_aux (BK_nat, _)], _), _), _) -> true + | KOpt_aux (KOpt_none _, _) -> true + | _ -> false + +let is_order_kopt = function + | KOpt_aux (KOpt_kind (K_aux (K_kind [BK_aux (BK_order, _)], _), _), _) -> true + | _ -> false + +let is_typ_kopt = function + | KOpt_aux (KOpt_kind (K_aux (K_kind [BK_aux (BK_type, _)], _), _), _) -> true + | _ -> false + +let rec nexp_simp (Nexp_aux (nexp, l)) = Nexp_aux (nexp_simp_aux nexp, l) +and nexp_simp_aux = function + | Nexp_minus (Nexp_aux (Nexp_sum (Nexp_aux (n1, _), Nexp_aux (Nexp_constant c1, _)), _), Nexp_aux (Nexp_constant c2, _)) when c1 = c2 -> + nexp_simp_aux n1 + | Nexp_sum (Nexp_aux (Nexp_minus (Nexp_aux (n1, _), Nexp_aux (Nexp_constant c1, _)), _), Nexp_aux (Nexp_constant c2, _)) when c1 = c2 -> + nexp_simp_aux n1 + | Nexp_sum (n1, n2) -> + begin + let (Nexp_aux (n1_simp, _) as n1) = nexp_simp n1 in + let (Nexp_aux (n2_simp, _) as n2) = nexp_simp n2 in + match n1_simp, n2_simp with + | Nexp_constant c1, Nexp_constant c2 -> Nexp_constant (c1 + c2) + | _, Nexp_neg n2 -> Nexp_minus (n1, n2) + | _, _ -> Nexp_sum (n1, n2) + end + | Nexp_times (n1, n2) -> + begin + let (Nexp_aux (n1_simp, _) as n1) = nexp_simp n1 in + let (Nexp_aux (n2_simp, _) as n2) = nexp_simp n2 in + match n1_simp, n2_simp with + | Nexp_constant c1, Nexp_constant c2 -> Nexp_constant (c1 * c2) + | _, _ -> Nexp_times (n1, n2) + end + | Nexp_minus (n1, n2) -> + begin + let (Nexp_aux (n1_simp, _) as n1) = nexp_simp n1 in + let (Nexp_aux (n2_simp, _) as n2) = nexp_simp n2 in + match n1_simp, n2_simp with + | Nexp_constant c1, Nexp_constant c2 -> Nexp_constant (c1 - c2) + | _, _ -> Nexp_minus (n1, n2) + end + | nexp -> nexp + +let mk_typ typ = Typ_aux (typ, Parse_ast.Unknown) +let mk_typ_arg arg = Typ_arg_aux (arg, Parse_ast.Unknown) +let mk_kid str = Kid_aux (Var ("'" ^ str), Parse_ast.Unknown) +let mk_infix_id str = Id_aux (DeIid str, Parse_ast.Unknown) + +let mk_id_typ id = Typ_aux (Typ_id id, Parse_ast.Unknown) + +let mk_ord ord_aux = Ord_aux (ord_aux, Parse_ast.Unknown) + +let int_typ = mk_id_typ (mk_id "int") +let nat_typ = mk_id_typ (mk_id "nat") +let unit_typ = mk_id_typ (mk_id "unit") +let bit_typ = mk_id_typ (mk_id "bit") +let real_typ = mk_id_typ (mk_id "real") +let app_typ id args = mk_typ (Typ_app (id, args)) +let atom_typ nexp = + mk_typ (Typ_app (mk_id "atom", [mk_typ_arg (Typ_arg_nexp (nexp_simp nexp))])) +let range_typ nexp1 nexp2 = + mk_typ (Typ_app (mk_id "range", [mk_typ_arg (Typ_arg_nexp (nexp_simp nexp1)); + mk_typ_arg (Typ_arg_nexp (nexp_simp nexp2))])) +let bool_typ = mk_id_typ (mk_id "bool") +let string_typ = mk_id_typ (mk_id "string") +let list_typ typ = mk_typ (Typ_app (mk_id "list", [mk_typ_arg (Typ_arg_typ typ)])) + +let vector_typ n m ord typ = + mk_typ (Typ_app (mk_id "vector", + [mk_typ_arg (Typ_arg_nexp (nexp_simp n)); + mk_typ_arg (Typ_arg_nexp (nexp_simp m)); + mk_typ_arg (Typ_arg_order ord); + mk_typ_arg (Typ_arg_typ typ)])) + +let exc_typ = mk_id_typ (mk_id "exception") + +let nconstant c = Nexp_aux (Nexp_constant c, Parse_ast.Unknown) +let nminus n1 n2 = Nexp_aux (Nexp_minus (n1, n2), Parse_ast.Unknown) +let nsum n1 n2 = Nexp_aux (Nexp_sum (n1, n2), Parse_ast.Unknown) +let ntimes n1 n2 = Nexp_aux (Nexp_times (n1, n2), Parse_ast.Unknown) +let npow2 n = Nexp_aux (Nexp_exp n, Parse_ast.Unknown) +let nvar kid = Nexp_aux (Nexp_var kid, Parse_ast.Unknown) +let nid id = Nexp_aux (Nexp_id id, Parse_ast.Unknown) + +let nc_eq n1 n2 = mk_nc (NC_fixed (n1, n2)) +let nc_neq n1 n2 = mk_nc (NC_not_equal (n1, n2)) +let nc_lteq n1 n2 = NC_aux (NC_bounded_le (n1, n2), Parse_ast.Unknown) +let nc_gteq n1 n2 = NC_aux (NC_bounded_ge (n1, n2), Parse_ast.Unknown) +let nc_lt n1 n2 = nc_lteq n1 (nsum n2 (nconstant 1)) +let nc_gt n1 n2 = nc_gteq n1 (nsum n2 (nconstant 1)) +let nc_and nc1 nc2 = mk_nc (NC_and (nc1, nc2)) +let nc_or nc1 nc2 = mk_nc (NC_or (nc1, nc2)) +let nc_true = mk_nc NC_true +let nc_false = mk_nc NC_false + +let mk_typschm typq typ = TypSchm_aux (TypSchm_ts (typq, typ), Parse_ast.Unknown) + +let mk_fexp id exp = FE_aux (FE_Fexp (id, exp), no_annot) +let mk_fexps fexps = FES_aux (FES_Fexps (fexps, false), no_annot) + +let mk_effect effs = + Effect_aux (Effect_set (List.map (fun be_aux -> BE_aux (be_aux, Parse_ast.Unknown)) effs), Parse_ast.Unknown) + +let no_effect = mk_effect [] + +let quant_items : typquant -> quant_item list = function + | TypQ_aux (TypQ_tq qis, _) -> qis + | TypQ_aux (TypQ_no_forall, _) -> [] + let rec map_exp_annot f (E_aux (exp, annot)) = E_aux (map_exp_annot_aux f exp, f annot) and map_exp_annot_aux f = function | E_block xs -> E_block (List.map (map_exp_annot f) xs) diff --git a/src/ast_util.mli b/src/ast_util.mli index 7580404d..95afa232 100644 --- a/src/ast_util.mli +++ b/src/ast_util.mli @@ -44,21 +44,82 @@ open Ast +val mk_id : string -> id +val mk_kid : string -> kid +val mk_ord : order_aux -> order val mk_nc : n_constraint_aux -> n_constraint val mk_nexp : nexp_aux -> nexp val mk_exp : unit exp_aux -> unit exp val mk_pat : unit pat_aux -> unit pat +val mk_lexp : unit lexp_aux -> unit lexp val mk_lit : lit_aux -> lit val mk_lit_exp : lit_aux -> unit exp val mk_funcl : id -> unit pat -> unit exp -> unit funcl val mk_fundef : (unit funcl) list -> unit def val mk_val_spec : val_spec_aux -> unit def +val mk_typschm : typquant -> typ -> typschm +val mk_fexp : id -> unit exp -> unit fexp +val mk_fexps : (unit fexp) list -> unit fexps val unaux_exp : 'a exp -> 'a exp_aux val inc_ord : order val dec_ord : order +(* Utilites for working with kinded_ids *) +val kopt_kid : kinded_id -> kid +val is_nat_kopt : kinded_id -> bool +val is_order_kopt : kinded_id -> bool +val is_typ_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 +val mk_id_typ : id -> typ + +(* Sail builtin types. *) +val int_typ : typ +val nat_typ : typ +val atom_typ : nexp -> typ +val range_typ : nexp -> nexp -> typ +val bit_typ : typ +val bool_typ : typ +val app_typ : id -> typ_arg list -> typ +val unit_typ : typ +val string_typ : typ +val real_typ : typ +val vector_typ : nexp -> nexp -> order -> typ -> typ +val list_typ : typ -> typ +val exc_typ : typ + +val no_effect : effect +val mk_effect : base_effect_aux list -> effect + +val nexp_simp : nexp -> nexp + +(* Utilities for building n-expressions *) +val nconstant : int -> nexp +val nminus : nexp -> nexp -> nexp +val nsum : nexp -> nexp -> nexp +val ntimes : nexp -> nexp -> nexp +val npow2 : nexp -> nexp +val nvar : kid -> nexp +val nid : id -> nexp (* NOTE: Nexp_id's don't do anything currently *) + +(* Numeric constraint builders *) +val nc_eq : nexp -> nexp -> n_constraint +val nc_neq : nexp -> nexp -> n_constraint +val nc_lteq : nexp -> nexp -> n_constraint +val nc_gteq : nexp -> nexp -> n_constraint +val nc_lt : nexp -> nexp -> n_constraint +val nc_gt : nexp -> nexp -> n_constraint +val nc_and : n_constraint -> n_constraint -> n_constraint +val nc_or : n_constraint -> n_constraint -> n_constraint +val nc_true : n_constraint +val nc_false : n_constraint + +val quant_items : typquant -> quant_item list + (* 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/initial_check.ml b/src/initial_check.ml index 8e5fd35f..d8d3e56e 100644 --- a/src/initial_check.ml +++ b/src/initial_check.ml @@ -1012,6 +1012,8 @@ let typschm_of_string order str = let (typschm, _, _) = to_ast_typschm initial_kind_env order typschm in typschm +let val_spec_of_string order id str = mk_val_spec (VS_val_spec (typschm_of_string order str, id)) + let val_spec_ids (Defs defs) = let val_spec_id (VS_aux (vs_aux, _)) = match vs_aux with @@ -1027,14 +1029,55 @@ let val_spec_ids (Defs defs) = in IdSet.of_list (vs_ids defs) +let quant_item_param = function + | QI_aux (QI_id kopt, _) when is_nat_kopt kopt -> [prepend_id "atom_" (id_of_kid (kopt_kid kopt))] + | QI_aux (QI_id kopt, _) when is_typ_kopt kopt -> [prepend_id "typ_" (id_of_kid (kopt_kid kopt))] + | _ -> [] +let quant_item_typ = function + | QI_aux (QI_id kopt, _) when is_nat_kopt kopt -> [atom_typ (nvar (kopt_kid kopt))] + | QI_aux (QI_id kopt, _) when is_typ_kopt kopt -> [mk_typ (Typ_var (kopt_kid kopt))] + | _ -> [] +let quant_item_arg = function + | QI_aux (QI_id kopt, _) when is_nat_kopt kopt -> [mk_typ_arg (Typ_arg_nexp (nvar (kopt_kid kopt)))] + | QI_aux (QI_id kopt, _) when is_typ_kopt kopt -> [mk_typ_arg (Typ_arg_typ (mk_typ (Typ_var (kopt_kid kopt))))] + | _ -> [] +let undefined_typschm id typq = + let qis = quant_items typq in + if qis = [] then + mk_typschm typq (mk_typ (Typ_fn (unit_typ, mk_typ (Typ_id id), mk_effect [BE_undef]))) + else + let arg_typ = mk_typ (Typ_tup (List.concat (List.map quant_item_typ qis))) in + let ret_typ = app_typ id (List.concat (List.map quant_item_arg qis)) in + mk_typschm typq (mk_typ (Typ_fn (arg_typ, ret_typ, mk_effect [BE_undef]))) + let generate_undefineds vs_ids (Defs defs) = + let gen_vs id str = + if (IdSet.mem id vs_ids) then [] else [val_spec_of_string dec_ord id str] + in + let undefined_builtins = List.concat + [gen_vs (mk_id "internal_pick") "forall 'a:Type. list('a) -> 'a effect {undef}"; + gen_vs (mk_id "undefined_bool") "unit -> bool effect {undef}"; + gen_vs (mk_id "undefined_bit") "unit -> bit effect {undef}"; + gen_vs (mk_id "undefined_int") "unit -> int effect {undef}"; + gen_vs (mk_id "undefined_range") "forall 'n 'm. (atom('n), atom('m)) -> range('n,'m) effect {undef}"; + (* FIXME: How to handle inc/dec order correctly? *) + gen_vs (mk_id "undefined_vector") "forall 'n 'm 'a:Type. (atom('n), atom('m), 'a) -> vector('n, 'm, dec,'a) effect {undef}"; + gen_vs (mk_id "undefined_unit") "unit -> unit effect {undef}"] + in let undefined_td = function | TD_enum (id, _, ids, _) when not (IdSet.mem (prepend_id "undefined_" id) vs_ids) -> let typschm = typschm_of_string dec_ord ("unit -> " ^ string_of_id id ^ " effect {undef}") in [mk_val_spec (VS_val_spec (typschm, prepend_id "undefined_" id)); mk_fundef [mk_funcl (prepend_id "undefined_" id) (mk_pat (P_lit (mk_lit L_unit))) - (mk_exp (E_lit (mk_lit L_undef)))]] + (mk_exp (E_app (mk_id "internal_pick", + [mk_exp (E_list (List.map (fun id -> mk_exp (E_id id)) ids))])))]] + | TD_record (id, _, typq, fields, _) when not (IdSet.mem (prepend_id "undefined_" id) vs_ids) -> + let pat = mk_pat (P_tup (quant_items typq |> List.map quant_item_param |> List.concat |> List.map (fun id -> mk_pat (P_id id)))) in + [mk_val_spec (VS_val_spec (undefined_typschm id typq, prepend_id "undefined_" id)); + mk_fundef [mk_funcl (prepend_id "undefined_" id) + pat + (mk_exp (E_record (mk_fexps (List.map (fun (_, id) -> mk_fexp id (mk_lit_exp L_undef)) fields))))]] | _ -> [] in let rec undefined_defs = function @@ -1044,9 +1087,28 @@ let generate_undefineds vs_ids (Defs defs) = def :: undefined_defs defs | [] -> [] in - Defs (undefined_defs defs) + Defs (undefined_builtins @ undefined_defs defs) + +let rec get_registers = function + | DEF_reg_dec (DEC_aux (DEC_reg (typ, id), _)) :: defs -> (typ, id) :: get_registers defs + | def :: defs -> get_registers defs + | [] -> [] + +let generate_initialize_registers vs_ids (Defs defs) = + let regs = get_registers defs in + let initialize_registers = + if IdSet.mem (mk_id "initialize_registers") vs_ids || regs = [] then [] + else + [val_spec_of_string dec_ord (mk_id "initialize_registers") "unit -> unit effect {undef, wreg}"; + mk_fundef [mk_funcl (mk_id "initialize_registers") + (mk_pat (P_lit (mk_lit L_unit))) + (mk_exp (E_block (List.map (fun (typ, id) -> mk_exp (E_assign (mk_lexp (LEXP_cast (typ, id)), mk_lit_exp L_undef))) regs)))]] + in + Defs (defs @ initialize_registers) + let process_ast order defs = let (ast, _, _) = to_ast Nameset.empty initial_kind_env order defs in let vs_ids = val_spec_ids ast in - generate_undefineds vs_ids ast + let ast = generate_undefineds vs_ids ast in + generate_initialize_registers vs_ids ast diff --git a/src/parse_ast.ml b/src/parse_ast.ml index 3951ab51..b259611d 100644 --- a/src/parse_ast.ml +++ b/src/parse_ast.ml @@ -288,6 +288,7 @@ exp_aux = (* Expression *) | E_try of exp * pexp list | E_return of exp | E_assert of exp * exp + | E_internal_let of exp * exp * exp and exp = E_aux of exp_aux * l diff --git a/src/rewriter.ml b/src/rewriter.ml index 21ea3cf5..3c4f8eb2 100644 --- a/src/rewriter.ml +++ b/src/rewriter.ml @@ -2146,7 +2146,7 @@ let rewrite_exp_lift_assign_intro rewriters ((E_aux (exp,((l,_) as annot))) as f | (E_aux(E_assign((LEXP_aux ((LEXP_id id | LEXP_cast (_,id)),_)) as le,e), ((l, Some (env,typ,eff)) as annot)) as exp)::exps -> (match Env.lookup_id id env with - | Unbound | Local _ -> + | Unbound -> let le' = rewriters.rewrite_lexp rewriters le in let e' = rewrite_base e in let exps' = walker exps in @@ -2417,6 +2417,11 @@ let rewrite_undefined = mk_exp (E_app (prepend_id "undefined_" id, [mk_lit_exp L_unit])) | Typ_app (id, args) -> mk_exp (E_app (prepend_id "undefined_" id, List.concat (List.map undefined_of_typ_args args))) + | Typ_var kid -> + (* FIXME: bit of a hack, need to add a restriction to how + polymorphic undefined can be in the type checker to + guarantee this always works. *) + mk_exp (E_id (prepend_id "typ_" (id_of_kid kid))) | Typ_fn _ -> assert false and undefined_of_typ_args (Typ_arg_aux (typ_arg_aux, _) as typ_arg) = match typ_arg_aux with @@ -2427,7 +2432,6 @@ let rewrite_undefined = let rewrite_e_aux (E_aux (e_aux, _) as exp) = match e_aux with | E_lit (L_aux (L_undef, l)) -> - print_endline ("Undefined: " ^ string_of_typ (typ_of exp)); check_exp (env_of exp) (undefined_of_typ (typ_of exp)) (typ_of exp) | _ -> exp in @@ -2455,10 +2459,15 @@ let rewrite_simple_types (Defs defs) = Typ_id (mk_id "int") | Typ_app (id, [_; _]) when Id.compare id (mk_id "range") = 0 -> Typ_id (mk_id "int") + | Typ_app (id, args) -> Typ_app (id, List.concat (List.map simple_typ_arg args)) | Typ_fn (typ1, typ2, effs) -> Typ_fn (simple_typ typ1, simple_typ typ2, effs) | Typ_tup typs -> Typ_tup (List.map simple_typ typs) | Typ_exist (_, _, Typ_aux (typ, l)) -> simple_typ_aux typ | typ_aux -> typ_aux + and simple_typ_arg (Typ_arg_aux (typ_arg_aux, l)) = + match typ_arg_aux with + | Typ_arg_typ typ -> [Typ_arg_aux (Typ_arg_typ (simple_typ typ), l)] + | _ -> [] in let simple_typschm (TypSchm_aux (TypSchm_ts (typq, typ), annot)) = TypSchm_aux (TypSchm_ts (simple_typquant typq, simple_typ typ), annot) @@ -3354,10 +3363,10 @@ let rewrite_defs_ocaml = [ rewrite_defs_remove_vector_concat; rewrite_constraint; rewrite_trivial_sizeof; - (* rewrite_sizeof; *) - (* rewrite_simple_types; *) - (* rewrite_overload_cast; *) - (* rewrite_defs_exp_lift_assign; *) + rewrite_sizeof; + rewrite_simple_types; + rewrite_overload_cast; + rewrite_defs_exp_lift_assign; (* rewrite_defs_exp_lift_assign *) (* rewrite_defs_separate_numbs *) ] diff --git a/src/sail.ml b/src/sail.ml index 081a414f..89f7c44c 100644 --- a/src/sail.ml +++ b/src/sail.ml @@ -159,6 +159,7 @@ let main() = (if !(opt_print_ocaml) then let ast_ocaml = rewrite_ast_ocaml ast in Pretty_print_sail.pp_defs stdout ast_ocaml; + Ocaml_backend.ocaml_pp_defs stdout ast_ocaml; if !(opt_libs_ocaml) = [] then output "" (Ocaml_out None) [out_name,ast_ocaml] else output "" (Ocaml_out (Some (List.hd !opt_libs_ocaml))) [out_name,ast_ocaml] diff --git a/src/type_check.ml b/src/type_check.ml index 9e7a1ab3..fb5f7d59 100644 --- a/src/type_check.ml +++ b/src/type_check.ml @@ -91,74 +91,6 @@ let orig_kid (Kid_aux (Var v, l) as kid) = with | Not_found -> kid -let mk_typ typ = Typ_aux (typ, Parse_ast.Unknown) -let mk_typ_arg arg = Typ_arg_aux (arg, Parse_ast.Unknown) -let mk_id str = Id_aux (Id str, Parse_ast.Unknown) -let mk_kid str = Kid_aux (Var ("'" ^ str), Parse_ast.Unknown) -let mk_infix_id str = Id_aux (DeIid str, Parse_ast.Unknown) - -let mk_id_typ id = Typ_aux (Typ_id id, Parse_ast.Unknown) - -let mk_ord ord_aux = Ord_aux (ord_aux, Parse_ast.Unknown) - -let rec nexp_simp (Nexp_aux (nexp, l)) = Nexp_aux (nexp_simp_aux nexp, l) -and nexp_simp_aux = function - | Nexp_minus (Nexp_aux (Nexp_sum (Nexp_aux (n1, _), Nexp_aux (Nexp_constant c1, _)), _), Nexp_aux (Nexp_constant c2, _)) when c1 = c2 -> - nexp_simp_aux n1 - | Nexp_sum (Nexp_aux (Nexp_minus (Nexp_aux (n1, _), Nexp_aux (Nexp_constant c1, _)), _), Nexp_aux (Nexp_constant c2, _)) when c1 = c2 -> - nexp_simp_aux n1 - | Nexp_sum (n1, n2) -> - begin - let (Nexp_aux (n1_simp, _) as n1) = nexp_simp n1 in - let (Nexp_aux (n2_simp, _) as n2) = nexp_simp n2 in - match n1_simp, n2_simp with - | Nexp_constant c1, Nexp_constant c2 -> Nexp_constant (c1 + c2) - | _, Nexp_neg n2 -> Nexp_minus (n1, n2) - | _, _ -> Nexp_sum (n1, n2) - end - | Nexp_times (n1, n2) -> - begin - let (Nexp_aux (n1_simp, _) as n1) = nexp_simp n1 in - let (Nexp_aux (n2_simp, _) as n2) = nexp_simp n2 in - match n1_simp, n2_simp with - | Nexp_constant c1, Nexp_constant c2 -> Nexp_constant (c1 * c2) - | _, _ -> Nexp_times (n1, n2) - end - | Nexp_minus (n1, n2) -> - begin - let (Nexp_aux (n1_simp, _) as n1) = nexp_simp n1 in - let (Nexp_aux (n2_simp, _) as n2) = nexp_simp n2 in - typ_debug ("SIMP: " ^ string_of_nexp n1 ^ " - " ^ string_of_nexp n2); - match n1_simp, n2_simp with - | Nexp_constant c1, Nexp_constant c2 -> Nexp_constant (c1 - c2) - | _, _ -> Nexp_minus (n1, n2) - end - | nexp -> nexp - -let int_typ = mk_id_typ (mk_id "int") -let nat_typ = mk_id_typ (mk_id "nat") -let unit_typ = mk_id_typ (mk_id "unit") -let bit_typ = mk_id_typ (mk_id "bit") -let real_typ = mk_id_typ (mk_id "real") -let app_typ id args = mk_typ (Typ_app (id, args)) -let atom_typ nexp = - mk_typ (Typ_app (mk_id "atom", [mk_typ_arg (Typ_arg_nexp (nexp_simp nexp))])) -let range_typ nexp1 nexp2 = - mk_typ (Typ_app (mk_id "range", [mk_typ_arg (Typ_arg_nexp (nexp_simp nexp1)); - mk_typ_arg (Typ_arg_nexp (nexp_simp nexp2))])) -let bool_typ = mk_id_typ (mk_id "bool") -let string_typ = mk_id_typ (mk_id "string") -let list_typ typ = mk_typ (Typ_app (mk_id "list", [mk_typ_arg (Typ_arg_typ typ)])) - -let vector_typ n m ord typ = - mk_typ (Typ_app (mk_id "vector", - [mk_typ_arg (Typ_arg_nexp (nexp_simp n)); - mk_typ_arg (Typ_arg_nexp (nexp_simp m)); - mk_typ_arg (Typ_arg_order ord); - mk_typ_arg (Typ_arg_typ typ)])) - -let exc_typ = mk_id_typ (mk_id "exception") - let is_range (Typ_aux (typ_aux, _)) = match typ_aux with | Typ_app (f, [Typ_arg_aux (Typ_arg_nexp n, _)]) @@ -173,25 +105,6 @@ let is_list (Typ_aux (typ_aux, _)) = when string_of_id f = "list" -> Some typ | _ -> None -let nconstant c = Nexp_aux (Nexp_constant c, Parse_ast.Unknown) -let nminus n1 n2 = Nexp_aux (Nexp_minus (n1, n2), Parse_ast.Unknown) -let nsum n1 n2 = Nexp_aux (Nexp_sum (n1, n2), Parse_ast.Unknown) -let ntimes n1 n2 = Nexp_aux (Nexp_times (n1, n2), Parse_ast.Unknown) -let npow2 n = Nexp_aux (Nexp_exp n, Parse_ast.Unknown) -let nvar kid = Nexp_aux (Nexp_var kid, Parse_ast.Unknown) -let nid id = Nexp_aux (Nexp_id id, Parse_ast.Unknown) - -let nc_eq n1 n2 = mk_nc (NC_fixed (n1, n2)) -let nc_neq n1 n2 = mk_nc (NC_not_equal (n1, n2)) -let nc_lteq n1 n2 = NC_aux (NC_bounded_le (n1, n2), Parse_ast.Unknown) -let nc_gteq n1 n2 = NC_aux (NC_bounded_ge (n1, n2), Parse_ast.Unknown) -let nc_lt n1 n2 = nc_lteq n1 (nsum n2 (nconstant 1)) -let nc_gt n1 n2 = nc_gteq n1 (nsum n2 (nconstant 1)) -let nc_and nc1 nc2 = mk_nc (NC_and (nc1, nc2)) -let nc_or nc1 nc2 = mk_nc (NC_or (nc1, nc2)) -let nc_true = mk_nc NC_true -let nc_false = mk_nc NC_false - let mk_lit l = E_aux (E_lit (L_aux (l, Parse_ast.Unknown)), (Parse_ast.Unknown, ())) let rec nc_negate (NC_aux (nc, _)) = @@ -211,10 +124,6 @@ let rec nc_negate (NC_aux (nc, _)) = (* Utilities for constructing effect sets *) -let mk_effect effs = - Effect_aux (Effect_set (List.map (fun be_aux -> BE_aux (be_aux, Parse_ast.Unknown)) effs), Parse_ast.Unknown) - -let no_effect = mk_effect [] module BESet = Set.Make(BE) @@ -246,10 +155,6 @@ let string_of_index_sort = function ^ string_of_list " & " (fun (x, y) -> string_of_nexp x ^ " <= " ^ string_of_nexp y) constraints ^ "}" -let quant_items : typquant -> quant_item list = function - | TypQ_aux (TypQ_tq qis, _) -> qis - | TypQ_aux (TypQ_no_forall, _) -> [] - let quant_split typq = let qi_kopt = function | QI_aux (QI_id kopt, _) -> [kopt] @@ -262,23 +167,6 @@ let quant_split typq = let qis = quant_items typq in List.concat (List.map qi_kopt qis), List.concat (List.map qi_nc qis) -let kopt_kid (KOpt_aux (kopt_aux, _)) = - match kopt_aux with - | KOpt_none kid | KOpt_kind (_, kid) -> kid - -let is_nat_kopt = function - | KOpt_aux (KOpt_kind (K_aux (K_kind [BK_aux (BK_nat, _)], _), _), _) -> true - | KOpt_aux (KOpt_none _, _) -> true - | _ -> false - -let is_order_kopt = function - | KOpt_aux (KOpt_kind (K_aux (K_kind [BK_aux (BK_order, _)], _), _), _) -> true - | _ -> false - -let is_typ_kopt = function - | KOpt_aux (KOpt_kind (K_aux (K_kind [BK_aux (BK_type, _)], _), _), _) -> true - | _ -> false - (**************************************************************************) (* 1. Substitutions *) (**************************************************************************) @@ -764,6 +652,7 @@ end = struct end let add_register id 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") else diff --git a/src/type_check.mli b/src/type_check.mli index e3b9b81b..fedf8788 100644 --- a/src/type_check.mli +++ b/src/type_check.mli @@ -151,68 +151,22 @@ val add_typquant : typquant -> Env.t -> Env.t not of this form. *) val orig_kid : kid -> kid -(* Some handy utility functions for constructing types. *) -val mk_typ : typ_aux -> typ -val mk_typ_arg : typ_arg_aux -> typ_arg -val mk_id : string -> id -val mk_id_typ : id -> typ - -val no_effect : effect -val mk_effect : base_effect_aux list -> effect - val union_effects : effect -> effect -> effect val equal_effects : effect -> effect -> bool -val nconstant : int -> nexp -val nminus : nexp -> nexp -> nexp -val nsum : nexp -> nexp -> nexp -val ntimes : nexp -> nexp -> nexp -val npow2 : nexp -> nexp -val nvar : kid -> nexp -val nid : id -> nexp (* NOTE: Nexp_id's don't do anything currently *) - -(* Numeric constraint builders *) -val nc_eq : nexp -> nexp -> n_constraint -val nc_neq : nexp -> nexp -> n_constraint -val nc_lteq : nexp -> nexp -> n_constraint -val nc_gteq : nexp -> nexp -> n_constraint -val nc_lt : nexp -> nexp -> n_constraint -val nc_gt : nexp -> nexp -> n_constraint -val nc_and : n_constraint -> n_constraint -> n_constraint -val nc_or : n_constraint -> n_constraint -> n_constraint -val nc_true : n_constraint -val nc_false : n_constraint - (* Negate a n_constraint. Note that there's no NC_not constructor, so this flips all the inequalites a the n_constraint leaves and uses de-morgans to switch and to or and vice versa. *) val nc_negate : n_constraint -> n_constraint -val is_nat_kopt : kinded_id -> bool -val is_order_kopt : kinded_id -> bool -val is_typ_kopt : kinded_id -> bool - -(* Sail builtin types. *) -val int_typ : typ -val nat_typ : typ -val atom_typ : nexp -> typ -val range_typ : nexp -> nexp -> typ -val bit_typ : typ -val bool_typ : typ -val unit_typ : typ -val string_typ : typ -val real_typ : typ -val vector_typ : nexp -> nexp -> order -> typ -> typ -val list_typ : typ -> typ -val exist_typ : (kid -> n_constraint) -> (kid -> typ) -> typ -val exc_typ : typ - (* Vector with default order. *) val dvector_typ : Env.t -> nexp -> nexp -> typ -> typ (* Vector of specific length with default order, i.e. lvector_typ env n bit_typ = bit[n]. *) val lvector_typ : Env.t -> nexp -> typ -> typ +val exist_typ : (kid -> n_constraint) -> (kid -> typ) -> typ + type tannot = (Env.t * typ * effect) option (* Strip the type annotations from an expression. *) |
