summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ast_util.ml48
-rw-r--r--src/ast_util.mli13
-rw-r--r--src/pretty_print_lem_new_tc.ml1385
-rw-r--r--src/rewriter_new_tc.ml304
-rw-r--r--src/rewriter_new_tc.mli1
-rw-r--r--src/type_check_new.ml29
-rw-r--r--src/type_check_new.mli2
7 files changed, 1596 insertions, 186 deletions
diff --git a/src/ast_util.ml b/src/ast_util.ml
index d8e1e7a6..3eb5ddf0 100644
--- a/src/ast_util.ml
+++ b/src/ast_util.ml
@@ -10,6 +10,7 @@
(* Christopher Pulte *)
(* Peter Sewell *)
(* Alasdair Armstrong *)
+(* Thomas Bauereiss *)
(* *)
(* All rights reserved. *)
(* *)
@@ -335,3 +336,50 @@ module Id = struct
| Id_aux (Id _, _), Id_aux (DeIid _, _) -> -1
| Id_aux (DeIid _, _), Id_aux (Id _, _) -> 1
end
+
+let rec is_number (Typ_aux (t,_)) =
+ match t with
+ | Typ_app (Id_aux (Id "range", _),_)
+ | Typ_app (Id_aux (Id "implicit", _),_)
+ | Typ_app (Id_aux (Id "atom", _),_) -> true
+ | _ -> false
+
+let rec is_vector_typ = function
+ | Typ_aux (Typ_app (Id_aux (Id "vector",_), [_;_;_;_]), _) -> true
+ | Typ_aux (Typ_app (Id_aux (Id "register",_), [Typ_arg_aux (Typ_arg_typ rtyp,_)]), _) ->
+ is_vector_typ rtyp
+ | _ -> false
+
+let typ_app_args_of = function
+ | Typ_aux (Typ_app (Id_aux (Id c,_), targs), l) ->
+ (c, List.map (fun (Typ_arg_aux (a,_)) -> a) targs, l)
+ | Typ_aux (_, l) -> raise (Reporting_basic.err_typ l "typ_app_args_of called on non-app type")
+
+let rec vector_typ_args_of typ = match typ_app_args_of typ with
+ | ("vector", [Typ_arg_nexp start; Typ_arg_nexp len; Typ_arg_order ord; Typ_arg_typ etyp], _) ->
+ (start, len, ord, etyp)
+ | ("register", [Typ_arg_typ rtyp], _) -> vector_typ_args_of rtyp
+ | (_, _, l) -> raise (Reporting_basic.err_typ l "vector_typ_args_of called on non-vector type")
+
+let is_order_inc = function
+ | Ord_aux (Ord_inc, _) -> true
+ | Ord_aux (Ord_dec, _) -> false
+ | Ord_aux (Ord_var _, l) ->
+ raise (Reporting_basic.err_unreachable l "is_order_inc called on vector with variable ordering")
+
+let is_bit_typ = function
+ | Typ_aux (Typ_id (Id_aux (Id "bit", _)), _) -> true
+ | _ -> false
+
+let is_bitvector_typ typ =
+ if is_vector_typ typ then
+ let (_,_,_,etyp) = vector_typ_args_of typ in
+ is_bit_typ etyp
+ else false
+
+let has_effect (Effect_aux (eff,_)) searched_for = match eff with
+ | Effect_set effs ->
+ List.exists (fun (BE_aux (be,_)) -> be = searched_for) effs
+ | Effect_var _ ->
+ raise (Reporting_basic.err_unreachable Parse_ast.Unknown
+ "has_effect called on effect variable")
diff --git a/src/ast_util.mli b/src/ast_util.mli
index 9d6c5653..8902c39c 100644
--- a/src/ast_util.mli
+++ b/src/ast_util.mli
@@ -10,6 +10,7 @@
(* Christopher Pulte *)
(* Peter Sewell *)
(* Alasdair Armstrong *)
+(* Thomas Bauereiss *)
(* *)
(* All rights reserved. *)
(* *)
@@ -94,3 +95,15 @@ module BE : sig
type t = base_effect
val compare : base_effect -> base_effect -> int
end
+
+val is_number : typ -> bool
+val is_vector_typ : typ -> bool
+val is_bit_typ : typ -> bool
+val is_bitvector_typ : typ -> bool
+
+val typ_app_args_of : typ -> string * typ_arg_aux list * Ast.l
+val vector_typ_args_of : typ -> nexp * nexp * order * typ
+
+val is_order_inc : order -> bool
+
+val has_effect : effect -> base_effect_aux -> bool
diff --git a/src/pretty_print_lem_new_tc.ml b/src/pretty_print_lem_new_tc.ml
new file mode 100644
index 00000000..443695d3
--- /dev/null
+++ b/src/pretty_print_lem_new_tc.ml
@@ -0,0 +1,1385 @@
+(**************************************************************************)
+(* Sail *)
+(* *)
+(* Copyright (c) 2013-2017 *)
+(* Kathyrn Gray *)
+(* Shaked Flur *)
+(* Stephen Kell *)
+(* Gabriel Kerneis *)
+(* Robert Norton-Wright *)
+(* Christopher Pulte *)
+(* Peter Sewell *)
+(* Thomas Bauereiss *)
+(* *)
+(* All rights reserved. *)
+(* *)
+(* This software was developed by the University of Cambridge Computer *)
+(* Laboratory as part of the Rigorous Engineering of Mainstream Systems *)
+(* (REMS) project, funded by EPSRC grant EP/K008528/1. *)
+(* *)
+(* Redistribution and use in source and binary forms, with or without *)
+(* modification, are permitted provided that the following conditions *)
+(* are met: *)
+(* 1. Redistributions of source code must retain the above copyright *)
+(* notice, this list of conditions and the following disclaimer. *)
+(* 2. Redistributions in binary form must reproduce the above copyright *)
+(* notice, this list of conditions and the following disclaimer in *)
+(* the documentation and/or other materials provided with the *)
+(* distribution. *)
+(* *)
+(* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' *)
+(* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *)
+(* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *)
+(* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR *)
+(* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *)
+(* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *)
+(* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF *)
+(* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND *)
+(* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, *)
+(* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT *)
+(* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF *)
+(* SUCH DAMAGE. *)
+(**************************************************************************)
+
+open Type_check_new
+open Ast
+open Ast_util
+open Rewriter_new_tc
+open Big_int
+open PPrint
+open Pretty_print_common
+
+(****************************************************************************
+ * PPrint-based sail-to-lem pprinter
+****************************************************************************)
+
+let print_to_from_interp_value = ref false
+let langlebar = string "<|"
+let ranglebar = string "|>"
+let anglebars = enclose langlebar ranglebar
+
+let fix_id name = match name with
+ | "assert"
+ | "lsl"
+ | "lsr"
+ | "asr"
+ | "type"
+ | "fun"
+ | "function"
+ | "raise"
+ | "try"
+ | "match"
+ | "with"
+ | "field"
+ | "LT"
+ | "GT"
+ | "EQ"
+ | "integer"
+ -> name ^ "'"
+ | _ -> name
+
+let is_number char =
+ char = '0' || char = '1' || char = '2' || char = '3' || char = '4' || char = '5' ||
+ char = '6' || char = '7' || char = '8' || char = '9'
+
+let doc_id_lem (Id_aux(i,_)) =
+ match i with
+ | Id i ->
+ (* this not the right place to do this, just a workaround *)
+ if i.[0] = '\'' then
+ string ((String.sub i 1 (String.length i - 1)) ^ "'")
+ else if is_number(i.[0]) then
+ string ("v" ^ i ^ "'")
+ else
+ string (fix_id i)
+ | DeIid x ->
+ (* add an extra space through empty to avoid a closing-comment
+ * token in case of x ending with star. *)
+ parens (separate space [colon; string x; empty])
+
+let doc_id_lem_type (Id_aux(i,_)) =
+ match i with
+ | Id("int") -> string "ii"
+ | Id("nat") -> string "ii"
+ | Id("option") -> string "maybe"
+ | Id i -> string (fix_id i)
+ | DeIid x ->
+ (* add an extra space through empty to avoid a closing-comment
+ * token in case of x ending with star. *)
+ parens (separate space [colon; string x; empty])
+
+let doc_id_lem_ctor (Id_aux(i,_)) =
+ match i with
+ | Id("bit") -> string "bitU"
+ | Id("int") -> string "integer"
+ | Id("nat") -> string "integer"
+ | Id("Some") -> string "Just"
+ | Id("None") -> string "Nothing"
+ | Id i -> string (fix_id (String.capitalize i))
+ | DeIid x ->
+ (* add an extra space through empty to avoid a closing-comment
+ * token in case of x ending with star. *)
+ separate space [colon; string (String.capitalize x); empty]
+
+let effectful_set =
+ List.exists
+ (fun (BE_aux (eff,_)) ->
+ match eff with
+ | BE_rreg | BE_wreg | BE_rmem | BE_rmemt | BE_wmem | BE_eamem
+ | BE_exmem | BE_wmv | BE_wmvt | BE_barr | BE_depend | BE_nondet
+ | BE_escape -> true
+ | _ -> false)
+
+let effectful (Effect_aux (eff,_)) =
+ match eff with
+ | Effect_var _ -> failwith "effectful: Effect_var not supported"
+ | Effect_set effs -> effectful_set effs
+
+let doc_typ_lem, doc_atomic_typ_lem =
+ (* following the structure of parser for precedence *)
+ let rec typ regtypes ty = fn_typ regtypes true ty
+ and typ' regtypes ty = fn_typ regtypes false ty
+ and fn_typ regtypes atyp_needed ((Typ_aux (t, _)) as ty) = match t with
+ | Typ_fn(arg,ret,efct) ->
+ (*let exc_typ = string "string" in*)
+ let ret_typ =
+ if effectful efct
+ then separate space [string "M";(*parens exc_typ;*) fn_typ regtypes true ret]
+ else separate space [fn_typ regtypes false ret] in
+ let tpp = separate space [tup_typ regtypes true arg; arrow;ret_typ] in
+ (* once we have proper excetions we need to know what the exceptions type is *)
+ if atyp_needed then parens tpp else tpp
+ | _ -> tup_typ regtypes atyp_needed ty
+ and tup_typ regtypes atyp_needed ((Typ_aux (t, _)) as ty) = match t with
+ | Typ_tup typs ->
+ let tpp = separate_map (space ^^ star ^^ space) (app_typ regtypes false) typs in
+ if atyp_needed then parens tpp else tpp
+ | _ -> app_typ regtypes atyp_needed ty
+ and app_typ regtypes atyp_needed ((Typ_aux (t, _)) as ty) = match t with
+ | Typ_app(Id_aux (Id "vector", _), [
+ Typ_arg_aux (Typ_arg_nexp n, _);
+ Typ_arg_aux (Typ_arg_nexp m, _);
+ Typ_arg_aux (Typ_arg_order ord, _);
+ Typ_arg_aux (Typ_arg_typ elem_typ, _)]) ->
+ let tpp = match elem_typ with
+ | Typ_aux (Typ_id (Id_aux (Id "bit",_)),_) ->
+ let len = match m with
+ | (Nexp_aux(Nexp_constant i,_)) -> string "ty" ^^ doc_int i
+ | _ -> doc_nexp m in
+ string "bitvector" ^^ space ^^ len
+ | _ -> string "vector" ^^ space ^^ typ regtypes elem_typ in
+ if atyp_needed then parens tpp else tpp
+ | Typ_app(Id_aux (Id "register", _), [Typ_arg_aux (Typ_arg_typ etyp, _)]) ->
+ (* TODO: Better distinguish register names and contents?
+ The former are represented in the Lem library using a type
+ "register" (without parameters), the latter just using the content
+ type (e.g. "bitvector ty64"). We assume the latter is meant here
+ and drop the "register" keyword. *)
+ fn_typ regtypes atyp_needed etyp
+ | Typ_app(Id_aux (Id "range", _),_) ->
+ (string "integer")
+ | Typ_app(Id_aux (Id "implicit", _),_) ->
+ (string "integer")
+ | Typ_app(Id_aux (Id "atom", _), [Typ_arg_aux(Typ_arg_nexp n,_)]) ->
+ (string "integer")
+ | Typ_app(id,args) ->
+ let tpp = (doc_id_lem_type id) ^^ space ^^ (separate_map space (doc_typ_arg_lem regtypes) args) in
+ if atyp_needed then parens tpp else tpp
+ | _ -> atomic_typ regtypes atyp_needed ty
+ and atomic_typ regtypes atyp_needed ((Typ_aux (t, _)) as ty) = match t with
+ | Typ_id (Id_aux (Id "bool",_)) -> string "bitU"
+ | Typ_id (Id_aux (Id "boolean",_)) -> string "bitU"
+ | Typ_id (Id_aux (Id "bit",_)) -> string "bitU"
+ | Typ_id (id) ->
+ if List.exists ((=) (string_of_id id)) regtypes
+ then string "register"
+ else doc_id_lem_type id
+ | Typ_var v -> doc_var v
+ | Typ_wild -> underscore
+ | Typ_app _ | Typ_tup _ | Typ_fn _ ->
+ (* exhaustiveness matters here to avoid infinite loops
+ * if we add a new Typ constructor *)
+ let tpp = typ regtypes ty in
+ if atyp_needed then parens tpp else tpp
+ and doc_typ_arg_lem regtypes (Typ_arg_aux(t,_)) = match t with
+ | Typ_arg_typ t -> app_typ regtypes true t
+ | Typ_arg_nexp n -> empty
+ | Typ_arg_order o -> empty
+ | Typ_arg_effect e -> empty
+ in typ', atomic_typ
+
+let doc_tannot_lem regtypes eff typ =
+ let ta = doc_typ_lem regtypes typ in
+ if eff then string " : M " ^^ parens ta
+ else string " : " ^^ ta
+
+(* doc_lit_lem gets as an additional parameter the type information from the
+ * expression around it: that's a hack, but how else can we distinguish between
+ * undefined values of different types ? *)
+let doc_lit_lem in_pat (L_aux(lit,l)) a =
+ utf8string (match lit with
+ | L_unit -> "()"
+ | L_zero -> "B0"
+ | L_one -> "B1"
+ | L_false -> "B0"
+ | L_true -> "B1"
+ | L_num i ->
+ let ipp = string_of_int i in
+ if in_pat then "("^ipp^":nn)"
+ else if i < 0 then "((0"^ipp^"):ii)"
+ else "("^ipp^":ii)"
+ | L_hex n -> failwith "Shouldn't happen" (*"(num_to_vec " ^ ("0x" ^ n) ^ ")" (*shouldn't happen*)*)
+ | L_bin n -> failwith "Shouldn't happen" (*"(num_to_vec " ^ ("0b" ^ n) ^ ")" (*shouldn't happen*)*)
+ | L_undef ->
+ (match a with
+ | Some (_, Typ_aux (t,_), _) ->
+ (match t with
+ | Typ_id (Id_aux (Id "bit", _))
+ | Typ_app (Id_aux (Id "register", _),_) -> "UndefinedRegister 0"
+ | Typ_id (Id_aux (Id "string", _)) -> "\"\""
+ | _ -> "(failwith \"undefined value of unsupported type\")")
+ | _ -> "(failwith \"undefined value of unsupported type\")")
+ | L_string s -> "\"" ^ s ^ "\"")
+
+(* typ_doc is the doc for the type being quantified *)
+
+let doc_typquant_lem (TypQ_aux(tq,_)) typ_doc = typ_doc
+
+let doc_typschm_lem regtypes (TypSchm_aux(TypSchm_ts(tq,t),_)) =
+ (doc_typquant_lem tq (doc_typ_lem regtypes t))
+
+let is_ctor env id = match Env.lookup_id id env with
+| Enum _ | Union _ -> true
+| _ -> false
+
+(*Note: vector concatenation, literal vectors, indexed vectors, and record should
+ be removed prior to pp. The latter two have never yet been seen
+*)
+let rec doc_pat_lem regtypes apat_needed (P_aux (p,(l,annot)) as pa) = match p with
+ | P_app(id, ((_ :: _) as pats)) ->
+ (match annot with
+ | Some (env, _, _) when (is_ctor env id) ->
+ let ppp = doc_unop (doc_id_lem_ctor id)
+ (parens (separate_map comma (doc_pat_lem regtypes true) pats)) in
+ if apat_needed then parens ppp else ppp
+ | _ -> empty)
+ | P_app(id,[]) ->
+ (match annot with
+ | Some (env, _, _) when (is_ctor env id) -> doc_id_lem_ctor id
+ | _ -> empty)
+ | P_lit lit -> doc_lit_lem true lit annot
+ | P_wild -> underscore
+ | P_id id ->
+ begin match id with
+ | Id_aux (Id "None",_) -> string "Nothing" (* workaround temporary issue *)
+ | _ -> doc_id_lem id end
+ | P_as(p,id) -> parens (separate space [doc_pat_lem regtypes true p; string "as"; doc_id_lem id])
+ | P_typ(typ,p) -> doc_op colon (doc_pat_lem regtypes true p) (doc_typ_lem regtypes typ)
+ | P_vector pats ->
+ let ppp =
+ (separate space)
+ [string "Vector";brackets (separate_map semi (doc_pat_lem regtypes true) pats);underscore;underscore] in
+ if apat_needed then parens ppp else ppp
+ | P_vector_concat pats ->
+ let ppp =
+ (separate space)
+ [string "Vector";parens (separate_map (string "::") (doc_pat_lem regtypes true) pats);underscore;underscore] in
+ if apat_needed then parens ppp else ppp
+ | P_tup pats ->
+ (match pats with
+ | [p] -> doc_pat_lem regtypes apat_needed p
+ | _ -> parens (separate_map comma_sp (doc_pat_lem regtypes false) pats))
+ | P_list pats -> brackets (separate_map semi (doc_pat_lem regtypes false) pats) (*Never seen but easy in lem*)
+ | P_record (_,_) | P_vector_indexed _ -> empty (* TODO *)
+
+let rec contains_bitvector_typ (Typ_aux (t,_) as typ) = match t with
+ | Typ_tup ts -> List.exists contains_bitvector_typ ts
+ | Typ_app (_, targs) -> is_bitvector_typ typ || List.exists contains_bitvector_typ_arg targs
+ | Typ_fn (t1,t2,_) -> contains_bitvector_typ t1 || contains_bitvector_typ t2
+ | _ -> false
+and contains_bitvector_typ_arg (Typ_arg_aux (targ, _)) = match targ with
+ | Typ_arg_typ t -> contains_bitvector_typ t
+ | _ -> false
+
+let const_nexp (Nexp_aux (nexp,_)) = match nexp with
+ | Nexp_constant _ -> true
+ | _ -> false
+
+(* Check for variables in types that would be pretty-printed.
+ In particular, in case of vector types, only the element type and the
+ length argument are checked for variables, and the latter only if it is
+ a bitvector; for other types of vectors, the length is not pretty-printed
+ in the type, and the start index is never pretty-printed in vector types. *)
+let rec contains_t_pp_var (Typ_aux (t,a) as typ) = match t with
+ | Typ_wild -> true
+ | Typ_id _ -> false
+ | Typ_var _ -> true
+ | Typ_fn (t1,t2,_) -> contains_t_pp_var t1 || contains_t_pp_var t2
+ | Typ_tup ts -> List.exists contains_t_pp_var ts
+ | Typ_app (c,targs) ->
+ if is_bitvector_typ typ then
+ let (_,length,_,_) = vector_typ_args_of typ in
+ not (const_nexp ((*normalize_nexp*) length))
+ else List.exists contains_t_arg_pp_var targs
+and contains_t_arg_pp_var (Typ_arg_aux (targ, _)) = match targ with
+ | Typ_arg_typ t -> contains_t_pp_var t
+ | Typ_arg_nexp nexp -> not (const_nexp ((*normalize_nexp*) nexp))
+ | _ -> false
+
+let prefix_recordtype = true
+let report = Reporting_basic.err_unreachable
+let doc_exp_lem, doc_let_lem =
+ let rec top_exp regtypes (aexp_needed : bool) (E_aux (e, (l,annot)) as full_exp) =
+ let expY = top_exp regtypes true in
+ let expN = top_exp regtypes false in
+ let expV = top_exp regtypes in
+ match e with
+ | E_assign((LEXP_aux(le_act,tannot) as le), e) ->
+ (* can only be register writes *)
+ let t = typ_of_annot tannot in
+ (match le_act (*, t, tag*) with
+ | LEXP_vector_range (le,e2,e3) ->
+ (match le with
+ | LEXP_aux (LEXP_field (le,id), lannot) ->
+ if is_bit_typ (typ_of_annot lannot) then
+ raise (report l "indexing a register's (single bit) bitfield not supported")
+ else
+ (prefix 2 1)
+ (string "write_reg_field_range")
+ (align (doc_lexp_deref_lem regtypes le ^^ space^^
+ string_lit (doc_id_lem id) ^/^ expY e2 ^/^ expY e3 ^/^ expY e))
+ | _ ->
+ (prefix 2 1)
+ (string "write_reg_range")
+ (align (doc_lexp_deref_lem regtypes le ^^ space ^^ expY e2 ^/^ expY e3 ^/^ expY e))
+ )
+ | LEXP_vector (le,e2) when is_bit_typ t ->
+ (match le with
+ | LEXP_aux (LEXP_field (le,id), lannot) ->
+ if is_bit_typ (typ_of_annot lannot) then
+ raise (report l "indexing a register's (single bit) bitfield not supported")
+ else
+ (prefix 2 1)
+ (string "write_reg_field_bit")
+ (align (doc_lexp_deref_lem regtypes le ^^ space ^^ doc_id_lem id ^/^ expY e2 ^/^ expY e))
+ | _ ->
+ (prefix 2 1)
+ (string "write_reg_bit")
+ (doc_lexp_deref_lem regtypes le ^^ space ^^ expY e2 ^/^ expY e)
+ )
+ | LEXP_field (le,id) when is_bit_typ t ->
+ (prefix 2 1)
+ (string "write_reg_bitfield")
+ (doc_lexp_deref_lem regtypes le ^^ space ^^ string_lit(doc_id_lem id) ^/^ expY e)
+ | LEXP_field (le,id) ->
+ (prefix 2 1)
+ (string "write_reg_field")
+ (doc_lexp_deref_lem regtypes le ^^ space ^^
+ string_lit(doc_id_lem id) ^/^ expY e)
+ (* | (LEXP_id id | LEXP_cast (_,id)), t, Alias alias_info ->
+ (match alias_info with
+ | Alias_field(reg,field) ->
+ let f = match t with
+ | (Tid "bit" | Tabbrev (_,{t=Tid "bit"})) ->
+ string "write_reg_bitfield"
+ | _ -> string "write_reg_field" in
+ (prefix 2 1)
+ f
+ (separate space [string reg;string_lit(string field);expY e])
+ | Alias_pair(reg1,reg2) ->
+ string "write_two_regs" ^^ space ^^ string reg1 ^^ space ^^
+ string reg2 ^^ space ^^ expY e) *)
+ | _ ->
+ (prefix 2 1) (string "write_reg") (doc_lexp_deref_lem regtypes le ^/^ expY e))
+ | E_vector_append(le,re) ->
+ let t = typ_of_annot (l,annot) in
+ let (call,ta,aexp_needed) =
+ if is_bitvector_typ t then
+ if not (contains_t_pp_var t)
+ then ("bitvector_concat", doc_tannot_lem regtypes false t, true)
+ else ("bitvector_concat", empty, aexp_needed)
+ else ("vector_concat",empty,aexp_needed) in
+ let epp =
+ align (group (separate space [string call;expY le;expY re])) ^^ ta in
+ if aexp_needed then parens epp else epp
+ | E_cons(le,re) -> doc_op (group (colon^^colon)) (expY le) (expY re)
+ | E_if(c,t,e) ->
+ let (E_aux (_,(_,cannot))) = c in
+ let epp =
+ separate space [string "if";group (align (string "bitU_to_bool" ^//^ group (expY c)))] ^^
+ break 1 ^^
+ (prefix 2 1 (string "then") (expN t)) ^^ (break 1) ^^
+ (prefix 2 1 (string "else") (expN e)) in
+ if aexp_needed then parens (align epp) else epp
+ | E_for(id,exp1,exp2,exp3,(Ord_aux(order,_)),exp4) ->
+ raise (report l "E_for should have been removed till now")
+ | E_let(leb,e) ->
+ let epp = let_exp regtypes leb ^^ space ^^ string "in" ^^ hardline ^^ expN e in
+ if aexp_needed then parens epp else epp
+ | E_app(f,args) ->
+ begin match f with
+ (* temporary hack to make the loop body a function of the temporary variables *)
+ | Id_aux ((Id (("foreach_inc" | "foreach_dec" |
+ "foreachM_inc" | "foreachM_dec" ) as loopf),_)) ->
+ let [id;indices;body;e5] = args in
+ let varspp = match e5 with
+ | E_aux (E_tuple vars,_) ->
+ let vars = List.map (fun (E_aux (E_id (Id_aux (Id name,_)),_)) -> string name) vars in
+ begin match vars with
+ | [v] -> v
+ | _ -> parens (separate comma vars) end
+ | E_aux (E_id (Id_aux (Id name,_)),_) ->
+ string name
+ | E_aux (E_lit (L_aux (L_unit,_)),_) ->
+ string "_" in
+ parens (
+ (prefix 2 1)
+ ((separate space) [string loopf;group (expY indices);expY e5])
+ (parens
+ (prefix 1 1 (separate space [string "fun";expY id;varspp;arrow]) (expN body))
+ )
+ )
+ | Id_aux (Id "append",_) ->
+ let [e1;e2] = args in
+ let epp = align (expY e1 ^^ space ^^ string "++" ^//^ expY e2) in
+ if aexp_needed then parens (align epp) else epp
+ | Id_aux (Id "slice_raw",_) ->
+ let [e1;e2;e3] = args in
+ let t1 = typ_of e1 in
+ let eff1 = effect_of e1 in
+ let call = if is_bitvector_typ t1 then "bvslice_raw" else "slice_raw" in
+ let epp = separate space [string call;expY e1;expY e2;expY e3] in
+ let (taepp,aexp_needed) =
+ let t = typ_of full_exp in
+ let eff = effect_of full_exp in
+ if contains_bitvector_typ t && not (contains_t_pp_var t)
+ then (align epp ^^ (doc_tannot_lem regtypes (effectful eff) t), true)
+ else (epp, aexp_needed) in
+ if aexp_needed then parens (align taepp) else taepp
+ | Id_aux (Id "length",_) ->
+ let [arg] = args in
+ let targ = typ_of arg in
+ let call = if is_bitvector_typ targ then "bvlength" else "length" in
+ let epp = separate space [string call;expY arg] in
+ if aexp_needed then parens (align epp) else epp
+ | Id_aux (Id "bool_not", _) ->
+ let [a] = args in
+ let epp = align (string "~" ^^ expY a) in
+ if aexp_needed then parens (align epp) else epp
+ | _ ->
+ begin match annot with
+ | Some (env, _, _) when (is_ctor env f) ->
+ let argpp a_needed arg =
+ let t = typ_of arg in
+ if is_vector_typ t then
+ let call =
+ if is_bitvector_typ t then "reset_bitvector_start"
+ else "reset_vector_start" in
+ let epp = concat [string call;space;expY arg] in
+ if a_needed then parens epp else epp
+ else expV a_needed arg in
+ let epp =
+ match args with
+ | [] -> doc_id_lem_ctor f
+ | [arg] -> doc_id_lem_ctor f ^^ space ^^ argpp true arg
+ | _ ->
+ doc_id_lem_ctor f ^^ space ^^
+ parens (separate_map comma (argpp false) args) in
+ if aexp_needed then parens (align epp) else epp
+ | _ ->
+ let call = (*match annot with
+ | Base(_,External (Some n),_,_,_,_) -> string n
+ | _ ->*) doc_id_lem f in
+ let argpp a_needed arg =
+ let t = typ_of arg in
+ if is_vector_typ t then
+ let call =
+ if is_bitvector_typ t then "reset_bitvector_start"
+ else "reset_vector_start" in
+ let epp = concat [string call;space;expY arg] in
+ if a_needed then parens epp else epp
+ else expV a_needed arg in
+ let argspp = match args with
+ | [arg] -> argpp true arg
+ | args -> parens (align (separate_map (comma ^^ break 0) (argpp false) args)) in
+ let epp = align (call ^//^ argspp) in
+ let (taepp,aexp_needed) =
+ let t = typ_of full_exp in
+ let eff = effect_of full_exp in
+ if contains_bitvector_typ t && not (contains_t_pp_var t)
+ then (align epp ^^ (doc_tannot_lem regtypes (effectful eff) t), true)
+ else (epp, aexp_needed) in
+ if aexp_needed then parens (align taepp) else taepp
+ end
+ end
+ | E_vector_access (v,e) ->
+ let eff = effect_of full_exp in
+ let epp =
+ if has_effect eff BE_rreg then
+ separate space [string "read_reg_bit";expY v;expY e]
+ else
+ let tv = typ_of v in
+ let call = if is_bitvector_typ tv then "bvaccess" else "access" in
+ separate space [string call;expY v;expY e] in
+ if aexp_needed then parens (align epp) else epp
+ | E_vector_subrange (v,e1,e2) ->
+ let t = typ_of full_exp in
+ let eff = effect_of full_exp in
+ let (epp,aexp_needed) =
+ if has_effect eff BE_rreg then
+ let epp = align (string "read_reg_range" ^^ space ^^ expY v ^//^ expY e1 ^//^ expY e2) in
+ if contains_bitvector_typ t && not (contains_t_pp_var t)
+ then (epp ^^ doc_tannot_lem regtypes true t, true)
+ else (epp, aexp_needed)
+ else
+ if is_bitvector_typ t then
+ let bepp = string "bvslice" ^^ space ^^ expY v ^//^ expY e1 ^//^ expY e2 in
+ if not (contains_t_pp_var t)
+ then (bepp ^^ doc_tannot_lem regtypes false t, true)
+ else (bepp, aexp_needed)
+ else (string "slice" ^^ space ^^ expY v ^//^ expY e1 ^//^ expY e2, aexp_needed) in
+ if aexp_needed then parens (align epp) else epp
+ | E_field((E_aux(_,(l,fannot)) as fexp),id) ->
+ let ft = typ_of_annot (l,fannot) in
+ (match fannot with
+ | Some(env, (Typ_aux (Typ_id tid, _)), _) when Env.is_regtyp tid env ->
+ let t = typ_of full_exp in
+ let field_f = string
+ (if is_bit_typ t
+ then "read_reg_bitfield"
+ else "read_reg_field") in
+ let (ta,aexp_needed) =
+ if contains_bitvector_typ t && not (contains_t_pp_var t)
+ then (doc_tannot_lem regtypes true t, true)
+ else (empty, aexp_needed) in
+ let epp = field_f ^^ space ^^ (expY fexp) ^^ space ^^ string_lit (doc_id_lem id) in
+ if aexp_needed then parens (align epp ^^ ta) else (epp ^^ ta)
+ | Some(env, (Typ_aux (Typ_id tid, _)), _) when Env.is_record tid env ->
+ let fname =
+ if prefix_recordtype
+ then (string (string_of_id tid ^ "_")) ^^ doc_id_lem id
+ else doc_id_lem id in
+ expY fexp ^^ dot ^^ fname
+ | _ ->
+ raise (report l "E_field expression with no register or record type"))
+ | E_block [] -> string "()"
+ | E_block exps -> raise (report l "Blocks should have been removed till now.")
+ | E_nondet exps -> raise (report l "Nondet blocks not supported.")
+ | E_id id ->
+ let t = typ_of full_exp in
+ (match annot with
+ | Some (env, Typ_aux (Typ_id tid, _), eff) when Env.is_regtyp tid env ->
+ if has_effect eff BE_rreg then
+ let epp = separate space [string "read_reg";doc_id_lem id] in
+ if contains_bitvector_typ t && not (contains_t_pp_var t)
+ then parens (epp ^^ doc_tannot_lem regtypes true t)
+ else epp
+ else
+ doc_id_lem id
+ | Some (env, _, _) when (is_ctor env id) -> doc_id_lem_ctor id
+ (*| Base((_,t),Alias alias_info,_,eff,_,_) ->
+ (match alias_info with
+ | Alias_field(reg,field) ->
+ let call = match t.t with
+ | Tid "bit" | Tabbrev (_,{t=Tid "bit"}) -> "read_reg_bitfield"
+ | _ -> "read_reg_field" in
+ let ta =
+ if contains_bitvector_typ t && not (contains_t_pp_var t)
+ then doc_tannot_lem regtypes true t else empty in
+ let epp = separate space [string call;string reg;string_lit(string field)] ^^ ta in
+ if aexp_needed then parens (align epp) else epp
+ | Alias_pair(reg1,reg2) ->
+ let (call,ta) =
+ if has_effect eff BE_rreg then
+ let ta =
+ if contains_bitvector_typ t && not (contains_t_pp_var t)
+ then doc_tannot_lem regtypes true t else empty in
+ ("read_two_regs", ta)
+ else
+ ("RegisterPair", empty) in
+ let epp = separate space [string call;string reg1;string reg2] ^^ ta in
+ if aexp_needed then parens (align epp) else epp
+ | Alias_extract(reg,start,stop) ->
+ let epp =
+ if start = stop then
+ separate space [string "read_reg_bit";string reg;doc_int start]
+ else
+ let ta =
+ if contains_bitvector_typ t && not (contains_t_pp_var t)
+ then doc_tannot_lem regtypes true t else empty in
+ separate space [string "read_reg_range";string reg;doc_int start;doc_int stop] ^^ ta in
+ if aexp_needed then parens (align epp) else epp
+ )*)
+ | _ -> doc_id_lem id)
+ | E_lit lit -> doc_lit_lem false lit annot
+ | E_cast(typ,e) ->
+ if is_vector_typ typ then
+ let (start,_,_,_) = vector_typ_args_of typ in
+ let call =
+ if is_bitvector_typ typ then "set_bitvector_start"
+ else "set_vector_start" in
+ let epp = (concat [string call;space;doc_nexp start]) ^//^
+ expY e in
+ if aexp_needed then parens epp else epp
+ else
+ expV aexp_needed e (*
+ (match annot with
+ | Base((_,t),External _,_,_,_,_) ->
+ (* TODO: Does this case still exist with the new type checker? *)
+ let epp = string "read_reg" ^^ space ^^ expY e in
+ if contains_bitvector_typ t && not (contains_t_pp_var t)
+ then parens (epp ^^ doc_tannot_lem regtypes true t) else epp
+ | Base((_,t),_,_,_,_,_) ->
+ (match typ with
+ | Typ_app (Id_aux (Id "vector",_), [Typ_arg_aux (Typ_arg_nexp(Nexp_aux (Nexp_constant i,_)),_);_;_;_]) ->
+ let call =
+ if is_bitvector_typ t then "set_bitvector_start"
+ else "set_vector_start" in
+ let epp = (concat [string call;space;string (string_of_int i)]) ^//^
+ expY e in
+ if aexp_needed then parens epp else epp
+ (*
+ | Typ_var (Kid_aux (Var "length",_)) ->
+ (* TODO: Does this case still exist with the new type checker? *)
+ let call =
+ if is_bitvector_typ t then "set_bitvector_start_to_length"
+ else "set_vector_start_to_length" in
+ let epp = (string call) ^//^ expY e in
+ if aexp_needed then parens epp else epp
+ *)
+ | _ ->
+ expV aexp_needed e)) (*(parens (doc_op colon (group (expY e)) (doc_typ_lem typ)))) *)
+ *)
+ | E_tuple exps ->
+ (match exps with (*
+ | [e] -> expV aexp_needed e *)
+ | _ -> parens (separate_map comma expN exps))
+ | E_record(FES_aux(FES_Fexps(fexps,_),_)) ->
+ let recordtyp = match annot with
+ | Some (env, Typ_aux (Typ_id tid,_), _) when Env.is_record tid env ->
+ tid
+ | _ -> raise (report l "cannot get record type") in
+ let epp = anglebars (space ^^ (align (separate_map
+ (semi_sp ^^ break 1)
+ (doc_fexp regtypes recordtyp) fexps)) ^^ space) in
+ if aexp_needed then parens epp else epp
+ | E_record_update(e,(FES_aux(FES_Fexps(fexps,_),_))) ->
+ let recordtyp = match annot with
+ | Some (env, Typ_aux (Typ_id tid,_), _) when Env.is_record tid env ->
+ tid
+ | _ -> raise (report l "cannot get record type") in
+ anglebars (doc_op (string "with") (expY e) (separate_map semi_sp (doc_fexp regtypes recordtyp) fexps))
+ | E_vector exps ->
+ let t = typ_of full_exp in
+ let (start, len, order, etyp) =
+ if is_vector_typ t then vector_typ_args_of t
+ else raise (Reporting_basic.err_unreachable l "E_vector of non-vector type") in
+ (*match annot with
+ | Base((_,t),_,_,_,_,_) ->
+ match t.t with
+ | Tapp("vector", [TA_nexp start; TA_nexp len; TA_ord order; TA_typ etyp])
+ | Tabbrev(_,{t= Tapp("vector", [TA_nexp start; TA_nexp len; TA_ord order; TA_typ etyp])}) ->*)
+ let dir,dir_out = if is_order_inc order then (true,"true") else (false, "false") in
+ let start = match start with
+ | Nexp_aux (Nexp_constant i, _) -> string_of_int i
+ | _ -> if dir then "0" else string_of_int (List.length exps) in
+ let expspp =
+ match exps with
+ | [] -> empty
+ | e :: es ->
+ let (expspp,_) =
+ List.fold_left
+ (fun (pp,count) e ->
+ (pp ^^ semi ^^ (if count = 20 then break 0 else empty) ^^
+ expN e),
+ if count = 20 then 0 else count + 1)
+ (expN e,0) es in
+ align (group expspp) in
+ let epp =
+ group (separate space [string "Vector"; brackets expspp;string start;string dir_out]) in
+ let (epp,aexp_needed) =
+ if is_bit_typ etyp then
+ let bepp = string "vec_to_bvec" ^^ space ^^ parens (align epp) in
+ if contains_t_pp_var t
+ then (bepp, aexp_needed)
+ else (bepp ^^ doc_tannot_lem regtypes false t, true)
+ else (epp,aexp_needed) in
+ if aexp_needed then parens (align epp) else epp
+ (* *)
+ | E_vector_indexed (iexps, (Def_val_aux (default,(dl,dannot)))) ->
+ let t = typ_of full_exp in
+ let (start, len, order, etyp) =
+ if is_vector_typ t then vector_typ_args_of t
+ else raise (Reporting_basic.err_unreachable l "E_vector_indexed of non-vector type") in
+ let dir,dir_out = if is_order_inc order then (true,"true") else (false, "false") in
+ let start = match start with
+ | Nexp_aux (Nexp_constant i, _) -> string_of_int i
+ | _ -> if dir then "0" else string_of_int (List.length iexps) in
+ let size = match len with
+ | Nexp_aux (Nexp_constant i, _)-> string_of_int i
+ | Nexp_aux (Nexp_exp (Nexp_aux (Nexp_constant i, _)), _) ->
+ string_of_int (Util.power 2 i)
+ | _ ->
+ raise (Reporting_basic.err_unreachable l
+ "trying to pretty-print indexed vector without constant size") in
+ let default_string =
+ match default with
+ | Def_val_empty ->
+ if is_bitvector_typ t then string "BU"
+ else failwith "E_vector_indexed of non-bitvector type without default argument"
+ | Def_val_dec e ->
+ (*let (Base ((_,{t = t}),_,_,_,_,_)) = dannot in
+ match t with
+ | Tapp ("register",
+ [TA_typ ({t = rt})]) ->
+ (* TODO: Does this case still occur with the new type checker? *)
+ let n = match rt with
+ | Tapp ("vector",TA_nexp {nexp = Nconst i} :: TA_nexp {nexp = Nconst j} ::_) ->
+ abs_big_int (sub_big_int i j)
+ | _ ->
+ raise ((Reporting_basic.err_unreachable dl)
+ ("not the right type information available to construct "^
+ "undefined register")) in
+ parens (string ("UndefinedRegister " ^ string_of_big_int n))
+ | _ ->*) expY e in
+ let iexp (i,e) = parens (doc_int i ^^ comma ^^ expN e) in
+ let expspp =
+ match iexps with
+ | [] -> empty
+ | e :: es ->
+ let (expspp,_) =
+ List.fold_left
+ (fun (pp,count) e ->
+ (pp ^^ semi ^^ (if count = 5 then break 1 else empty) ^^ iexp e),
+ if count = 5 then 0 else count + 1)
+ (iexp e,0) es in
+ align (expspp) in
+ let call = string "make_indexed_vector" in
+ let epp =
+ align (group (call ^//^ brackets expspp ^/^
+ separate space [default_string;string start;string size;string dir_out])) in
+ let (bepp, aexp_needed) =
+ if is_bitvector_typ t
+ then (string "vec_to_bvec" ^^ space ^^ parens (epp) ^^ doc_tannot_lem regtypes false t, true)
+ else (epp, aexp_needed) in
+ if aexp_needed then parens (align bepp) else bepp
+ | E_vector_update(v,e1,e2) ->
+ let t = typ_of full_exp in
+ let call = if is_bitvector_typ t then "bvupdate_pos" else "update_pos" in
+ let epp = separate space [string call;expY v;expY e1;expY e2] in
+ if aexp_needed then parens (align epp) else epp
+ | E_vector_update_subrange(v,e1,e2,e3) ->
+ let t = typ_of full_exp in
+ let call = if is_bitvector_typ t then "bvupdate" else "update" in
+ let epp = align (string call ^//^
+ group (group (expY v) ^/^ group (expY e1) ^/^ group (expY e2)) ^/^
+ group (expY e3)) in
+ if aexp_needed then parens (align epp) else epp
+ | E_list exps ->
+ brackets (separate_map semi (expN) exps)
+ | E_case(e,pexps) ->
+ let only_integers e =
+ let typ = typ_of e in
+ if Ast_util.is_number typ then
+ let e_pp = expY e in
+ align (string "toNatural" ^//^ e_pp)
+ else
+ (* TODO: Where does this come from?? *)
+ (match typ with
+ | Typ_aux (Typ_tup ([t1;t2;t3;t4;t5] as ts), _) when List.for_all Ast_util.is_number ts ->
+ let e_pp = expY e in
+ align (string "toNaturalFiveTup" ^//^ e_pp)
+ | _ -> expY e)
+ in
+
+ (* This is a hack, incomplete. It's because lem does not allow
+ pattern-matching on integers *)
+ let epp =
+ group ((separate space [string "match"; only_integers e; string "with"]) ^/^
+ (separate_map (break 1) (doc_case regtypes) pexps) ^/^
+ (string "end")) in
+ if aexp_needed then parens (align epp) else align epp
+ | E_exit e -> separate space [string "exit"; expY e;]
+ | E_assert (e1,e2) ->
+ let epp = separate space [string "assert'"; expY e1; expY e2] in
+ if aexp_needed then parens (align epp) else align epp
+ | E_app_infix (e1,id,e2) ->
+ (* TODO: Should have been removed by the new type checker; check with Alasdair *)
+ raise (Reporting_basic.err_unreachable l
+ "E_app_infix should have been rewritten before pretty-printing")
+ (*match annot with
+ | Base((_,t),External(Some name),_,_,_,_) ->
+ let argpp arg =
+ let (E_aux (_,(_,Base((_,t),_,_,_,_,_)))) = arg in
+ match t.t with
+ | Tapp("vector",_) ->
+ let call =
+ if is_bitvector_typ t then "reset_bitvector_start"
+ else "reset_vector_start" in
+ parens (concat [string call;space;expY arg])
+ | _ -> expY arg in
+ let epp =
+ let aux name = align (argpp e1 ^^ space ^^ string name ^//^ argpp e2) in
+ let aux2 name = align (string name ^//^ argpp e1 ^/^ argpp e2) in
+ align
+ (match name with
+ | "power" -> aux2 "pow"
+
+ | "bitwise_and_bit" -> aux "&."
+ | "bitwise_or_bit" -> aux "|."
+ | "bitwise_xor_bit" -> aux "+."
+ | "add" -> aux "+"
+ | "minus" -> aux "-"
+ | "multiply" -> aux "*"
+
+ | "quot" -> aux2 "quot"
+ | "quot_signed" -> aux2 "quot"
+ | "modulo" -> aux2 "modulo"
+ | "add_vec" -> aux2 "add_VVV"
+ | "add_vec_signed" -> aux2 "addS_VVV"
+ | "add_overflow_vec" -> aux2 "addO_VVV"
+ | "add_overflow_vec_signed" -> aux2 "addSO_VVV"
+ | "minus_vec" -> aux2 "minus_VVV"
+ | "minus_overflow_vec" -> aux2 "minusO_VVV"
+ | "minus_overflow_vec_signed" -> aux2 "minusSO_VVV"
+ | "multiply_vec" -> aux2 "mult_VVV"
+ | "multiply_vec_signed" -> aux2 "multS_VVV"
+ | "mult_overflow_vec" -> aux2 "multO_VVV"
+ | "mult_overflow_vec_signed" -> aux2 "multSO_VVV"
+ | "quot_vec" -> aux2 "quot_VVV"
+ | "quot_vec_signed" -> aux2 "quotS_VVV"
+ | "quot_overflow_vec" -> aux2 "quotO_VVV"
+ | "quot_overflow_vec_signed" -> aux2 "quotSO_VVV"
+ | "mod_vec" -> aux2 "mod_VVV"
+
+ | "add_vec_range" -> aux2 "add_VIV"
+ | "add_vec_range_signed" -> aux2 "addS_VIV"
+ | "minus_vec_range" -> aux2 "minus_VIV"
+ | "mult_vec_range" -> aux2 "mult_VIV"
+ | "mult_vec_range_signed" -> aux2 "multS_VIV"
+ | "mod_vec_range" -> aux2 "minus_VIV"
+
+ | "add_range_vec" -> aux2 "add_IVV"
+ | "add_range_vec_signed" -> aux2 "addS_IVV"
+ | "minus_range_vec" -> aux2 "minus_IVV"
+ | "mult_range_vec" -> aux2 "mult_IVV"
+ | "mult_range_vec_signed" -> aux2 "multS_IVV"
+
+ | "add_range_vec_range" -> aux2 "add_IVI"
+ | "add_range_vec_range_signed" -> aux2 "addS_IVI"
+ | "minus_range_vec_range" -> aux2 "minus_IVI"
+
+ | "add_vec_range_range" -> aux2 "add_VII"
+ | "add_vec_range_range_signed" -> aux2 "addS_VII"
+ | "minus_vec_range_range" -> aux2 "minus_VII"
+ | "add_vec_vec_range" -> aux2 "add_VVI"
+ | "add_vec_vec_range_signed" -> aux2 "addS_VVI"
+
+ | "add_vec_bit" -> aux2 "add_VBV"
+ | "add_vec_bit_signed" -> aux2 "addS_VBV"
+ | "add_overflow_vec_bit_signed" -> aux2 "addSO_VBV"
+ | "minus_vec_bit_signed" -> aux2 "minus_VBV"
+ | "minus_overflow_vec_bit" -> aux2 "minusO_VBV"
+ | "minus_overflow_vec_bit_signed" -> aux2 "minusSO_VBV"
+
+ | _ ->
+ string name ^//^ parens (expN e1 ^^ comma ^/^ expN e2)) in
+ let (epp,aexp_needed) =
+ if contains_bitvector_typ t && not (contains_t_pp_var t)
+ then (parens epp ^^ doc_tannot_lem regtypes false t, true)
+ else (epp, aexp_needed) in
+ if aexp_needed then parens (align epp) else epp
+ | _ ->
+ let epp =
+ align (doc_id_lem id ^//^ parens (expN e1 ^^ comma ^/^ expN e2)) in
+ if aexp_needed then parens (align epp) else epp*)
+ | E_internal_let(lexp, eq_exp, in_exp) ->
+ raise (report l "E_internal_lets should have been removed till now")
+ (* (separate
+ space
+ [string "let internal";
+ (match lexp with (LEXP_aux ((LEXP_id id | LEXP_cast (_,id)),_)) -> doc_id_lem id);
+ coloneq;
+ exp eq_exp;
+ string "in"]) ^/^
+ exp in_exp *)
+ | E_internal_plet (pat,e1,e2) ->
+ let epp =
+ let b = match e1 with E_aux (E_if _,_) -> true | _ -> false in
+ match pat with
+ | P_aux (P_wild,_) ->
+ (separate space [expV b e1; string ">>"]) ^^ hardline ^^ expN e2
+ | _ ->
+ (separate space [expV b e1; string ">>= fun";
+ doc_pat_lem regtypes true pat;arrow]) ^^ hardline ^^ expN e2 in
+ if aexp_needed then parens (align epp) else epp
+ | E_internal_return (e1) ->
+ separate space [string "return"; expY e1;]
+ | E_sizeof nexp ->
+ (match nexp with
+ | Nexp_aux (Nexp_constant i, _) -> doc_lit_lem false (L_aux (L_num i, l)) annot
+ | _ ->
+ raise (Reporting_basic.err_unreachable l
+ "pretty-printing non-constant sizeof expressions to Lem not yet supported"))
+ | E_return _ ->
+ raise (Reporting_basic.err_unreachable l
+ "pretty-printing early return statements not yet to Lem supported")
+ | E_comment _ | E_comment_struc _ -> empty
+ | E_internal_cast _ | E_internal_exp _ | E_sizeof_internal _ | E_internal_exp_user _ ->
+ raise (Reporting_basic.err_unreachable l
+ "unsupported internal expression encountered while pretty-printing")
+ and let_exp regtypes (LB_aux(lb,_)) = match lb with
+ | LB_val_explicit(_,pat,e)
+ | LB_val_implicit(pat,e) ->
+ prefix 2 1
+ (separate space [string "let"; doc_pat_lem regtypes true pat; equals])
+ (top_exp regtypes false e)
+
+ and doc_fexp regtypes recordtyp (FE_aux(FE_Fexp(id,e),_)) =
+ let fname =
+ if prefix_recordtype
+ then (string (string_of_id recordtyp ^ "_")) ^^ doc_id_lem id
+ else doc_id_lem id in
+ group (doc_op equals fname (top_exp regtypes true e))
+
+ and doc_case regtypes (Pat_aux(Pat_exp(pat,e),_)) =
+ group (prefix 3 1 (separate space [pipe; doc_pat_lem regtypes false pat;arrow])
+ (group (top_exp regtypes false e)))
+
+ and doc_lexp_deref_lem regtypes ((LEXP_aux(lexp,(l,annot))) as le) = match lexp with
+ | LEXP_field (le,id) ->
+ parens (separate empty [doc_lexp_deref_lem regtypes le;dot;doc_id_lem id])
+ | LEXP_vector(le,e) ->
+ parens ((separate space) [string "access";doc_lexp_deref_lem regtypes le;
+ top_exp regtypes true e])
+ | LEXP_id id -> doc_id_lem id
+ | LEXP_cast (typ,id) -> doc_id_lem id
+ | _ ->
+ raise (Reporting_basic.err_unreachable l ("doc_lexp_deref_lem: Shouldn't happen"))
+ (* expose doc_exp_lem and doc_let *)
+ in top_exp, let_exp
+
+(*TODO Upcase and downcase type and constructors as needed*)
+let doc_type_union_lem regtypes (Tu_aux(typ_u,_)) = match typ_u with
+ | Tu_ty_id(typ,id) -> separate space [pipe; doc_id_lem_ctor id; string "of";
+ parens (doc_typ_lem regtypes typ)]
+ | Tu_id id -> separate space [pipe; doc_id_lem_ctor id]
+
+let rec doc_range_lem (BF_aux(r,_)) = match r with
+ | BF_single i -> parens (doc_op comma (doc_int i) (doc_int i))
+ | BF_range(i1,i2) -> parens (doc_op comma (doc_int i1) (doc_int i2))
+ | BF_concat(ir1,ir2) -> (doc_range ir1) ^^ comma ^^ (doc_range ir2)
+
+let doc_typdef_lem regtypes (TD_aux(td,_)) = match td with
+ | TD_abbrev(id,nm,typschm) ->
+ doc_op equals (concat [string "type"; space; doc_id_lem_type id])
+ (doc_typschm_lem regtypes typschm)
+ | TD_record(id,nm,typq,fs,_) ->
+ let f_pp (typ,fid) =
+ let fname = if prefix_recordtype
+ then concat [doc_id_lem id;string "_";doc_id_lem_type fid;]
+ else doc_id_lem_type fid in
+ concat [fname;space;colon;space;doc_typ_lem regtypes typ; semi] in
+ let fs_doc = group (separate_map (break 1) f_pp fs) in
+ doc_op equals
+ (concat [string "type"; space; doc_id_lem_type id;])
+ (doc_typquant_lem typq (anglebars (space ^^ align fs_doc ^^ space)))
+ | TD_variant(id,nm,typq,ar,_) ->
+ (match id with
+ | Id_aux ((Id "read_kind"),_) -> empty
+ | Id_aux ((Id "write_kind"),_) -> empty
+ | Id_aux ((Id "barrier_kind"),_) -> empty
+ | Id_aux ((Id "trans_kind"),_) -> empty
+ | Id_aux ((Id "instruction_kind"),_) -> empty
+ | Id_aux ((Id "regfp"),_) -> empty
+ | Id_aux ((Id "niafp"),_) -> empty
+ | Id_aux ((Id "diafp"),_) -> empty
+ | _ ->
+ let ar_doc = group (separate_map (break 1) (doc_type_union_lem regtypes) ar) in
+ let typ_pp =
+
+ (doc_op equals)
+ (concat [string "type"; space; doc_id_lem_type id;])
+ (doc_typquant_lem typq ar_doc) in
+ let make_id pat id =
+ separate space [string "SIA.Id_aux";
+ parens (string "SIA.Id " ^^ string_lit (doc_id id));
+ if pat then underscore else string "SIA.Unknown"] in
+ let fromInterpValueF = concat [doc_id_lem_type id;string "FromInterpValue"] in
+ let toInterpValueF = concat [doc_id_lem_type id;string "ToInterpValue"] in
+ let fromInterpValuePP =
+ (prefix 2 1)
+ (separate space [string "let rec";fromInterpValueF;string "v";equals;string "match v with"])
+ (
+ ((separate_map (break 1))
+ (fun (Tu_aux (tu,_)) ->
+ match tu with
+ | Tu_ty_id (ty,cid) ->
+ (separate space)
+ [pipe;string "SI.V_ctor";parens (make_id true cid);underscore;underscore;string "v";
+ arrow;
+ doc_id_lem_ctor cid;
+ parens (string "fromInterpValue v")]
+ | Tu_id cid ->
+ (separate space)
+ [pipe;string "SI.V_ctor";parens (make_id true cid);underscore;underscore;string "v";
+ arrow;
+ doc_id_lem_ctor cid])
+ ar) ^/^
+
+ ((separate space) [pipe;string "SI.V_tuple [v]";arrow;fromInterpValueF;string "v"]) ^/^
+
+ let failmessage =
+ (string_lit
+ (concat [string "fromInterpValue";space;doc_id_lem_type id;colon;space;string "unexpected value. ";]))
+ ^^
+ (string " ^ Interp.debug_print_value v") in
+ ((separate space) [pipe;string "v";arrow;string "failwith";parens failmessage]) ^/^
+ string "end") in
+ let toInterpValuePP =
+ (prefix 2 1)
+ (separate space [string "let";toInterpValueF;equals;string "function"])
+ (
+ ((separate_map (break 1))
+ (fun (Tu_aux (tu,_)) ->
+ match tu with
+ | Tu_ty_id (ty,cid) ->
+ (separate space)
+ [pipe;doc_id_lem_ctor cid;string "v";arrow;
+ string "SI.V_ctor";
+ parens (make_id false cid);
+ parens (string "SIA.T_id " ^^ string_lit (doc_id id));
+ string "SI.C_Union";
+ parens (string "toInterpValue v")]
+ | Tu_id cid ->
+ (separate space)
+ [pipe;doc_id_lem_ctor cid;arrow;
+ string "SI.V_ctor";
+ parens (make_id false cid);
+ parens (string "SIA.T_id " ^^ string_lit (doc_id id));
+ string "SI.C_Union";
+ parens (string "toInterpValue ()")])
+ ar) ^/^
+ string "end") in
+ let fromToInterpValuePP =
+ ((prefix 2 1)
+ (concat [string "instance ";parens (string "ToFromInterpValue " ^^ doc_id_lem_type id)])
+ (concat [string "let toInterpValue = ";toInterpValueF;hardline;
+ string "let fromInterpValue = ";fromInterpValueF]))
+ ^/^ string "end" in
+ typ_pp ^^ hardline ^^ hardline ^^
+ if !print_to_from_interp_value then
+ toInterpValuePP ^^ hardline ^^ hardline ^^
+ fromInterpValuePP ^^ hardline ^^ hardline ^^
+ fromToInterpValuePP ^^ hardline
+ else empty)
+ | TD_enum(id,nm,enums,_) ->
+ (match id with
+ | Id_aux ((Id "read_kind"),_) -> empty
+ | Id_aux ((Id "write_kind"),_) -> empty
+ | Id_aux ((Id "barrier_kind"),_) -> empty
+ | Id_aux ((Id "trans_kind"),_) -> empty
+ | Id_aux ((Id "instruction_kind"),_) -> empty
+ | Id_aux ((Id "regfp"),_) -> empty
+ | Id_aux ((Id "niafp"),_) -> empty
+ | Id_aux ((Id "diafp"),_) -> empty
+ | _ ->
+ let rec range i j = if i > j then [] else i :: (range (i+1) j) in
+ let nats = range 0 in
+ let enums_doc = group (separate_map (break 1 ^^ pipe ^^ space) doc_id_lem_ctor enums) in
+ let typ_pp = (doc_op equals)
+ (concat [string "type"; space; doc_id_lem_type id;])
+ (enums_doc) in
+ let fromInterpValueF = concat [doc_id_lem_type id;string "FromInterpValue"] in
+ let toInterpValueF = concat [doc_id_lem_type id;string "ToInterpValue"] in
+ let make_id pat id =
+ separate space [string "SIA.Id_aux";
+ parens (string "SIA.Id " ^^ string_lit (doc_id id));
+ if pat then underscore else string "SIA.Unknown"] in
+ let fromInterpValuePP =
+ (prefix 2 1)
+ (separate space [string "let rec";fromInterpValueF;string "v";equals;string "match v with"])
+ (
+ ((separate_map (break 1))
+ (fun (cid) ->
+ (separate space)
+ [pipe;string "SI.V_ctor";parens (make_id true cid);underscore;underscore;string "v";
+ arrow;doc_id_lem_ctor cid]
+ )
+ enums
+ ) ^/^
+ (
+ (align
+ ((prefix 3 1)
+ (separate space [pipe;string ("SI.V_lit (SIA.L_aux (SIA.L_num n) _)");arrow])
+ (separate space [string "match";parens(string "natFromInteger n");string "with"] ^/^
+ (
+ ((separate_map (break 1))
+ (fun (cid,number) ->
+ (separate space)
+ [pipe;string (string_of_int number);arrow;doc_id_lem_ctor cid]
+ )
+ (List.combine enums (nats ((List.length enums) - 1)))
+ ) ^/^ string "end"
+ )
+ )
+ )
+ )
+ ) ^/^
+
+ ((separate space) [pipe;string "SI.V_tuple [v]";arrow;fromInterpValueF;string "v"]) ^/^
+
+ let failmessage =
+ (string_lit
+ (concat [string "fromInterpValue";space;doc_id_lem_type id;colon;space;string "unexpected value. ";]))
+ ^^
+ (string " ^ Interp.debug_print_value v") in
+ ((separate space) [pipe;string "v";arrow;string "failwith";parens failmessage]) ^/^
+
+ string "end") in
+ let toInterpValuePP =
+ (prefix 2 1)
+ (separate space [string "let";toInterpValueF;equals;string "function"])
+ (
+ ((separate_map (break 1))
+ (fun (cid,number) ->
+ (separate space)
+ [pipe;doc_id_lem_ctor cid;arrow;
+ string "SI.V_ctor";
+ parens (make_id false cid);
+ parens (string "SIA.T_id " ^^ string_lit (doc_id id));
+ parens (string ("SI.C_Enum " ^ string_of_int number));
+ parens (string "toInterpValue ()")])
+ (List.combine enums (nats ((List.length enums) - 1)))) ^/^
+ string "end") in
+ let fromToInterpValuePP =
+ ((prefix 2 1)
+ (concat [string "instance ";parens (string "ToFromInterpValue " ^^ doc_id_lem_type id)])
+ (concat [string "let toInterpValue = ";toInterpValueF;hardline;
+ string "let fromInterpValue = ";fromInterpValueF]))
+ ^/^ string "end" in
+ typ_pp ^^ hardline ^^ hardline ^^
+ if !print_to_from_interp_value
+ then toInterpValuePP ^^ hardline ^^ hardline ^^
+ fromInterpValuePP ^^ hardline ^^ hardline ^^
+ fromToInterpValuePP ^^ hardline
+ else empty)
+ | TD_register(id,n1,n2,rs) ->
+ match n1,n2 with
+ | Nexp_aux(Nexp_constant i1,_),Nexp_aux(Nexp_constant i2,_) ->
+ let doc_rid (r,id) = parens (separate comma_sp [string_lit (doc_id_lem id);
+ doc_range_lem r;]) in
+ let doc_rids = group (separate_map (semi ^^ (break 1)) doc_rid rs) in
+ (*let doc_rfield (_,id) =
+ (doc_op equals)
+ (string "let" ^^ space ^^ doc_id_lem id)
+ (string "Register_field" ^^ space ^^ string_lit(doc_id_lem id)) in*)
+ let dir_b = i1 < i2 in
+ let dir = string (if dir_b then "true" else "false") in
+ let size = if dir_b then i2-i1 +1 else i1-i2 + 1 in
+ (doc_op equals)
+ (concat [string "let";space;string "build_";doc_id_lem id;space;string "regname"])
+ (string "Register" ^^ space ^^
+ align (separate space [string "regname"; doc_int size; doc_int i1; dir;
+ break 0 ^^ brackets (align doc_rids)]))
+ (*^^ hardline ^^
+ separate_map hardline doc_rfield rs *)
+
+let doc_rec_lem (Rec_aux(r,_)) = match r with
+ | Rec_nonrec -> space
+ | Rec_rec -> space ^^ string "rec" ^^ space
+
+let doc_tannot_opt_lem regtypes (Typ_annot_opt_aux(t,_)) = match t with
+ | Typ_annot_opt_some(tq,typ) -> doc_typquant_lem tq (doc_typ_lem regtypes typ)
+
+let doc_funcl_lem regtypes (FCL_aux(FCL_Funcl(id,pat,exp),_)) =
+ group (prefix 3 1 ((doc_pat_lem regtypes false pat) ^^ space ^^ arrow)
+ (doc_exp_lem regtypes false exp))
+
+let get_id = function
+ | [] -> failwith "FD_function with empty list"
+ | (FCL_aux (FCL_Funcl (id,_,_),_))::_ -> id
+
+module StringSet = Set.Make(String)
+
+let rec doc_fundef_lem regtypes (FD_aux(FD_function(r, typa, efa, fcls),fannot)) =
+ match fcls with
+ | [] -> failwith "FD_function with empty function list"
+ | [FCL_aux (FCL_Funcl(id,pat,exp),_)] ->
+ (prefix 2 1)
+ ((separate space)
+ [(string "let") ^^ (doc_rec_lem r) ^^ (doc_id_lem id);
+ (doc_pat_lem regtypes true pat);
+ equals])
+ (doc_exp_lem regtypes false exp)
+ | _ ->
+ let id = get_id fcls in
+ (* let sep = hardline ^^ pipe ^^ space in *)
+ match id with
+ | Id_aux (Id fname,idl)
+ when fname = "execute" || fname = "initial_analysis" ->
+ let (_,auxiliary_functions,clauses) =
+ List.fold_left
+ (fun (already_used_fnames,auxiliary_functions,clauses) funcl ->
+ match funcl with
+ | FCL_aux (FCL_Funcl (Id_aux (Id _,l),pat,exp),annot) ->
+ let (P_aux (P_app (Id_aux (Id ctor,l),argspat),pannot)) = pat in
+ let rec pick_name_not_clashing_with already_used candidate =
+ if StringSet.mem candidate already_used then
+ pick_name_not_clashing_with already_used (candidate ^ "'")
+ else candidate in
+ let aux_fname = pick_name_not_clashing_with already_used_fnames (fname ^ "_" ^ ctor) in
+ let already_used_fnames = StringSet.add aux_fname already_used_fnames in
+ let fcl = FCL_aux (FCL_Funcl (Id_aux (Id aux_fname,l),
+ P_aux (P_tup argspat,pannot),exp),annot) in
+ let auxiliary_functions =
+ auxiliary_functions ^^ hardline ^^ hardline ^^
+ doc_fundef_lem regtypes (FD_aux (FD_function(r,typa,efa,[fcl]),fannot)) in
+ (* Bind complex patterns to names so that we can pass them to the
+ auxiliary function *)
+ let name_pat idx (P_aux (p,a)) = match p with
+ | P_as (pat,_) -> P_aux (p,a) (* already named *)
+ | P_lit _ -> P_aux (p,a) (* no need to name a literal *)
+ | P_id _ -> P_aux (p,a) (* no need to name an identifier *)
+ | _ -> P_aux (P_as (P_aux (p,a), Id_aux (Id ("arg" ^ string_of_int idx),l)),a) in
+ let named_argspat = List.mapi name_pat argspat in
+ let named_pat = P_aux (P_app (Id_aux (Id ctor,l),named_argspat),pannot) in
+ let doc_arg idx (P_aux (p,(l,a))) = match p with
+ | P_as (pat,id) -> doc_id_lem id
+ | P_lit lit -> doc_lit_lem false lit a
+ | P_id id -> doc_id_lem id
+ | _ -> string ("arg" ^ string_of_int idx) in
+ let clauses =
+ clauses ^^ (break 1) ^^
+ (separate space
+ [pipe;doc_pat_lem regtypes false named_pat;arrow;
+ string aux_fname;
+ parens (separate comma (List.mapi doc_arg named_argspat))]) in
+ (already_used_fnames,auxiliary_functions,clauses)
+ ) (StringSet.empty,empty,empty) fcls in
+
+ auxiliary_functions ^^ hardline ^^ hardline ^^
+ (prefix 2 1)
+ ((separate space) [string "let" ^^ doc_rec_lem r ^^ doc_id_lem id;equals;string "function"])
+ (clauses ^/^ string "end")
+ | _ ->
+ let clauses =
+ (separate_map (break 1))
+ (fun fcl -> separate space [pipe;doc_funcl_lem regtypes fcl]) fcls in
+ (prefix 2 1)
+ ((separate space) [string "let" ^^ doc_rec_lem r ^^ doc_id_lem id;equals;string "function"])
+ (clauses ^/^ string "end")
+
+
+
+let doc_dec_lem (DEC_aux (reg,(l,annot))) =
+ match reg with
+ | DEC_reg(typ,id) ->
+ (match typ with
+ | Typ_aux (Typ_app (r, [Typ_arg_aux (Typ_arg_typ rt, _)]), _)
+ when string_of_id r = "register" && is_vector_typ rt ->
+ let (start, size, order, etyp) = vector_typ_args_of rt in
+ (match is_bit_typ etyp, start, size with
+ | true, Nexp_aux (Nexp_constant start, _), Nexp_aux (Nexp_constant size, _) ->
+ let o = if is_order_inc order then "true" else "false" in
+ (doc_op equals)
+ (string "let" ^^ space ^^ doc_id_lem id)
+ (string "Register" ^^ space ^^
+ align (separate space [string_lit(doc_id_lem id);
+ doc_int (size);
+ doc_int (start);
+ string o;
+ string "[]"]))
+ ^/^ hardline
+ | _ ->
+ let (Id_aux (Id name,_)) = id in
+ failwith ("can't deal with register " ^ name))
+ | Typ_aux (Typ_app(r, [Typ_arg_aux (Typ_arg_typ (Typ_aux (Typ_id idt, _)), _)]), _)
+ when string_of_id r = "register" ->
+ separate space [string "let";doc_id_lem id;equals;
+ string "build_" ^^ string (string_of_id idt);string_lit (doc_id_lem id)] ^/^ hardline
+ | Typ_aux (Typ_id idt, _) ->
+ separate space [string "let";doc_id_lem id;equals;
+ string "build_" ^^ string (string_of_id idt);string_lit (doc_id_lem id)] ^/^ hardline
+ |_-> empty)
+ | DEC_alias(id,alspec) -> empty
+ | DEC_typ_alias(typ,id,alspec) -> empty
+
+let doc_spec_lem regtypes (VS_aux (valspec,annot)) =
+ match valspec with
+ | VS_extern_no_rename _
+ | VS_extern_spec _ -> empty (* ignore these at the moment *)
+ | VS_val_spec (typschm,id) | VS_cast_spec (typschm,id) -> empty
+(* separate space [string "val"; doc_id_lem id; string ":";doc_typschm_lem regtypes typschm] ^/^ hardline *)
+
+
+let rec doc_def_lem regtypes def = match def with
+ | DEF_spec v_spec -> (doc_spec_lem regtypes v_spec,empty)
+ | DEF_overload _ -> (empty,empty)
+ | DEF_type t_def -> (group (doc_typdef_lem regtypes t_def) ^/^ hardline,empty)
+ | DEF_reg_dec dec -> (group (doc_dec_lem dec),empty)
+
+ | DEF_default df -> (empty,empty)
+ | DEF_fundef f_def -> (empty,group (doc_fundef_lem regtypes f_def) ^/^ hardline)
+ | DEF_val lbind -> (empty,group (doc_let_lem regtypes lbind) ^/^ hardline)
+ | DEF_scattered sdef -> failwith "doc_def_lem: shoulnd't have DEF_scattered at this point"
+
+ | DEF_kind _ -> (empty,empty)
+
+ | DEF_comm (DC_comm s) -> (empty,comment (string s))
+ | DEF_comm (DC_comm_struct d) ->
+ let (typdefs,vdefs) = doc_def_lem regtypes d in
+ (empty,comment (typdefs ^^ hardline ^^ vdefs))
+
+
+let doc_defs_lem regtypes (Defs defs) =
+ let (typdefs,valdefs) = List.split (List.map (doc_def_lem regtypes) defs) in
+ (separate empty typdefs,separate empty valdefs)
+
+let find_regtypes (Defs defs) =
+ List.fold_left
+ (fun acc def ->
+ match def with
+ | DEF_type (TD_aux(TD_register (Id_aux (Id tname, _),_,_,_),_)) -> tname :: acc
+ | _ -> acc
+ ) [] defs
+
+
+let typ_to_t env =
+ Type_check.typ_to_t env false false
+
+let pp_defs_lem (types_file,types_modules) (prompt_file,prompt_modules) (state_file,state_modules) d top_line =
+ let regtypes = find_regtypes d in
+ let (typdefs,valdefs) = doc_defs_lem regtypes d in
+ (print types_file)
+ (concat
+ [string "(*" ^^ (string top_line) ^^ string "*)";hardline;
+ (separate_map hardline)
+ (fun lib -> separate space [string "open import";string lib]) types_modules;hardline;
+ if !print_to_from_interp_value
+ then
+ concat
+ [(separate_map hardline)
+ (fun lib -> separate space [string " import";string lib]) ["Interp";"Interp_ast"];
+ string "open import Deep_shallow_convert";
+ hardline;
+ hardline;
+ string "module SI = Interp"; hardline;
+ string "module SIA = Interp_ast"; hardline;
+ hardline]
+ else empty;
+ typdefs]);
+ (print prompt_file)
+ (concat
+ [string "(*" ^^ (string top_line) ^^ string "*)";hardline;
+ (separate_map hardline)
+ (fun lib -> separate space [string "open import";string lib]) prompt_modules;hardline;
+ hardline;
+ valdefs]);
+ (print state_file)
+ (concat
+ [string "(*" ^^ (string top_line) ^^ string "*)";hardline;
+ (separate_map hardline)
+ (fun lib -> separate space [string "open import";string lib]) state_modules;hardline;
+ hardline;
+ valdefs]);
diff --git a/src/rewriter_new_tc.ml b/src/rewriter_new_tc.ml
index c76254f1..842ebdef 100644
--- a/src/rewriter_new_tc.ml
+++ b/src/rewriter_new_tc.ml
@@ -9,6 +9,7 @@
(* Robert Norton-Wright *)
(* Christopher Pulte *)
(* Peter Sewell *)
+(* Thomas Bauereiss *)
(* *)
(* All rights reserved. *)
(* *)
@@ -64,67 +65,32 @@ type 'a rewriters = {
let (>>) f g = fun x -> g(f(x))
-let raise_typ_err l m = raise (Reporting_basic.err_typ l m)
-
-let get_env_annot = function
+let env_of_annot = function
| (_,Some(env,_,_)) -> env
| (l,None) -> Env.empty
-let get_typ_annot = function
+let env_of (E_aux (_,a)) = env_of_annot a
+
+(*let typ_of_annot = function
| (_,Some(_,typ,_)) -> typ
- | (l,None) -> raise_typ_err l "no type information"
+ | (l,None) -> raise (Reporting_basic.err_typ l "no type information")
-let get_eff_annot = function
+let effect_of_annot = function
| (_,Some(_,_,eff)) -> eff
| (l,None) -> no_effect
-let get_env_exp (E_aux (_,a)) = get_env_annot a
-let get_typ_exp (E_aux (_,a)) = get_typ_annot a
-let get_eff_exp (E_aux (_,a)) = get_eff_annot a
-let get_eff_fpat (FP_aux (_,a)) = get_eff_annot a
-let get_eff_lexp (LEXP_aux (_,a)) = get_eff_annot a
-let get_eff_fexp (FE_aux (_,a)) = get_eff_annot a
-let get_eff_fexps (FES_aux (FES_Fexps (fexps,_),_)) =
- List.fold_left union_effects no_effect (List.map get_eff_fexp fexps)
-let get_eff_opt_default (Def_val_aux (_,a)) = get_eff_annot a
-let get_eff_pexp (Pat_aux (_,a)) = get_eff_annot a
-let get_eff_lb (LB_aux (_,a)) = get_eff_annot a
+let typ_of (E_aux (_,a)) = typ_of_annot a*)
+let effect_of_fpat (FP_aux (_,(_,a))) = effect_of_annot a
+let effect_of_lexp (LEXP_aux (_,(_,a))) = effect_of_annot a
+let effect_of_fexp (FE_aux (_,(_,a))) = effect_of_annot a
+let effect_of_fexps (FES_aux (FES_Fexps (fexps,_),_)) =
+ List.fold_left union_effects no_effect (List.map effect_of_fexp fexps)
+let effect_of_opt_default (Def_val_aux (_,(_,a))) = effect_of_annot a
+let effect_of_pexp (Pat_aux (_,(_,a))) = effect_of_annot a
+let effect_of_lb (LB_aux (_,(_,a))) = effect_of_annot a
let get_loc_exp (E_aux (_,(l,_))) = l
-let rec is_vector_typ = function
- | Typ_aux (Typ_app (Id_aux (Id "vector",_), [_;_;_;_]), _) -> true
- | Typ_aux (Typ_app (Id_aux (Id "register",_), [Typ_arg_aux (Typ_arg_typ rtyp,_)]), _) ->
- is_vector_typ rtyp
- | _ -> false
-
-let get_typ_app_args = function
- | Typ_aux (Typ_app (Id_aux (Id c,_), targs), l) ->
- (c, List.map (fun (Typ_arg_aux (a,_)) -> a) targs, l)
- | Typ_aux (_, l) -> raise (Reporting_basic.err_typ l "get_typ_app_args called on non-app type")
-
-let rec get_vector_typ_args typ = match get_typ_app_args typ with
- | ("vector", [Typ_arg_nexp start; Typ_arg_nexp len; Typ_arg_order ord; Typ_arg_typ etyp], _) ->
- (start, len, ord, etyp)
- | ("register", [Typ_arg_typ rtyp], _) -> get_vector_typ_args rtyp
- | (_, _, l) -> raise (Reporting_basic.err_typ l "get_vector_typ_args called on non-vector type")
-
-let order_is_inc = function
- | Ord_aux (Ord_inc, _) -> true
- | Ord_aux (Ord_dec, _) -> false
- | Ord_aux (Ord_var _, l) ->
- raise (Reporting_basic.err_unreachable l "order_is_inc called on vector with variable ordering")
-
-let is_bit_typ = function
- | Typ_aux (Typ_id (Id_aux (Id "bit", _)), _) -> true
- | _ -> false
-
-let is_bitvector_typ typ =
- if is_vector_typ typ then
- let (_,_,_,etyp) = get_vector_typ_args typ in
- is_bit_typ etyp
- else false
-
let simple_annot l typ = (Parse_ast.Generated l, Some (Env.empty, typ, no_effect))
let simple_num l n = E_aux (
E_lit (L_aux (L_num n, Parse_ast.Generated l)),
@@ -153,7 +119,7 @@ let fresh_id_pat pre ((l,annot)) =
P_aux (P_id id, (Parse_ast.Generated l, annot))
let union_eff_exps es =
- List.fold_left union_effects no_effect (List.map get_eff_exp es)
+ List.fold_left union_effects no_effect (List.map effect_of es)
let fix_eff_exp (E_aux (e,((l,_) as annot))) = match snd annot with
| Some (env, typ, eff) ->
@@ -162,7 +128,7 @@ let fix_eff_exp (E_aux (e,((l,_) as annot))) = match snd annot with
| E_nondet es -> union_eff_exps es
| E_id _
| E_lit _ -> no_effect
- | E_cast (_,e) -> get_eff_exp e
+ | E_cast (_,e) -> effect_of e
| E_app (_,es)
| E_tuple es -> union_eff_exps es
| E_app_infix (e1,_,e2) -> union_eff_exps [e1;e2]
@@ -171,7 +137,7 @@ let fix_eff_exp (E_aux (e,((l,_) as annot))) = match snd annot with
| E_vector es -> union_eff_exps es
| E_vector_indexed (ies,opt_default) ->
let (_,es) = List.split ies in
- union_effects (get_eff_opt_default opt_default) (union_eff_exps es)
+ union_effects (effect_of_opt_default opt_default) (union_eff_exps es)
| E_vector_access (e1,e2) -> union_eff_exps [e1;e2]
| E_vector_subrange (e1,e2,e3) -> union_eff_exps [e1;e2;e3]
| E_vector_update (e1,e2,e3) -> union_eff_exps [e1;e2;e3]
@@ -179,27 +145,27 @@ let fix_eff_exp (E_aux (e,((l,_) as annot))) = match snd annot with
| E_vector_append (e1,e2) -> union_eff_exps [e1;e2]
| E_list es -> union_eff_exps es
| E_cons (e1,e2) -> union_eff_exps [e1;e2]
- | E_record fexps -> get_eff_fexps fexps
+ | E_record fexps -> effect_of_fexps fexps
| E_record_update(e,fexps) ->
- union_effects (get_eff_exp e) (get_eff_fexps fexps)
- | E_field (e,_) -> get_eff_exp e
+ union_effects (effect_of e) (effect_of_fexps fexps)
+ | E_field (e,_) -> effect_of e
| E_case (e,pexps) ->
- List.fold_left union_effects (get_eff_exp e) (List.map get_eff_pexp pexps)
- | E_let (lb,e) -> union_effects (get_eff_lb lb) (get_eff_exp e)
- | E_assign (lexp,e) -> union_effects (get_eff_lexp lexp) (get_eff_exp e)
- | E_exit e -> get_eff_exp e
- | E_return e -> get_eff_exp e
+ List.fold_left union_effects (effect_of e) (List.map effect_of_pexp pexps)
+ | E_let (lb,e) -> union_effects (effect_of_lb lb) (effect_of e)
+ | E_assign (lexp,e) -> union_effects (effect_of_lexp lexp) (effect_of e)
+ | E_exit e -> effect_of e
+ | E_return e -> effect_of e
| E_sizeof _ | E_sizeof_internal _ -> no_effect
| E_assert (c,m) -> no_effect
| E_comment _ | E_comment_struc _ -> no_effect
- | E_internal_cast (_,e) -> get_eff_exp e
+ | E_internal_cast (_,e) -> effect_of e
| E_internal_exp _ -> no_effect
| E_internal_exp_user _ -> no_effect
| E_internal_let (lexp,e1,e2) ->
- union_effects (get_eff_lexp lexp)
- (union_effects (get_eff_exp e1) (get_eff_exp e2))
- | E_internal_plet (_,e1,e2) -> union_effects (get_eff_exp e1) (get_eff_exp e2)
- | E_internal_return e1 -> get_eff_exp e1)
+ union_effects (effect_of_lexp lexp)
+ (union_effects (effect_of e1) (effect_of e2))
+ | E_internal_plet (_,e1,e2) -> union_effects (effect_of e1) (effect_of e2)
+ | E_internal_return e1 -> effect_of e1)
in
E_aux (e, (l, Some (env, typ, effsum)))
| None ->
@@ -211,11 +177,11 @@ let fix_eff_lexp (LEXP_aux (lexp,((l,_) as annot))) = match snd annot with
| LEXP_id _ -> no_effect
| LEXP_cast _ -> no_effect
| LEXP_memory (_,es) -> union_eff_exps es
- | LEXP_vector (lexp,e) -> union_effects (get_eff_lexp lexp) (get_eff_exp e)
+ | LEXP_vector (lexp,e) -> union_effects (effect_of_lexp lexp) (effect_of e)
| LEXP_vector_range (lexp,e1,e2) ->
- union_effects (get_eff_lexp lexp)
- (union_effects (get_eff_exp e1) (get_eff_exp e2))
- | LEXP_field (lexp,_) -> get_eff_lexp lexp) in
+ union_effects (effect_of_lexp lexp)
+ (union_effects (effect_of e1) (effect_of e2))
+ | LEXP_field (lexp,_) -> effect_of_lexp lexp) in
LEXP_aux (lexp, (l, Some (env, typ, effsum)))
| None ->
LEXP_aux (lexp, (l, None))
@@ -223,7 +189,7 @@ let fix_eff_lexp (LEXP_aux (lexp,((l,_) as annot))) = match snd annot with
let fix_eff_fexp (FE_aux (fexp,((l,_) as annot))) = match snd annot with
| Some (env, typ, eff) ->
let effsum = union_effects eff (match fexp with
- | FE_Fexp (_,e) -> get_eff_exp e) in
+ | FE_Fexp (_,e) -> effect_of e) in
FE_aux (fexp, (l, Some (env, typ, effsum)))
| None ->
FE_aux (fexp, (l, None))
@@ -234,7 +200,7 @@ let fix_eff_opt_default (Def_val_aux (opt_default,((l,_) as annot))) = match snd
| Some (env, typ, eff) ->
let effsum = union_effects eff (match opt_default with
| Def_val_empty -> no_effect
- | Def_val_dec e -> get_eff_exp e) in
+ | Def_val_dec e -> effect_of e) in
Def_val_aux (opt_default, (l, Some (env, typ, effsum)))
| None ->
Def_val_aux (opt_default, (l, None))
@@ -242,7 +208,7 @@ let fix_eff_opt_default (Def_val_aux (opt_default,((l,_) as annot))) = match snd
let fix_eff_pexp (Pat_aux (pexp,((l,_) as annot))) = match snd annot with
| Some (env, typ, eff) ->
let effsum = union_effects eff (match pexp with
- | Pat_exp (_,e) -> get_eff_exp e) in
+ | Pat_exp (_,e) -> effect_of e) in
Pat_aux (pexp, (l, Some (env, typ, effsum)))
| None ->
Pat_aux (pexp, (l, None))
@@ -250,8 +216,8 @@ let fix_eff_pexp (Pat_aux (pexp,((l,_) as annot))) = match snd annot with
let fix_eff_lb (LB_aux (lb,((l,_) as annot))) = match snd annot with
| Some (env, typ, eff) ->
let effsum = union_effects eff (match lb with
- | LB_val_explicit (_,_,e) -> get_eff_exp e
- | LB_val_implicit (_,e) -> get_eff_exp e) in
+ | LB_val_explicit (_,_,e) -> effect_of e
+ | LB_val_implicit (_,e) -> effect_of e) in
LB_aux (lb, (l, Some (env, typ, effsum)))
| None ->
LB_aux (lb, (l, None))
@@ -266,7 +232,7 @@ let effectful_effs = function
) effs
| _ -> true
-let effectful eaux = effectful_effs (get_eff_exp eaux)
+let effectful eaux = effectful_effs (effect_of eaux)
let updates_vars_effs = function
| Effect_aux (Effect_set effs, _) ->
@@ -278,7 +244,7 @@ let updates_vars_effs = function
) effs
| _ -> true
-let updates_vars eaux = updates_vars_effs (get_eff_exp eaux)
+let updates_vars eaux = updates_vars_effs (effect_of eaux)
let id_to_string (Id_aux(id,l)) =
match id with
@@ -462,7 +428,7 @@ let rewrite_exp rewriters (E_aux (exp,(l,annot))) =
| E_assert(e1,e2) -> rewrap (E_assert(rewrite e1,rewrite e2))
| E_internal_cast (casted_annot,exp) ->
rewrap (E_internal_cast (casted_annot, rewrite exp))
- (* check_exp (get_env_exp exp) (strip_exp exp) (get_typ_annot casted_annot) *)
+ (* check_exp (env_of exp) (strip_exp exp) (typ_of_annot casted_annot) *)
(*let new_exp = rewrite exp in
(*let _ = Printf.eprintf "Removing an internal_cast with %s\n" (tannot_to_string casted_annot) in*)
(match casted_annot,exp with
@@ -1009,7 +975,7 @@ let remove_vector_concat_pat pat =
| Some j ->*) simple_num l j in
(*)| None ->
let length_app_exp = unit_exp l (E_app (Id_aux (Id "length",l),[root])) in
- (*let (_,length_root_nexp,_,_) = get_vector_typ_args (snd rannot) in
+ (*let (_,length_root_nexp,_,_) = vector_typ_args_of (snd rannot) in
let length_app_exp : tannot exp =
let typ = mk_atom_typ length_root_nexp in
let annot = (l,tag_annot typ (External (Some "length"))) in
@@ -1023,23 +989,23 @@ let remove_vector_concat_pat pat =
let letbind = fix_eff_lb (LB_aux (LB_val_implicit (P_aux (P_id child,cannot),subv),cannot)) in
(letbind,
- (fun body -> fix_eff_exp (E_aux (E_let (letbind,body), simple_annot l (get_typ_exp body)))),
+ (fun body -> fix_eff_exp (E_aux (E_let (letbind,body), simple_annot l (typ_of body)))),
(rootname,childname)) in
let p_aux = function
| ((P_as (P_aux (P_vector_concat pats,rannot'),rootid),decls),rannot) ->
- let (start,last_idx) = (match get_vector_typ_args (get_typ_annot rannot') with
+ let (start,last_idx) = (match vector_typ_args_of (typ_of_annot rannot') with
| (Nexp_aux (Nexp_constant start,_), Nexp_aux (Nexp_constant length,_), ord, _) ->
- (start, if order_is_inc ord then start + length - 1 else start - length + 1)
+ (start, if is_order_inc ord then start + length - 1 else start - length + 1)
| _ ->
raise (Reporting_basic.err_unreachable (fst rannot')
("unname_vector_concat_elements: vector of unspecified length in vector-concat pattern"))) in
let aux (pos,pat_acc,decl_acc) (P_aux (p,cannot),is_last) =
- let (_,length,ord,_) = get_vector_typ_args (get_typ_annot cannot) in
+ let (_,length,ord,_) = vector_typ_args_of (typ_of_annot cannot) in
(*)| (_,length,ord,_) ->*)
let (pos',index_j) = match length with
| Nexp_aux (Nexp_constant i,_) ->
- if order_is_inc ord then (pos+i, pos+i-1)
+ if is_order_inc ord then (pos+i, pos+i-1)
else (pos-i, pos-i+1)
| Nexp_aux (_,l) ->
if is_last then (pos,last_idx)
@@ -1065,7 +1031,7 @@ let remove_vector_concat_pat pat =
(Reporting_basic.err_unreachable
(fst cannot)
("unname_vector_concat_elements: Non-vector in vector-concat pattern:" ^
- string_of_typ (get_typ_annot cannot))
+ string_of_typ (typ_of_annot cannot))
)*) in
let pats_tagged = tag_last pats in
let (_,pats',decls') = List.fold_left aux (start,[],[]) pats_tagged in
@@ -1155,11 +1121,11 @@ let remove_vector_concat_pat pat =
let remove_vector_concats =
let p_vector_concat ps =
let aux acc (P_aux (p,annot),is_last) =
- let env = get_env_annot annot in
- let eff = get_eff_annot annot in
+ let env = env_of_annot annot in
+ let eff = effect_of_annot (snd annot) in
let (l,_) = annot in
let wild _ = P_aux (P_wild,(Parse_ast.Generated l, Some (env, bit_typ, eff))) in
- match p, get_vector_typ_args (get_typ_annot annot) with
+ match p, vector_typ_args_of (typ_of_annot annot) with
| P_vector ps,_ -> acc @ ps
| _, (_,Nexp_aux (Nexp_constant length,_),_,_) ->
acc @ (List.map wild (range 0 (length - 1)))
@@ -1168,10 +1134,10 @@ let remove_vector_concat_pat pat =
else raise
(Reporting_basic.err_unreachable l
("remove_vector_concats: Non-vector in vector-concat pattern " ^
- string_of_typ (get_typ_annot annot))) in
+ string_of_typ (typ_of_annot annot))) in
let has_length (P_aux (p,annot)) =
- match get_vector_typ_args (get_typ_annot annot) with
+ match vector_typ_args_of (typ_of_annot annot) with
| (_,Nexp_aux (Nexp_constant length,_),_,_) -> true
| _ -> false in
@@ -1250,7 +1216,7 @@ let rec contains_bitvector_pat (P_aux (pat,annot)) = match pat with
| P_lit _ | P_wild | P_id _ -> false
| P_as (pat,_) | P_typ (_,pat) -> contains_bitvector_pat pat
| P_vector _ | P_vector_concat _ | P_vector_indexed _ ->
- is_bitvector_typ (get_typ_annot annot)
+ is_bitvector_typ (typ_of_annot annot)
| P_app (_,pats) | P_tup pats | P_list pats ->
List.exists contains_bitvector_pat pats
| P_record (fpats,_) ->
@@ -1274,7 +1240,7 @@ let remove_bitvector_pat pat =
; p_list = (fun ps -> P_list (List.map (fun p -> p false) ps))
; p_aux =
(fun (pat,annot) contained_in_p_as ->
- let t = get_typ_annot annot in
+ let t = typ_of_annot annot in
let (l,_) = annot in
match pat, is_bitvector_typ t, contained_in_p_as with
| P_vector _, true, false
@@ -1305,10 +1271,10 @@ let remove_bitvector_pat pat =
Some (eqexp) in
let test_subvec_exp rootid l typ i j lits =
- let (start, length, ord, _) = get_vector_typ_args typ in
+ let (start, length, ord, _) = vector_typ_args_of typ in
let length' = nconstant (List.length lits) in
let start' =
- if order_is_inc ord then nconstant 0
+ if is_order_inc ord then nconstant 0
else nminus length' (nconstant 1) in
let typ' = vector_typ start' length' ord bit_typ in
let subvec_exp =
@@ -1355,9 +1321,9 @@ let remove_bitvector_pat pat =
(* Collect guards and let bindings *)
let guard_bitvector_pat =
let collect_guards_decls ps rootid t =
- let (start,_,ord,_) = get_vector_typ_args t in
+ let (start,_,ord,_) = vector_typ_args_of t in
let rec collect current (guards,dls) idx ps =
- let idx' = if order_is_inc ord then idx + 1 else idx - 1 in
+ let idx' = if is_order_inc ord then idx + 1 else idx - 1 in
(match ps with
| pat :: ps' ->
(match pat with
@@ -1434,7 +1400,7 @@ let remove_bitvector_pat pat =
; p_list = (fun ps -> let (ps,gdls) = List.split ps in
(P_list ps, flatten_guards_decls gdls))
; p_aux = (fun ((pat,gdls),annot) ->
- let t = get_typ_annot annot in
+ let t = typ_of_annot annot in
(match pat, is_bitvector_typ t with
| P_as (P_aux (P_vector ps, _), id), true ->
(P_aux (P_id id, annot), collect_guards_decls ps id t)
@@ -1480,11 +1446,11 @@ let rec subsumes_pat (P_aux (p1,annot1) as pat1) (P_aux (p2,annot2) as pat2) =
| _, P_typ (_,pat2) -> subsumes_pat pat1 pat2
| P_id (Id_aux (id1,_) as aid1), P_id (Id_aux (id2,_) as aid2) ->
if id1 = id2 then Some []
- else if Env.lookup_id aid1 (get_env_annot annot1) = Unbound &&
- Env.lookup_id aid2 (get_env_annot annot2) = Unbound
+ else if Env.lookup_id aid1 (env_of_annot annot1) = Unbound &&
+ Env.lookup_id aid2 (env_of_annot annot2) = Unbound
then Some [(id2,id1)] else None
| P_id id1, _ ->
- if Env.lookup_id id1 (get_env_annot annot1) = Unbound then Some [] else None
+ if Env.lookup_id id1 (env_of_annot annot1) = Unbound then Some [] else None
| P_wild, _ -> Some []
| P_app (Id_aux (id1,l1),args1), P_app (Id_aux (id2,_),args2) ->
if id1 = id2 then subsumes_list subsumes_pat args1 args2 else None
@@ -1544,8 +1510,8 @@ and fpat_to_fexp (FP_aux (FP_Fpat (id,pat),(l,annot))) =
let case_exp e t cs =
let pexp (pat,body,annot) = Pat_aux (Pat_exp (pat,body),annot) in
let ps = List.map pexp cs in
- (* let efr = union_effs (List.map get_eff_pexp ps) in *)
- fix_eff_exp (E_aux (E_case (e,ps), (get_loc_exp e, Some (get_env_exp e, t, no_effect))))
+ (* let efr = union_effs (List.map effect_of_pexp ps) in *)
+ fix_eff_exp (E_aux (E_case (e,ps), (get_loc_exp e, Some (env_of e, t, no_effect))))
let rewrite_guarded_clauses l cs =
let rec group clauses =
@@ -1590,7 +1556,7 @@ let rewrite_guarded_clauses l cs =
let else_exp =
if equiv_pats current_pat pat'
then if_exp current_pat (c' :: cs)
- else case_exp (pat_to_exp current_pat) (get_typ_annot annot') (group (c' :: cs)) in
+ else case_exp (pat_to_exp current_pat) (typ_of_annot annot') (group (c' :: cs)) in
fix_eff_exp (E_aux (E_if (exp,body,else_exp), annot))
| None -> body)
| [(pat,guard,body,annot)] -> body
@@ -1620,9 +1586,9 @@ let rewrite_exp_remove_bitvector_pat rewriters (E_aux (exp,(l,annot)) as full_ex
let exp_e' = E_aux (E_id fresh, gen_annot l (get_type e) pure_e) in
let pat_e' = P_aux (P_id fresh, gen_annot l (get_type e) pure_e) in *)
let letbind_e = LB_aux (LB_val_implicit (pat_e',e), (el,eannot)) in
- let exp' = case_exp exp_e' (get_typ_exp full_exp) clauses in
+ let exp' = case_exp exp_e' (typ_of full_exp) clauses in
rewrap (E_let (letbind_e, exp'))
- else case_exp e (get_typ_exp full_exp) clauses
+ else case_exp e (typ_of full_exp) clauses
| E_let (LB_aux (LB_val_explicit (typ,pat,v),annot'),body) ->
let (pat,(_,decls,_)) = remove_bitvector_pat pat in
rewrap (E_let (LB_aux (LB_val_explicit (typ,pat,rewrite_rec v),annot'),
@@ -1679,7 +1645,7 @@ let rewrite_defs_remove_bitvector_pats (Defs defs) =
let rewrite_exp_lift_assign_intro rewriters ((E_aux (exp,((l,_) as annot))) as full_exp) =
let rewrap e = E_aux (e,annot) in
let rewrap_effects e eff =
- E_aux (e, (l,Some (get_env_annot annot, get_typ_annot annot, eff))) in
+ E_aux (e, (l,Some (env_of_annot annot, typ_of_annot annot, eff))) in
let rewrite_rec = rewriters.rewrite_exp rewriters in
let rewrite_base = rewrite_exp rewriters in
match exp with
@@ -1745,15 +1711,15 @@ let rewrite_exp_lift_assign_intro rewriters ((E_aux (exp,((l,_) as annot))) as f
| E_assign(((LEXP_aux ((LEXP_id id | LEXP_cast (_,id)),lannot)) as le),e) ->
let le' = rewriters.rewrite_lexp rewriters le in
let e' = rewrite_base e in
- let effects = get_eff_exp e' in
- (match Env.lookup_id id (get_env_annot annot) with
+ let effects = effect_of e' in
+ (match Env.lookup_id id (env_of_annot annot) with
| Unbound ->
rewrap_effects
(E_internal_let(le', e', E_aux(E_block [], simple_annot l unit_typ)))
effects
| Local _ ->
- let effects' = union_effects effects (get_eff_annot lannot) in
- let annot' = Some (get_env_annot annot, unit_typ, effects') in
+ let effects' = union_effects effects (effect_of_annot (snd lannot)) in
+ let annot' = Some (env_of_annot annot, unit_typ, effects') in
E_aux((E_assign(le', e')),(l, annot'))
| _ -> rewrite_base full_exp)
| _ -> rewrite_base full_exp
@@ -1836,9 +1802,9 @@ let rewrite_defs_ocaml defs =
let rewrite_defs_remove_blocks =
let letbind_wild v body =
let (E_aux (_,(l,tannot))) = v in
- let annot_pat = (simple_annot l (get_typ_exp v)) in
+ let annot_pat = (simple_annot l (typ_of v)) in
let annot_lb = (Parse_ast.Generated l, tannot) in
- let annot_let = (Parse_ast.Generated l, Some (get_env_exp body, get_typ_exp body, union_eff_exps [v;body])) in
+ let annot_let = (Parse_ast.Generated l, Some (env_of body, typ_of body, union_eff_exps [v;body])) in
E_aux (E_let (LB_aux (LB_val_implicit (P_aux (P_wild,annot_pat),v),annot_lb),body),annot_let) in
let rec f l = function
@@ -1866,14 +1832,14 @@ let rewrite_defs_remove_blocks =
let letbind (v : 'a exp) (body : 'a exp -> 'a exp) : 'a exp =
(* body is a function : E_id variable -> actual body *)
- match get_typ_exp v with
+ match typ_of v with
| Typ_aux (Typ_id (Id_aux (Id "unit", _)), _) ->
let (E_aux (_,(l,annot))) = v in
let e = E_aux (E_lit (L_aux (L_unit,Parse_ast.Generated l)),(simple_annot l unit_typ)) in
let body = body e in
let annot_pat = simple_annot l unit_typ in
let annot_lb = annot_pat in
- let annot_let = (Parse_ast.Generated l, Some (get_env_exp body, get_typ_exp body, union_eff_exps [v;body])) in
+ let annot_let = (Parse_ast.Generated l, Some (env_of body, typ_of body, union_eff_exps [v;body])) in
let pat = P_aux (P_wild,annot_pat) in
E_aux (E_let (LB_aux (LB_val_implicit (pat,v),annot_lb),body),annot_let)
@@ -1883,9 +1849,9 @@ let letbind (v : 'a exp) (body : 'a exp -> 'a exp) : 'a exp =
let e_id = E_aux (E_id id, annot) in
let body = body e_id in
- let annot_pat = simple_annot l (get_typ_exp v) in
+ let annot_pat = simple_annot l (typ_of v) in
let annot_lb = annot_pat in
- let annot_let = (Parse_ast.Generated l, Some (get_env_exp body, get_typ_exp body, union_eff_exps [v;body])) in
+ let annot_let = (Parse_ast.Generated l, Some (env_of body, typ_of body, union_eff_exps [v;body])) in
let pat = P_aux (P_id id,annot_pat) in
E_aux (E_let (LB_aux (LB_val_implicit (pat,v),annot_lb),body),annot_let)
@@ -2077,7 +2043,7 @@ let rewrite_defs_letbind_effects =
| E_case (exp1,pexps) ->
let newreturn =
List.fold_left
- (fun b (Pat_aux (_,annot)) -> b || effectful_effs (get_eff_annot annot))
+ (fun b (Pat_aux (_,(_,annot))) -> b || effectful_effs (effect_of_annot annot))
false pexps in
n_exp_name exp1 (fun exp1 ->
n_pexpL newreturn pexps (fun pexps ->
@@ -2123,8 +2089,8 @@ let rewrite_defs_letbind_effects =
let rewrite_fun _ (FD_aux (FD_function(recopt,tannotopt,effectopt,funcls),fdannot)) =
let newreturn =
List.fold_left
- (fun b (FCL_aux (FCL_Funcl(id,pat,exp),annot)) ->
- b || effectful_effs (get_eff_annot annot)) false funcls in
+ (fun b (FCL_aux (FCL_Funcl(id,pat,exp),(_,annot))) ->
+ b || effectful_effs (effect_of_annot annot)) false funcls in
let rewrite_funcl (FCL_aux (FCL_Funcl(id,pat,exp),annot)) =
let _ = reset_fresh_name_counter () in
FCL_aux (FCL_Funcl (id,pat,n_exp_term newreturn exp),annot)
@@ -2241,7 +2207,7 @@ let find_updated_vars exp =
; lEXP_aux =
(function
| ((Some id,ids,acc),(annot)) ->
- (match Env.lookup_id id (get_env_annot annot) with
+ (match Env.lookup_id id (env_of_annot annot) with
| Unbound | Local _ -> ((id,annot) :: ids,acc)
| _ -> (ids,acc))
| ((_,ids,acc),_) -> (ids,acc)
@@ -2272,22 +2238,22 @@ let mktup l es =
| [e] -> e
| e :: _ ->
let effs =
- List.fold_left (fun acc e -> union_effects acc (get_eff_exp e)) no_effect es in
- let typ = mk_typ (Typ_tup (List.map get_typ_exp es)) in
- E_aux (E_tuple es,(Parse_ast.Generated l, Some (get_env_exp e, typ, effs)))
+ List.fold_left (fun acc e -> union_effects acc (effect_of e)) no_effect es in
+ let typ = mk_typ (Typ_tup (List.map typ_of es)) in
+ E_aux (E_tuple es,(Parse_ast.Generated l, Some (env_of e, typ, effs)))
let mktup_pat l es =
match es with
| [] -> P_aux (P_wild,(simple_annot l unit_typ))
| [E_aux (E_id id,_) as exp] ->
- P_aux (P_id id,(simple_annot l (get_typ_exp exp)))
+ P_aux (P_id id,(simple_annot l (typ_of exp)))
| _ ->
- let typ = mk_typ (Typ_tup (List.map get_typ_exp es)) in
+ let typ = mk_typ (Typ_tup (List.map typ_of es)) in
let pats = List.map (function
| (E_aux (E_id id,_) as exp) ->
- P_aux (P_id id,(simple_annot l (get_typ_exp exp)))
+ P_aux (P_id id,(simple_annot l (typ_of exp)))
| exp ->
- P_aux (P_wild,(simple_annot l (get_typ_exp exp)))) es in
+ P_aux (P_wild,(simple_annot l (typ_of exp)))) es in
P_aux (P_tup pats,(simple_annot l typ))
@@ -2301,31 +2267,31 @@ let rec rewrite_var_updates ((E_aux (expaux,((l,_) as annot))) as exp) =
match expaux with
| E_let (lb,exp) ->
let exp = add_vars overwrite exp vars in
- E_aux (E_let (lb,exp),swaptyp (get_typ_exp exp) annot)
+ E_aux (E_let (lb,exp),swaptyp (typ_of exp) annot)
| E_internal_let (lexp,exp1,exp2) ->
let exp2 = add_vars overwrite exp2 vars in
- E_aux (E_internal_let (lexp,exp1,exp2), swaptyp (get_typ_exp exp2) annot)
+ E_aux (E_internal_let (lexp,exp1,exp2), swaptyp (typ_of exp2) annot)
| E_internal_plet (pat,exp1,exp2) ->
let exp2 = add_vars overwrite exp2 vars in
- E_aux (E_internal_plet (pat,exp1,exp2), swaptyp (get_typ_exp exp2) annot)
+ E_aux (E_internal_plet (pat,exp1,exp2), swaptyp (typ_of exp2) annot)
| E_internal_return exp2 ->
let exp2 = add_vars overwrite exp2 vars in
- E_aux (E_internal_return exp2,swaptyp (get_typ_exp exp2) annot)
+ E_aux (E_internal_return exp2,swaptyp (typ_of exp2) annot)
| _ ->
(* after rewrite_defs_letbind_effects there cannot be terms that have
effects/update local variables in "tail-position": check n_exp_term
and where it is used. *)
if overwrite then
- match get_typ_exp exp with
+ match typ_of exp with
| Typ_aux (Typ_id (Id_aux (Id "unit", _)), _) -> vars
| _ -> raise (Reporting_basic.err_unreachable l
"add_vars: trying to overwrite a non-unit expression in tail-position")
else
- let typ' = Typ_aux (Typ_tup [get_typ_exp exp;get_typ_exp vars], Parse_ast.Generated l) in
+ let typ' = Typ_aux (Typ_tup [typ_of exp;typ_of vars], Parse_ast.Generated l) in
E_aux (E_tuple [exp;vars],swaptyp typ' annot) in
let rewrite (E_aux (expaux,((el,_) as annot))) (P_aux (_,(pl,pannot)) as pat) =
- let overwrite = match get_typ_annot annot with
+ let overwrite = match typ_of_annot annot with
| Typ_aux (Typ_id (Id_aux (Id "unit", _)), _) -> true
| _ -> false in
match expaux with
@@ -2352,13 +2318,13 @@ let rec rewrite_var_updates ((E_aux (expaux,((l,_) as annot))) as exp) =
let loopvar =
(* Don't bother with creating a range type annotation, since the
Lem pretty-printing does not use it. *)
- (* let (bf,tf) = match get_typ_exp exp1 with
+ (* let (bf,tf) = match typ_of exp1 with
| {t = Tapp ("atom",[TA_nexp f])} -> (TA_nexp f,TA_nexp f)
| {t = Tapp ("reg", [TA_typ {t = Tapp ("atom",[TA_nexp f])}])} -> (TA_nexp f,TA_nexp f)
| {t = Tapp ("range",[TA_nexp bf;TA_nexp tf])} -> (TA_nexp bf,TA_nexp tf)
| {t = Tapp ("reg", [TA_typ {t = Tapp ("range",[TA_nexp bf;TA_nexp tf])}])} -> (TA_nexp bf,TA_nexp tf)
| {t = Tapp (name,_)} -> failwith (name ^ " shouldn't be here") in
- let (bt,tt) = match get_typ_exp exp2 with
+ let (bt,tt) = match typ_of exp2 with
| {t = Tapp ("atom",[TA_nexp t])} -> (TA_nexp t,TA_nexp t)
| {t = Tapp ("atom",[TA_typ {t = Tapp ("atom", [TA_nexp t])}])} -> (TA_nexp t,TA_nexp t)
| {t = Tapp ("range",[TA_nexp bt;TA_nexp tt])} -> (TA_nexp bt,TA_nexp tt)
@@ -2373,7 +2339,7 @@ let rec rewrite_var_updates ((E_aux (expaux,((l,_) as annot))) as exp) =
let pat =
if overwrite then mktup_pat el vars
else P_aux (P_tup [pat; mktup_pat pl vars],
- simple_annot pl (get_typ_exp v)) in
+ simple_annot pl (typ_of v)) in
Added_vars (v,pat)
| E_if (c,e1,e2) ->
let vars = List.map (fun (var,(l,t)) -> E_aux (E_id var,(l,t)))
@@ -2385,14 +2351,14 @@ let rec rewrite_var_updates ((E_aux (expaux,((l,_) as annot))) as exp) =
let e1 = rewrite_var_updates (add_vars overwrite e1 vartuple) in
let e2 = rewrite_var_updates (add_vars overwrite e2 vartuple) in
(* after rewrite_defs_letbind_effects c has no variable updates *)
- let env = get_env_annot annot in
- let typ = get_typ_exp e1 in
+ let env = env_of_annot annot in
+ let typ = typ_of e1 in
let eff = union_eff_exps [e1;e2] in
let v = E_aux (E_if (c,e1,e2), (Parse_ast.Generated el, Some (env, typ, eff))) in
let pat =
if overwrite then mktup_pat el vars
else P_aux (P_tup [pat; mktup_pat pl vars],
- (simple_annot pl (get_typ_exp v))) in
+ (simple_annot pl (typ_of v))) in
Added_vars (v,pat)
| E_case (e1,ps) ->
(* after rewrite_defs_letbind_effects e1 needs no rewriting *)
@@ -2407,25 +2373,25 @@ let rec rewrite_var_updates ((E_aux (expaux,((l,_) as annot))) as exp) =
let vartuple = mktup el vars in
let typ =
let (Pat_aux (Pat_exp (_,first),_)) = List.hd ps in
- get_typ_exp first in
+ typ_of first in
let (ps,typ,effs) =
let f (acc,typ,effs) (Pat_aux (Pat_exp (p,e),pannot)) =
- let etyp = get_typ_exp e in
+ let etyp = typ_of e in
let () = assert (string_of_typ etyp = string_of_typ typ) in
let e = rewrite_var_updates (add_vars overwrite e vartuple) in
- let pannot = simple_annot pl (get_typ_exp e) in
- let effs = union_effects effs (get_eff_exp e) in
+ let pannot = simple_annot pl (typ_of e) in
+ let effs = union_effects effs (effect_of e) in
let pat' = Pat_aux (Pat_exp (p,e),pannot) in
(acc @ [pat'],typ,effs) in
List.fold_left f ([],typ,no_effect) ps in
- let v = E_aux (E_case (e1,ps), (Parse_ast.Generated pl, Some (get_env_annot annot, typ, effs))) in
+ let v = E_aux (E_case (e1,ps), (Parse_ast.Generated pl, Some (env_of_annot annot, typ, effs))) in
let pat =
if overwrite then mktup_pat el vars
else P_aux (P_tup [pat; mktup_pat pl vars],
- (simple_annot pl (get_typ_exp v))) in
+ (simple_annot pl (typ_of v))) in
Added_vars (v,pat)
| E_assign (lexp,vexp) ->
- let effs = match get_eff_annot annot with
+ let effs = match effect_of_annot (snd annot) with
| Effect_aux (Effect_set effs, _) -> effs
| _ ->
raise (Reporting_basic.err_unreachable l
@@ -2435,23 +2401,23 @@ let rec rewrite_var_updates ((E_aux (expaux,((l,_) as annot))) as exp) =
else
(match lexp with
| LEXP_aux (LEXP_id id,annot) ->
- let pat = P_aux (P_id id, simple_annot pl (get_typ_exp vexp)) in
+ let pat = P_aux (P_id id, simple_annot pl (typ_of vexp)) in
Added_vars (vexp,pat)
| LEXP_aux (LEXP_cast (_,id),annot) ->
- let pat = P_aux (P_id id, simple_annot pl (get_typ_exp vexp)) in
+ let pat = P_aux (P_id id, simple_annot pl (typ_of vexp)) in
Added_vars (vexp,pat)
| LEXP_aux (LEXP_vector (LEXP_aux (LEXP_id id,((l2,_) as annot2)),i),((l1,_) as annot)) ->
- let eid = E_aux (E_id id, simple_annot l2 (get_typ_annot annot2)) in
+ let eid = E_aux (E_id id, simple_annot l2 (typ_of_annot annot2)) in
let vexp = E_aux (E_vector_update (eid,i,vexp),
- simple_annot l1 (get_typ_annot annot)) in
- let pat = P_aux (P_id id, simple_annot pl (get_typ_exp vexp)) in
+ simple_annot l1 (typ_of_annot annot)) in
+ let pat = P_aux (P_id id, simple_annot pl (typ_of vexp)) in
Added_vars (vexp,pat)
| LEXP_aux (LEXP_vector_range (LEXP_aux (LEXP_id id,((l2,_) as annot2)),i,j),
((l,_) as annot)) ->
- let eid = E_aux (E_id id, simple_annot l2 (get_typ_annot annot2)) in
+ let eid = E_aux (E_id id, simple_annot l2 (typ_of_annot annot2)) in
let vexp = E_aux (E_vector_update_subrange (eid,i,j,vexp),
- simple_annot l (get_typ_annot annot)) in
- let pat = P_aux (P_id id, simple_annot pl (get_typ_exp vexp)) in
+ simple_annot l (typ_of_annot annot)) in
+ let pat = P_aux (P_id id, simple_annot pl (typ_of vexp)) in
Added_vars (vexp,pat))
| _ ->
(* after rewrite_defs_letbind_effects this expression is pure and updates
@@ -2466,29 +2432,29 @@ let rec rewrite_var_updates ((E_aux (expaux,((l,_) as annot))) as exp) =
(match rewrite v pat with
| Added_vars (v,pat) ->
let (E_aux (_,(l,_))) = v in
- let lbannot = (simple_annot l (get_typ_exp v)) in
- (get_eff_exp v,LB_aux (LB_val_implicit (pat,v),lbannot))
- | Same_vars v -> (get_eff_exp v,LB_aux (LB_val_implicit (pat,v),lbannot)))
+ let lbannot = (simple_annot l (typ_of v)) in
+ (effect_of v,LB_aux (LB_val_implicit (pat,v),lbannot))
+ | Same_vars v -> (effect_of v,LB_aux (LB_val_implicit (pat,v),lbannot)))
| LB_aux (LB_val_explicit (typ,pat,v),lbannot) ->
(match rewrite v pat with
| Added_vars (v,pat) ->
let (E_aux (_,(l,_))) = v in
- let lbannot = (simple_annot l (get_typ_exp v)) in
- (get_eff_exp v,LB_aux (LB_val_implicit (pat,v),lbannot))
- | Same_vars v -> (get_eff_exp v,LB_aux (LB_val_explicit (typ,pat,v),lbannot))) in
- let tannot = Some (get_env_annot annot, get_typ_exp body, union_effects eff (get_eff_exp body)) in
+ let lbannot = (simple_annot l (typ_of v)) in
+ (effect_of v,LB_aux (LB_val_implicit (pat,v),lbannot))
+ | Same_vars v -> (effect_of v,LB_aux (LB_val_explicit (typ,pat,v),lbannot))) in
+ let tannot = Some (env_of_annot annot, typ_of body, union_effects eff (effect_of body)) in
E_aux (E_let (lb,body),(Parse_ast.Generated l,tannot))
| E_internal_let (lexp,v,body) ->
(* Rewrite E_internal_let into E_let and call recursively *)
let id = match lexp with
| LEXP_aux (LEXP_id id,_) -> id
| LEXP_aux (LEXP_cast (_,id),_) -> id in
- let env = get_env_annot annot in
- let vtyp = get_typ_exp v in
- let veff = get_eff_exp v in
- let bodyenv = get_env_exp body in
- let bodytyp = get_typ_exp body in
- let bodyeff = get_eff_exp body in
+ let env = env_of_annot annot in
+ let vtyp = typ_of v in
+ let veff = effect_of v in
+ let bodyenv = env_of body in
+ let bodytyp = typ_of body in
+ let bodyeff = effect_of body in
let pat = P_aux (P_id id, (simple_annot l vtyp)) in
let lbannot = (Parse_ast.Generated l, Some (env, vtyp, veff)) in
let lb = LB_aux (LB_val_implicit (pat,v),lbannot) in
@@ -2583,7 +2549,7 @@ let rewrite_defs_remove_superfluous_letbinds =
let rewrite_defs_remove_superfluous_returns =
- let has_unittype e = match get_typ_exp e with
+ let has_unittype e = match typ_of e with
| Typ_aux (Typ_id Id_aux (Id "unit", _), _) -> true
| _ -> false in
diff --git a/src/rewriter_new_tc.mli b/src/rewriter_new_tc.mli
index 3d80118a..584d33fa 100644
--- a/src/rewriter_new_tc.mli
+++ b/src/rewriter_new_tc.mli
@@ -9,6 +9,7 @@
(* Robert Norton-Wright *)
(* Christopher Pulte *)
(* Peter Sewell *)
+(* Thomas Bauereiss *)
(* *)
(* All rights reserved. *)
(* *)
diff --git a/src/type_check_new.ml b/src/type_check_new.ml
index 9aeded29..5e625112 100644
--- a/src/type_check_new.ml
+++ b/src/type_check_new.ml
@@ -1376,13 +1376,13 @@ let destructure_vec_typ l env typ =
in
destructure_vec_typ' l (Env.expand_synonyms env typ)
-let typ_of (E_aux (_, (_, tannot))) = match tannot with
+let typ_of_annot (l, tannot) = match tannot with
| Some (_, typ, _) -> typ
- | None -> assert false
+ | None -> raise (Reporting_basic.err_unreachable l "no type annotation")
-let pat_typ_of (P_aux (_, (_, tannot))) = match tannot with
- | Some (_, typ, _) -> typ
- | None -> assert false
+let typ_of (E_aux (_, (l, tannot))) = typ_of_annot (l, tannot)
+
+let pat_typ_of (P_aux (_, (l, tannot))) = typ_of_annot (l, tannot)
(* Flow typing *)
@@ -2190,30 +2190,25 @@ and infer_funapp' l env f (typq, f_typ) xs ret_ctx_typ =
(* 6. Effect system *)
(**************************************************************************)
-let effect_of (E_aux (exp, (l, annot))) =
- match annot with
- | Some (_, _, eff) -> eff
- | None -> no_effect
+let effect_of_annot = function
+| Some (_, _, eff) -> eff
+| None -> no_effect
+
+let effect_of (E_aux (exp, (l, annot))) = effect_of_annot annot
let add_effect (E_aux (exp, (l, annot))) eff1 =
match annot with
| Some (env, typ, eff2) -> E_aux (exp, (l, Some (env, typ, union_effects eff1 eff2)))
| None -> assert false
-let effect_of_lexp (LEXP_aux (exp, (l, annot))) =
- match annot with
- | Some (_, _, eff) -> eff
- | None -> no_effect
+let effect_of_lexp (LEXP_aux (exp, (l, annot))) = effect_of_annot annot
let add_effect_lexp (LEXP_aux (lexp, (l, annot))) eff1 =
match annot with
| Some (env, typ, eff2) -> LEXP_aux (lexp, (l, Some (env, typ, union_effects eff1 eff2)))
| None -> assert false
-let effect_of_pat (P_aux (exp, (l, annot))) =
- match annot with
- | Some (_, _, eff) -> eff
- | None -> no_effect
+let effect_of_pat (P_aux (exp, (l, annot))) = effect_of_annot annot
let add_effect_pat (P_aux (pat, (l, annot))) eff1 =
match annot with
diff --git a/src/type_check_new.mli b/src/type_check_new.mli
index 2989aa1d..757b6fe3 100644
--- a/src/type_check_new.mli
+++ b/src/type_check_new.mli
@@ -172,10 +172,12 @@ val check_exp : Env.t -> unit exp -> typ -> tannot exp
functions must be guaranteed to have tannots of the form Some (env,
typ) for these to work. *)
val typ_of : tannot exp -> typ
+val typ_of_annot : Ast.l * tannot -> typ
val pat_typ_of : tannot pat -> typ
val effect_of : tannot exp -> effect
+val effect_of_annot : tannot -> effect
val propagate_exp_effect : tannot exp -> tannot exp