summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/pretty_print.ml3305
-rw-r--r--src/pretty_print_common.ml227
-rw-r--r--src/pretty_print_lem.ml1197
-rw-r--r--src/pretty_print_lem_ast.ml711
-rw-r--r--src/pretty_print_ocaml.ml717
-rw-r--r--src/pretty_print_sail.ml564
-rw-r--r--src/pretty_print_t_ascii.ml149
7 files changed, 3570 insertions, 3300 deletions
diff --git a/src/pretty_print.ml b/src/pretty_print.ml
index b7b88bb1..442c368b 100644
--- a/src/pretty_print.ml
+++ b/src/pretty_print.ml
@@ -40,3304 +40,9 @@
(* SUCH DAMAGE. *)
(**************************************************************************)
-open Type_internal
-open Ast
-open Format
-open Big_int
+include Pretty_print_t_ascii
+include Pretty_print_lem_ast
+include Pretty_print_sail
+include Pretty_print_ocaml
+include Pretty_print_lem
-(****************************************************************************
- * annotated source to Lem ast pretty printer
-****************************************************************************)
-
-let print_to_from_interp_value = ref false
-
-let rec list_format (sep : string) (fmt : 'a -> string) (ls : 'a list) : string =
- match ls with
- | [] -> ""
- | [a] -> fmt a
- | a::ls -> (fmt a) ^ sep ^ (list_format sep fmt ls)
-
-let rec list_pp i_format l_format =
- fun ppf l ->
- match l with
- | [] -> fprintf ppf ""
- | [i] -> fprintf ppf "%a" l_format i
- | i::is -> fprintf ppf "%a%a" i_format i (list_pp i_format l_format) is
-
-let kwd ppf s = fprintf ppf "%s" s
-let base ppf s = fprintf ppf "%s" s
-
-let lemnum default n = match n with
- | 0 -> "zero"
- | 1 -> "one"
- | 2 -> "two"
- | 3 -> "three"
- | 4 -> "four"
- | 5 -> "five"
- | 6 -> "six"
- | 7 -> "seven"
- | 8 -> "eight"
- | 15 -> "fifteen"
- | 16 -> "sixteen"
- | 20 -> "twenty"
- | 23 -> "twentythree"
- | 24 -> "twentyfour"
- | 30 -> "thirty"
- | 31 -> "thirtyone"
- | 32 -> "thirtytwo"
- | 35 -> "thirtyfive"
- | 39 -> "thirtynine"
- | 40 -> "forty"
- | 47 -> "fortyseven"
- | 48 -> "fortyeight"
- | 55 -> "fiftyfive"
- | 56 -> "fiftysix"
- | 57 -> "fiftyseven"
- | 61 -> "sixtyone"
- | 63 -> "sixtythree"
- | 64 -> "sixtyfour"
- | 127 -> "onetwentyseven"
- | 128 -> "onetwentyeight"
- | _ -> if n >= 0 then default n else ("(zero - " ^ (default (abs n)) ^ ")")
-
-let pp_format_id (Id_aux(i,_)) =
- match i with
- | Id(i) -> i
- | DeIid(x) -> "(deinfix " ^ x ^ ")"
-
-let pp_format_var (Kid_aux(Var v,_)) = v
-
-let rec pp_format_l_lem = function
- | Parse_ast.Unknown -> "Unknown"
- | _ -> "Unknown"(*
- | Parse_ast.Int(s,None) -> "(Int \"" ^ s ^ "\" Nothing)"
- | Parse_ast.Int(s,(Some l)) -> "(Int \"" ^ s ^ "\" (Just " ^ (pp_format_l_lem l) ^ "))"
- | Parse_ast.Range(p1,p2) -> "(Range \"" ^ p1.Lexing.pos_fname ^ "\" " ^
- (string_of_int p1.Lexing.pos_lnum) ^ " " ^
- (string_of_int (p1.Lexing.pos_cnum - p1.Lexing.pos_bol)) ^ " " ^
- (string_of_int p2.Lexing.pos_lnum) ^ " " ^
- (string_of_int (p2.Lexing.pos_cnum - p2.Lexing.pos_bol)) ^ ")"
- | Parse_ast.Generated l -> "(Generated " ^ (pp_format_l_lem l) ^ ")"
- | _ -> "Unknown"*)
-
-let pp_lem_l ppf l = base ppf (pp_format_l_lem l)
-
-let pp_format_id_lem (Id_aux(i,l)) =
- "(Id_aux " ^
- (match i with
- | Id(i) -> "(Id \"" ^ i ^ "\")"
- | DeIid(x) -> "(DeIid \"" ^ x ^ "\")") ^ " " ^
- (pp_format_l_lem l) ^ ")"
-
-let pp_lem_id ppf id = base ppf (pp_format_id_lem id)
-
-let pp_format_var_lem (Kid_aux(Var v,l)) = "(Kid_aux (Var \"" ^ v ^ "\") " ^ (pp_format_l_lem l) ^ ")"
-
-let pp_lem_var ppf var = base ppf (pp_format_var_lem var)
-
-let pp_format_bkind_lem (BK_aux(k,l)) =
- "(BK_aux " ^
- (match k with
- | BK_type -> "BK_type"
- | BK_nat -> "BK_nat"
- | BK_order -> "BK_order"
- | BK_effect -> "BK_effect") ^ " " ^
- (pp_format_l_lem l) ^ ")"
-
-let pp_lem_bkind ppf bk = base ppf (pp_format_bkind_lem bk)
-
-let pp_format_kind_lem (K_aux(K_kind(klst),l)) =
- "(K_aux (K_kind [" ^ list_format "; " pp_format_bkind_lem klst ^ "]) " ^ (pp_format_l_lem l) ^ ")"
-
-let pp_lem_kind ppf k = base ppf (pp_format_kind_lem k)
-
-let rec pp_format_typ_lem (Typ_aux(t,l)) =
- "(Typ_aux " ^
- (match t with
- | Typ_id(id) -> "(Typ_id " ^ pp_format_id_lem id ^ ")"
- | Typ_var(var) -> "(Typ_var " ^ pp_format_var_lem var ^ ")"
- | Typ_fn(arg,ret,efct) -> "(Typ_fn " ^ pp_format_typ_lem arg ^ " " ^
- pp_format_typ_lem ret ^ " " ^
- (pp_format_effects_lem efct) ^ ")"
- | Typ_tup(typs) -> "(Typ_tup [" ^ (list_format "; " pp_format_typ_lem typs) ^ "])"
- | Typ_app(id,args) -> "(Typ_app " ^ (pp_format_id_lem id) ^ " [" ^ (list_format "; " pp_format_typ_arg_lem args) ^ "])"
- | Typ_wild -> "Typ_wild") ^ " " ^
- (pp_format_l_lem l) ^ ")"
-and pp_format_nexp_lem (Nexp_aux(n,l)) =
- "(Nexp_aux " ^
- (match n with
- | Nexp_id(i) -> "(Nexp_id " ^ pp_format_id_lem i ^ ")"
- | Nexp_var(v) -> "(Nexp_var " ^ pp_format_var_lem v ^ ")"
- | Nexp_constant(i) -> "(Nexp_constant " ^ (lemnum string_of_int i) ^ ")"
- | Nexp_sum(n1,n2) -> "(Nexp_sum " ^ (pp_format_nexp_lem n1) ^ " " ^ (pp_format_nexp_lem n2) ^ ")"
- | Nexp_minus(n1,n2) -> "(Nexp_minus " ^ (pp_format_nexp_lem n1)^ " " ^ (pp_format_nexp_lem n2) ^ ")"
- | Nexp_times(n1,n2) -> "(Nexp_times " ^ (pp_format_nexp_lem n1) ^ " " ^ (pp_format_nexp_lem n2) ^ ")"
- | Nexp_exp(n1) -> "(Nexp_exp " ^ (pp_format_nexp_lem n1) ^ ")"
- | Nexp_neg(n1) -> "(Nexp_neg " ^ (pp_format_nexp_lem n1) ^ ")") ^ " " ^
- (pp_format_l_lem l) ^ ")"
-and pp_format_ord_lem (Ord_aux(o,l)) =
- "(Ord_aux " ^
- (match o with
- | Ord_var(v) -> "(Ord_var " ^ pp_format_var_lem v ^ ")"
- | Ord_inc -> "Ord_inc"
- | Ord_dec -> "Ord_dec") ^ " " ^
- (pp_format_l_lem l) ^ ")"
-and pp_format_base_effect_lem (BE_aux(e,l)) =
- "(BE_aux " ^
- (match e with
- | BE_rreg -> "BE_rreg"
- | BE_wreg -> "BE_wreg"
- | BE_rmem -> "BE_rmem"
- | BE_wmem -> "BE_wmem"
- | BE_wmv -> "BE_wmv"
- | BE_eamem -> "BE_eamem"
- | BE_barr -> "BE_barr"
- | BE_depend -> "BE_depend"
- | BE_undef -> "BE_undef"
- | BE_unspec -> "BE_unspec"
- | BE_nondet -> "BE_nondet"
- | BE_lset -> "BE_lset"
- | BE_lret -> "BE_lret"
- | BE_escape -> "BE_escape") ^ " " ^
- (pp_format_l_lem l) ^ ")"
-and pp_format_effects_lem (Effect_aux(e,l)) =
- "(Effect_aux " ^
- (match e with
- | Effect_var(v) -> "(Effect_var " ^ pp_format_var v ^ ")"
- | Effect_set(efcts) ->
- "(Effect_set [" ^
- (list_format "; " pp_format_base_effect_lem efcts) ^ " ])") ^ " " ^
- (pp_format_l_lem l) ^ ")"
-and pp_format_typ_arg_lem (Typ_arg_aux(t,l)) =
- "(Typ_arg_aux " ^
- (match t with
- | Typ_arg_typ(t) -> "(Typ_arg_typ " ^ pp_format_typ_lem t ^ ")"
- | Typ_arg_nexp(n) -> "(Typ_arg_nexp " ^ pp_format_nexp_lem n ^ ")"
- | Typ_arg_order(o) -> "(Typ_arg_order " ^ pp_format_ord_lem o ^ ")"
- | Typ_arg_effect(e) -> "(Typ_arg_effect " ^ pp_format_effects_lem e ^ ")") ^ " " ^
- (pp_format_l_lem l) ^ ")"
-
-let pp_lem_typ ppf t = base ppf (pp_format_typ_lem t)
-let pp_lem_nexp ppf n = base ppf (pp_format_nexp_lem n)
-let pp_lem_ord ppf o = base ppf (pp_format_ord_lem o)
-let pp_lem_effects ppf e = base ppf (pp_format_effects_lem e)
-let pp_lem_beffect ppf be = base ppf (pp_format_base_effect_lem be)
-
-let pp_format_nexp_constraint_lem (NC_aux(nc,l)) =
- "(NC_aux " ^
- (match nc with
- | NC_fixed(n1,n2) -> "(NC_fixed " ^ pp_format_nexp_lem n1 ^ " " ^ pp_format_nexp_lem n2 ^ ")"
- | NC_bounded_ge(n1,n2) -> "(NC_bounded_ge " ^ pp_format_nexp_lem n1 ^ " " ^ pp_format_nexp_lem n2 ^ ")"
- | NC_bounded_le(n1,n2) -> "(NC_bounded_le " ^ pp_format_nexp_lem n1 ^ " " ^ pp_format_nexp_lem n2 ^ ")"
- | NC_nat_set_bounded(id,bounds) -> "(NC_nat_set_bounded " ^
- pp_format_var_lem id ^
- " [" ^
- list_format "; " string_of_int bounds ^
- "])") ^ " " ^
- (pp_format_l_lem l) ^ ")"
-
-let pp_lem_nexp_constraint ppf nc = base ppf (pp_format_nexp_constraint_lem nc)
-
-let pp_format_qi_lem (QI_aux(qi,lq)) =
- "(QI_aux " ^
- (match qi with
- | QI_const(n_const) -> "(QI_const " ^ pp_format_nexp_constraint_lem n_const ^ ")"
- | QI_id(KOpt_aux(ki,lk)) ->
- "(QI_id (KOpt_aux " ^
- (match ki with
- | KOpt_none(var) -> "(KOpt_none " ^ pp_format_var_lem var ^ ")"
- | KOpt_kind(k,var) -> "(KOpt_kind " ^ pp_format_kind_lem k ^ " " ^ pp_format_var_lem var ^ ")") ^ " " ^
- (pp_format_l_lem lk) ^ "))") ^ " " ^
- (pp_format_l_lem lq) ^ ")"
-
-let pp_lem_qi ppf qi = base ppf (pp_format_qi_lem qi)
-
-let pp_format_typquant_lem (TypQ_aux(tq,l)) =
- "(TypQ_aux " ^
- (match tq with
- | TypQ_no_forall -> "TypQ_no_forall"
- | TypQ_tq(qlist) ->
- "(TypQ_tq [" ^
- (list_format "; " pp_format_qi_lem qlist) ^
- "])") ^ " " ^
- (pp_format_l_lem l) ^ ")"
-
-let pp_lem_typquant ppf tq = base ppf (pp_format_typquant_lem tq)
-
-let pp_format_typscm_lem (TypSchm_aux(TypSchm_ts(tq,t),l)) =
- "(TypSchm_aux (TypSchm_ts " ^ (pp_format_typquant_lem tq) ^ " " ^ pp_format_typ_lem t ^ ") " ^
- (pp_format_l_lem l) ^ ")"
-
-let pp_lem_typscm ppf ts = base ppf (pp_format_typscm_lem ts)
-
-let pp_format_lit_lem (L_aux(lit,l)) =
- "(L_aux " ^
- (match lit with
- | L_unit -> "L_unit"
- | L_zero -> "L_zero"
- | L_one -> "L_one"
- | L_true -> "L_true"
- | L_false -> "L_false"
- | L_num(i) -> "(L_num " ^ (lemnum string_of_int i) ^ ")"
- | L_hex(n) -> "(L_hex \"" ^ n ^ "\")"
- | L_bin(n) -> "(L_bin \"" ^ n ^ "\")"
- | L_undef -> "L_undef"
- | L_string(s) -> "(L_string \"" ^ s ^ "\")") ^ " " ^
- (pp_format_l_lem l) ^ ")"
-
-let pp_lem_lit ppf l = base ppf (pp_format_lit_lem l)
-
-
-let rec pp_format_t_lem t =
- match t.t with
- | Tid i -> "(T_id \"" ^ i ^ "\")"
- | Tvar i -> "(T_var \"" ^ i ^ "\")"
- | Tfn(t1,t2,_,e) -> "(T_fn " ^ (pp_format_t_lem t1) ^ " " ^ (pp_format_t_lem t2) ^ " " ^ pp_format_e_lem e ^ ")"
- | Ttup(tups) -> "(T_tup [" ^ (list_format "; " pp_format_t_lem tups) ^ "])"
- | Tapp(i,args) -> "(T_app \"" ^ i ^ "\" (T_args [" ^ list_format "; " pp_format_targ_lem args ^ "]))"
- | Tabbrev(ti,ta) -> "(T_abbrev " ^ (pp_format_t_lem ti) ^ " " ^ (pp_format_t_lem ta) ^ ")"
- | Tuvar(_) -> "(T_var \"fresh_v\")"
- | Toptions _ -> "(T_var \"fresh_v\")"
-and pp_format_targ_lem = function
- | TA_typ t -> "(T_arg_typ " ^ pp_format_t_lem t ^ ")"
- | TA_nexp n -> "(T_arg_nexp " ^ pp_format_n_lem n ^ ")"
- | TA_eft e -> "(T_arg_effect " ^ pp_format_e_lem e ^ ")"
- | TA_ord o -> "(T_arg_order " ^ pp_format_o_lem o ^ ")"
-and pp_format_n_lem n =
- match n.nexp with
- | Nid (i, n) -> "(Ne_id \"" ^ i ^ " " ^ "\")"
- | Nvar i -> "(Ne_var \"" ^ i ^ "\")"
- | Nconst i -> "(Ne_const " ^ (lemnum string_of_int (int_of_big_int i)) ^ ")"
- | Npos_inf -> "Ne_inf"
- | Nadd(n1,n2) -> "(Ne_add [" ^ (pp_format_n_lem n1) ^ "; " ^ (pp_format_n_lem n2) ^ "])"
- | Nsub(n1,n2) -> "(Ne_minus "^ (pp_format_n_lem n1) ^ " " ^ (pp_format_n_lem n2) ^ ")"
- | Nmult(n1,n2) -> "(Ne_mult " ^ (pp_format_n_lem n1) ^ " " ^ (pp_format_n_lem n2) ^ ")"
- | N2n(n,Some i) -> "(Ne_exp " ^ (pp_format_n_lem n) ^ "(*" ^ string_of_big_int i ^ "*)" ^ ")"
- | N2n(n,None) -> "(Ne_exp " ^ (pp_format_n_lem n) ^ ")"
- | Nneg n -> "(Ne_unary " ^ (pp_format_n_lem n) ^ ")"
- | Nuvar _ -> "(Ne_var \"fresh_v_" ^ string_of_int (get_index n) ^ "\")"
- | Nneg_inf -> "(Ne_unary Ne_inf)"
- | Npow _ -> "power_not_implemented"
- | Ninexact -> "(Ne_add Ne_inf (Ne_unary Ne_inf)"
-and pp_format_e_lem e =
- "(Effect_aux " ^
- (match e.effect with
- | Evar i -> "(Effect_var (Kid_aux (Var \"" ^ i ^ "\") Unknown))"
- | Eset es -> "(Effect_set [" ^
- (list_format "; " pp_format_base_effect_lem es) ^ " ])"
- | Euvar(_) -> "(Effect_var (Kid_aux (Var \"fresh_v\") Unknown))")
- ^ " Unknown)"
-and pp_format_o_lem o =
- "(Ord_aux " ^
- (match o.order with
- | Ovar i -> "(Ord_var (Kid_aux (Var \"" ^ i ^ "\") Unknown))"
- | Oinc -> "Ord_inc"
- | Odec -> "Ord_dec"
- | Ouvar(_) -> "(Ord_var (Kid_aux (Var \"fresh_v\") Unknown))")
- ^ " Unknown)"
-
-let rec pp_format_tag = function
- | Emp_local -> "Tag_empty"
- | Emp_intro -> "Tag_intro"
- | Emp_set -> "Tag_set"
- | Emp_global -> "Tag_global"
- | Tuple_assign tags -> (*"(Tag_tuple_assign [" ^ list_format " ;" pp_format_tag tags ^ "])"*) "Tag_tuple_assign"
- | External (Some s) -> "(Tag_extern (Just \""^s^"\"))"
- | External None -> "(Tag_extern Nothing)"
- | Default -> "Tag_default"
- | Constructor _ -> "Tag_ctor"
- | Enum i -> "(Tag_enum " ^ (lemnum string_of_int i) ^ ")"
- | Alias alias_inf -> "Tag_alias"
- | Spec -> "Tag_spec"
-
-let rec pp_format_nes nes =
- "[" ^ (*
- (list_format "; "
- (fun ne -> match ne with
- | LtEq(_,n1,n2) -> "(Nec_lteq " ^ pp_format_n_lem n1 ^ " " ^ pp_format_n_lem n2 ^ ")"
- | Eq(_,n1,n2) -> "(Nec_eq " ^ pp_format_n_lem n1 ^ " " ^ pp_format_n_lem n2 ^ ")"
- | GtEq(_,n1,n2) -> "(Nec_gteq " ^ pp_format_n_lem n1 ^ " " ^ pp_format_n_lem n2 ^ ")"
- | In(_,i,ns) | InS(_,{nexp=Nvar i},ns) ->
- "(Nec_in \"" ^ i ^ "\" [" ^ (list_format "; " string_of_int ns)^ "])"
- | InS(_,_,ns) ->
- "(Nec_in \"fresh\" [" ^ (list_format "; " string_of_int ns)^ "])"
- | CondCons(_,nes_c,nes_t) ->
- "(Nec_cond " ^ (pp_format_nes nes_c) ^ " " ^ (pp_format_nes nes_t) ^ ")"
- | BranchCons(_,nes_b) ->
- "(Nec_branch " ^ (pp_format_nes nes_b) ^ ")"
- )
- nes) ^*) "]"
-
-let pp_format_annot = function
- | NoTyp -> "Nothing"
- | Base((_,t),tag,nes,efct,efctsum,_) ->
- (*TODO print out bindings for use in pattern match in interpreter*)
- "(Just (" ^ pp_format_t_lem t ^ ", " ^ pp_format_tag tag ^ ", " ^ pp_format_nes nes ^ ", " ^
- pp_format_e_lem efct ^ ", " ^ pp_format_e_lem efctsum ^ "))"
- | Overload _ -> "Nothing"
-
-let pp_annot ppf ant = base ppf (pp_format_annot ant)
-
-
-let rec pp_format_pat_lem (P_aux(p,(l,annot))) =
- "(P_aux " ^
- (match p with
- | P_lit(lit) -> "(P_lit " ^ pp_format_lit_lem lit ^ ")"
- | P_wild -> "P_wild"
- | P_id(id) -> "(P_id " ^ pp_format_id_lem id ^ ")"
- | P_as(pat,id) -> "(P_as " ^ pp_format_pat_lem pat ^ " " ^ pp_format_id_lem id ^ ")"
- | P_typ(typ,pat) -> "(P_typ " ^ pp_format_typ_lem typ ^ " " ^ pp_format_pat_lem pat ^ ")"
- | P_app(id,pats) -> "(P_app " ^ pp_format_id_lem id ^ " [" ^
- list_format "; " pp_format_pat_lem pats ^ "])"
- | P_record(fpats,_) -> "(P_record [" ^
- list_format "; " (fun (FP_aux(FP_Fpat(id,fpat),_)) ->
- "(FP_Fpat " ^ pp_format_id_lem id ^ " " ^ pp_format_pat_lem fpat ^ ")") fpats
- ^ "])"
- | P_vector(pats) -> "(P_vector [" ^ list_format "; " pp_format_pat_lem pats ^ "])"
- | P_vector_indexed(ipats) ->
- "(P_vector_indexed [" ^ list_format "; " (fun (i,p) -> Printf.sprintf "(%d, %s)" i (pp_format_pat_lem p)) ipats ^ "])"
- | P_vector_concat(pats) -> "(P_vector_concat [" ^ list_format "; " pp_format_pat_lem pats ^ "])"
- | P_tup(pats) -> "(P_tup [" ^ (list_format "; " pp_format_pat_lem pats) ^ "])"
- | P_list(pats) -> "(P_list [" ^ (list_format "; " pp_format_pat_lem pats) ^ "])") ^
- " (" ^ pp_format_l_lem l ^ ", " ^ pp_format_annot annot ^ "))"
-
-let pp_lem_pat ppf p = base ppf (pp_format_pat_lem p)
-
-let rec pp_lem_let ppf (LB_aux(lb,(l,annot))) =
- let print_lb ppf lb =
- match lb with
- | LB_val_explicit(ts,pat,exp) ->
- fprintf ppf "@[<0>(%a %a %a %a)@]" kwd "LB_val_explicit" pp_lem_typscm ts pp_lem_pat pat pp_lem_exp exp
- | LB_val_implicit(pat,exp) ->
- fprintf ppf "@[<0>(%a %a %a)@]" kwd "LB_val_implicit" pp_lem_pat pat pp_lem_exp exp in
- fprintf ppf "@[<0>(LB_aux %a (%a, %a))@]" print_lb lb pp_lem_l l pp_annot annot
-
-and pp_lem_exp ppf (E_aux(e,(l,annot))) =
- let print_e ppf e =
- match e with
- | E_block(exps) -> fprintf ppf "@[<0>(E_aux %a [%a] %a (%a, %a))@]"
- kwd "(E_block"
- (list_pp pp_semi_lem_exp pp_lem_exp) exps
- kwd ")" pp_lem_l l pp_annot annot
- | E_nondet(exps) -> fprintf ppf "@[<0>(E_aux %a [%a] %a (%a, %a))@]"
- kwd "(E_nondet"
- (list_pp pp_semi_lem_exp pp_lem_exp) exps
- kwd ")" pp_lem_l l pp_annot annot
- | E_id(id) -> fprintf ppf "(E_aux (%a %a) (%a, %a))" kwd "E_id" pp_lem_id id pp_lem_l l pp_annot annot
- | E_lit(lit) -> fprintf ppf "(E_aux (%a %a) (%a, %a))" kwd "E_lit" pp_lem_lit lit pp_lem_l l pp_annot annot
- | E_cast(typ,exp) ->
- fprintf ppf "@[<0>(E_aux (E_cast %a %a) (%a, %a))@]" pp_lem_typ typ pp_lem_exp exp pp_lem_l l pp_annot annot
- | E_internal_cast((_,NoTyp),e) -> pp_lem_exp ppf e
- | E_app(f,args) -> fprintf ppf "@[<0>(E_aux (E_app %a [%a]) (%a, %a))@]"
- pp_lem_id f (list_pp pp_semi_lem_exp pp_lem_exp) args pp_lem_l l pp_annot annot
- | E_app_infix(l',op,r) -> fprintf ppf "@[<0>(E_aux (E_app_infix %a %a %a) (%a, %a))@]"
- pp_lem_exp l' pp_lem_id op pp_lem_exp r pp_lem_l l pp_annot annot
- | E_tuple(exps) -> fprintf ppf "@[<0>(E_aux (E_tuple [%a]) (%a, %a))@]"
- (list_pp pp_semi_lem_exp pp_lem_exp) exps pp_lem_l l pp_annot annot
- | E_if(c,t,e) -> fprintf ppf "@[<0>(E_aux (E_if %a @[<1>%a@] @[<1> %a@]) (%a, %a))@]"
- pp_lem_exp c pp_lem_exp t pp_lem_exp e pp_lem_l l pp_annot annot
- | E_for(id,exp1,exp2,exp3,order,exp4) ->
- fprintf ppf "@[<0>(E_aux (E_for %a %a %a %a %a @ @[<1> %a @]) (%a, %a))@]"
- pp_lem_id id pp_lem_exp exp1 pp_lem_exp exp2 pp_lem_exp exp3
- pp_lem_ord order pp_lem_exp exp4 pp_lem_l l pp_annot annot
- | E_vector(exps) -> fprintf ppf "@[<0>(E_aux (%a [%a]) (%a, %a))@]"
- kwd "E_vector" (list_pp pp_semi_lem_exp pp_lem_exp) exps pp_lem_l l pp_annot annot
- | E_vector_indexed(iexps,(Def_val_aux (default, (dl,dannot)))) ->
- let iformat ppf (i,e) = fprintf ppf "@[<1>(%i %a %a) %a@]" i kwd ", " pp_lem_exp e kwd ";" in
- let lformat ppf (i,e) = fprintf ppf "@[<1>(%i %a %a) @]" i kwd ", " pp_lem_exp e in
- let default_string ppf _ = (match default with
- | Def_val_empty -> fprintf ppf "(Def_val_aux Def_val_empty (%a,%a))" pp_lem_l dl pp_annot dannot
- | Def_val_dec e -> fprintf ppf "(Def_val_aux (Def_val_dec %a) (%a,%a))"
- pp_lem_exp e pp_lem_l dl pp_annot dannot) in
- fprintf ppf "@[<0>(E_aux (%a [%a] %a) (%a, %a))@]" kwd "E_vector_indexed"
- (list_pp iformat lformat) iexps default_string () pp_lem_l l pp_annot annot
- | E_vector_access(v,e) ->
- fprintf ppf "@[<0>(E_aux (%a %a %a) (%a, %a))@]"
- kwd "E_vector_access" pp_lem_exp v pp_lem_exp e pp_lem_l l pp_annot annot
- | E_vector_subrange(v,e1,e2) ->
- fprintf ppf "@[<0>(E_aux (E_vector_subrange %a %a %a) (%a, %a))@]"
- pp_lem_exp v pp_lem_exp e1 pp_lem_exp e2 pp_lem_l l pp_annot annot
- | E_vector_update(v,e1,e2) ->
- fprintf ppf "@[<0>(E_aux (E_vector_update %a %a %a) (%a, %a))@]"
- pp_lem_exp v pp_lem_exp e1 pp_lem_exp e2 pp_lem_l l pp_annot annot
- | E_vector_update_subrange(v,e1,e2,e3) ->
- fprintf ppf "@[<0>(E_aux (E_vector_update_subrange %a %a %a %a) (%a, %a))@]"
- pp_lem_exp v pp_lem_exp e1 pp_lem_exp e2 pp_lem_exp e3 pp_lem_l l pp_annot annot
- | E_vector_append(v1,v2) ->
- fprintf ppf "@[<0>(E_aux (E_vector_append %a %a) (%a, %a))@]"
- pp_lem_exp v1 pp_lem_exp v2 pp_lem_l l pp_annot annot
- | E_list(exps) -> fprintf ppf "@[<0>(E_aux (E_list [%a]) (%a, %a))@]"
- (list_pp pp_semi_lem_exp pp_lem_exp) exps pp_lem_l l pp_annot annot
- | E_cons(e1,e2) -> fprintf ppf "@[<0>(E_aux (E_cons %a %a) (%a, %a))@]"
- pp_lem_exp e1 pp_lem_exp e2 pp_lem_l l pp_annot annot
- | E_record(FES_aux(FES_Fexps(fexps,_),(fl,fannot))) ->
- fprintf ppf "@[<0>(E_aux (E_record (FES_aux (FES_Fexps [%a] false) (%a,%a))) (%a, %a))@]"
- (list_pp pp_semi_lem_fexp pp_lem_fexp) fexps pp_lem_l fl pp_annot fannot pp_lem_l l pp_annot annot
- | E_record_update(exp,(FES_aux(FES_Fexps(fexps,_),(fl,fannot)))) ->
- fprintf ppf "@[<0>(E_aux (E_record_update %a (FES_aux (FES_Fexps [%a] false) (%a,%a))) (%a,%a))@]"
- pp_lem_exp exp (list_pp pp_semi_lem_fexp pp_lem_fexp) fexps
- pp_lem_l fl pp_annot fannot pp_lem_l l pp_annot annot
- | E_field(fexp,id) -> fprintf ppf "@[<0>(E_aux (E_field %a %a) (%a, %a))@]"
- pp_lem_exp fexp pp_lem_id id pp_lem_l l pp_annot annot
- | E_case(exp,pexps) ->
- fprintf ppf "@[<0>(E_aux (E_case %a [%a]) (%a, %a))@]"
- pp_lem_exp exp (list_pp pp_semi_lem_case pp_lem_case) pexps pp_lem_l l pp_annot annot
- | E_let(leb,exp) -> fprintf ppf "@[<0>(E_aux (E_let %a %a) (%a, %a))@]"
- pp_lem_let leb pp_lem_exp exp pp_lem_l l pp_annot annot
- | E_assign(lexp,exp) -> fprintf ppf "@[<0>(E_aux (E_assign %a %a) (%a, %a))@]"
- pp_lem_lexp lexp pp_lem_exp exp pp_lem_l l pp_annot annot
- | E_sizeof nexp ->
- fprintf ppf "@[<0>(E_aux (E_sizeof %a) (%a, %a))@]" pp_lem_nexp nexp pp_lem_l l pp_annot annot
- | E_exit exp ->
- fprintf ppf "@[<0>(E_aux (E_exit %a) (%a, %a))@]" pp_lem_exp exp pp_lem_l l pp_annot annot
- | E_return exp ->
- fprintf ppf "@[<0>(E_aux (E_return %a) (%a, %a))@]" pp_lem_exp exp pp_lem_l l pp_annot annot
- | E_assert(c,msg) ->
- fprintf ppf "@[<0>(E_aux (E_assert %a %a) (%a, %a))@]" pp_lem_exp c pp_lem_exp msg pp_lem_l l pp_annot annot
- | E_internal_exp ((l, Base((_,t),_,_,_,_,bindings))) ->
- (*TODO use bindings where appropriate*)
- (match t.t with
- | Tapp("register",[TA_typ {t=Tapp("vector",[TA_nexp _;TA_nexp r;_;_])}])
- | Tapp("vector",[TA_nexp _;TA_nexp r;_;_]) ->
- (match r.nexp with
- | Nconst bi -> fprintf ppf "@[<0>(E_aux (E_lit (L_aux (L_num %a) %a)) (%a, %a))@]"
- kwd (lemnum string_of_int (int_of_big_int bi)) pp_lem_l l pp_lem_l l pp_annot (Base(([],nat_t),Emp_local,[],pure_e,pure_e,nob))
- | Nvar v -> fprintf ppf "@[<0>(E_aux (E_id (Id_aux (Id \"%a\") %a)) (%a,%a))@]"
- kwd v pp_lem_l l pp_lem_l l pp_annot (Base(([],nat_t),Emp_local,[],pure_e,pure_e,nob))
- | _ -> raise (Reporting_basic.err_unreachable l "Internal exp given vector without known length"))
- | Tapp("implicit",[TA_nexp r]) ->
- (match r.nexp with
- | Nconst bi -> fprintf ppf "@[<0>(E_aux (E_lit (L_aux (L_num %a) %a)) (%a, %a))@]"
- kwd (lemnum string_of_int (int_of_big_int bi)) pp_lem_l l pp_lem_l l pp_annot (Base(([],nat_t),Emp_local,[],pure_e,pure_e,nob))
- | Nvar v -> fprintf ppf "@[<0>(E_aux (E_id (Id_aux (Id \"%a\") %a)) (%a,%a))@]"
- kwd v pp_lem_l l pp_lem_l l pp_annot (Base(([],nat_t),Emp_local,[],pure_e,pure_e,nob))
- | _ -> raise (Reporting_basic.err_unreachable l "Internal_exp given implicit without variable or const"))
- | _ -> raise (Reporting_basic.err_unreachable l "Internal exp given non-vector or implicit"))
- | E_comment _ | E_comment_struc _ ->
- fprintf ppf "@[(E_aux (E_lit (L_aux L_unit %a)) (%a,%a))@]" pp_lem_l l pp_lem_l l pp_annot annot
- | E_internal_cast _ | E_internal_exp _ ->
- raise (Reporting_basic.err_unreachable l "Found internal cast or exp")
- | E_internal_exp_user _ -> (raise (Reporting_basic.err_unreachable l "Found non-rewritten internal_exp_user"))
- | E_sizeof_internal _ -> (raise (Reporting_basic.err_unreachable l "Internal sizeof not removed"))
- | E_internal_let _ -> (raise (Reporting_basic.err_unreachable l "Found non-rewritten internal_let"))
- | E_internal_return _ -> (raise (Reporting_basic.err_unreachable l "Found non-rewritten internal_return"))
- | E_internal_plet _ -> raise (Reporting_basic.err_unreachable l "Found non-rewritten internal_plet")
- in
- print_e ppf e
-
-and pp_semi_lem_exp ppf e = fprintf ppf "@[<1>%a%a@]" pp_lem_exp e kwd ";"
-
-and pp_lem_fexp ppf (FE_aux(FE_Fexp(id,exp),(l,annot))) =
- fprintf ppf "@[<1>(FE_aux (FE_Fexp %a %a) (%a, %a))@]" pp_lem_id id pp_lem_exp exp pp_lem_l l pp_annot annot
-and pp_semi_lem_fexp ppf fexp = fprintf ppf "@[<1>%a %a@]" pp_lem_fexp fexp kwd ";"
-
-and pp_lem_case ppf (Pat_aux(Pat_exp(pat,exp),(l,annot))) =
- fprintf ppf "@[<1>(Pat_aux (Pat_exp %a@ %a) (%a, %a))@]" pp_lem_pat pat pp_lem_exp exp pp_lem_l l pp_annot annot
-and pp_semi_lem_case ppf case = fprintf ppf "@[<1>%a %a@]" pp_lem_case case kwd ";"
-
-and pp_lem_lexp ppf (LEXP_aux(lexp,(l,annot))) =
- let print_le ppf lexp =
- match lexp with
- | LEXP_id(id) -> fprintf ppf "(%a %a)" kwd "LEXP_id" pp_lem_id id
- | LEXP_memory(id,args) ->
- fprintf ppf "(LEXP_memory %a [%a])" pp_lem_id id (list_pp pp_semi_lem_exp pp_lem_exp) args
- | LEXP_cast(typ,id) -> fprintf ppf "(LEXP_cast %a %a)" pp_lem_typ typ pp_lem_id id
- | LEXP_tup tups -> fprintf ppf "(LEXP_tup [%a])" (list_pp pp_semi_lem_lexp pp_lem_lexp) tups
- | LEXP_vector(v,exp) -> fprintf ppf "@[(%a %a %a)@]" kwd "LEXP_vector" pp_lem_lexp v pp_lem_exp exp
- | LEXP_vector_range(v,e1,e2) ->
- fprintf ppf "@[(%a %a %a %a)@]" kwd "LEXP_vector_range" pp_lem_lexp v pp_lem_exp e1 pp_lem_exp e2
- | LEXP_field(v,id) -> fprintf ppf "@[(%a %a %a)@]" kwd "LEXP_field" pp_lem_lexp v pp_lem_id id
- in
- fprintf ppf "@[(LEXP_aux %a (%a, %a))@]" print_le lexp pp_lem_l l pp_annot annot
-and pp_semi_lem_lexp ppf le = fprintf ppf "@[<1>%a%a@]" pp_lem_lexp le kwd ";"
-
-
-let pp_lem_default ppf (DT_aux(df,l)) =
- let print_de ppf df =
- match df with
- | DT_kind(bk,var) -> fprintf ppf "@[<0>(%a %a %a)@]" kwd "DT_kind" pp_lem_bkind bk pp_lem_var var
- | DT_typ(ts,id) -> fprintf ppf "@[<0>(%a %a %a)@]" kwd "DT_typ" pp_lem_typscm ts pp_lem_id id
- | DT_order(ord) -> fprintf ppf "@[<0>(DT_order %a)@]" pp_lem_ord ord
- in
- fprintf ppf "@[<0>(DT_aux %a %a)@]" print_de df pp_lem_l l
-
-let pp_lem_spec ppf (VS_aux(v,(l,annot))) =
- let print_spec ppf v =
- match v with
- | VS_val_spec(ts,id) ->
- fprintf ppf "@[<0>(%a %a %a)@]@\n" kwd "VS_val_spec" pp_lem_typscm ts pp_lem_id id
- | VS_extern_spec(ts,id,s) ->
- fprintf ppf "@[<0>(%a %a %a \"%s\")@]@\n" kwd "VS_extern_spec" pp_lem_typscm ts pp_lem_id id s
- | VS_extern_no_rename(ts,id) ->
- fprintf ppf "@[<0>(%a %a %a)@]@\n" kwd "VS_extern_no_rename" pp_lem_typscm ts pp_lem_id id
- in
- fprintf ppf "@[<0>(VS_aux %a (%a, %a))@]" print_spec v pp_lem_l l pp_annot annot
-
-let pp_lem_namescm ppf (Name_sect_aux(ns,l)) =
- match ns with
- | Name_sect_none -> fprintf ppf "(Name_sect_aux Name_sect_none %a)" pp_lem_l l
- | Name_sect_some(s) -> fprintf ppf "(Name_sect_aux (Name_sect_some \"%s\") %a)" s pp_lem_l l
-
-let rec pp_lem_range ppf (BF_aux(r,l)) =
- match r with
- | BF_single(i) -> fprintf ppf "(BF_aux (BF_single %i) %a)" i pp_lem_l l
- | BF_range(i1,i2) -> fprintf ppf "(BF_aux (BF_range %i %i) %a)" i1 i2 pp_lem_l l
- | BF_concat(ir1,ir2) -> fprintf ppf "(BF_aux (BF_concat %a %a) %a)" pp_lem_range ir1 pp_lem_range ir2 pp_lem_l l
-
-let pp_lem_typdef ppf (TD_aux(td,(l,annot))) =
- let print_td ppf td =
- match td with
- | TD_abbrev(id,namescm,typschm) ->
- fprintf ppf "@[<0>(%a %a %a %a)@]" kwd "TD_abbrev" pp_lem_id id pp_lem_namescm namescm pp_lem_typscm typschm
- | TD_record(id,nm,typq,fs,_) ->
- let f_pp ppf (typ,id) =
- fprintf ppf "@[<1>(%a, %a)%a@]" pp_lem_typ typ pp_lem_id id kwd ";" in
- fprintf ppf "@[<0>(%a %a %a %a [%a] false)@]"
- kwd "TD_record" pp_lem_id id pp_lem_namescm nm pp_lem_typquant typq (list_pp f_pp f_pp) fs
- | TD_variant(id,nm,typq,ar,_) ->
- let a_pp ppf (Tu_aux(typ_u,l)) =
- match typ_u with
- | Tu_ty_id(typ,id) -> fprintf ppf "@[<1>(Tu_aux (Tu_ty_id %a %a) %a);@]"
- pp_lem_typ typ pp_lem_id id pp_lem_l l
- | Tu_id(id) -> fprintf ppf "@[<1>(Tu_aux (Tu_id %a) %a);@]" pp_lem_id id pp_lem_l l
- in
- fprintf ppf "@[<0>(%a %a %a %a [%a] false)@]"
- kwd "TD_variant" pp_lem_id id pp_lem_namescm nm pp_lem_typquant typq (list_pp a_pp a_pp) ar
- | TD_enum(id,ns,enums,_) ->
- let pp_id_semi ppf id = fprintf ppf "%a%a " pp_lem_id id kwd ";" in
- fprintf ppf "@[<0>(%a %a %a [%a] false)@]"
- kwd "TD_enum" pp_lem_id id pp_lem_namescm ns (list_pp pp_id_semi pp_lem_id) enums
- | TD_register(id,n1,n2,rs) ->
- let pp_rid ppf (r,id) = fprintf ppf "(%a, %a)%a " pp_lem_range r pp_lem_id id kwd ";" in
- let pp_rids = (list_pp pp_rid pp_rid) in
- fprintf ppf "@[<0>(%a %a %a %a [%a])@]"
- kwd "TD_register" pp_lem_id id pp_lem_nexp n1 pp_lem_nexp n2 pp_rids rs
- in
- fprintf ppf "@[<0>(TD_aux %a (%a, %a))@]" print_td td pp_lem_l l pp_annot annot
-
-let pp_lem_kindef ppf (KD_aux(kd,(l,annot))) =
- let print_kd ppf kd =
- match kd with
- | KD_abbrev(kind,id,namescm,typschm) ->
- fprintf ppf "@[<0>(KD_abbrev %a %a %a %a)@]"
- pp_lem_kind kind pp_lem_id id pp_lem_namescm namescm pp_lem_typscm typschm
- | KD_nabbrev(kind,id,namescm,n) ->
- fprintf ppf "@[<0>(KD_nabbrev %a %a %a %a)@]"
- pp_lem_kind kind pp_lem_id id pp_lem_namescm namescm pp_lem_nexp n
- | KD_record(kind,id,nm,typq,fs,_) ->
- let f_pp ppf (typ,id) =
- fprintf ppf "@[<1>(%a, %a)%a@]" pp_lem_typ typ pp_lem_id id kwd ";" in
- fprintf ppf "@[<0>(%a %a %a %a %a [%a] false)@]"
- kwd "KD_record" pp_lem_kind kind pp_lem_id id pp_lem_namescm nm pp_lem_typquant typq (list_pp f_pp f_pp) fs
- | KD_variant(kind,id,nm,typq,ar,_) ->
- let a_pp ppf (Tu_aux(typ_u,l)) =
- match typ_u with
- | Tu_ty_id(typ,id) -> fprintf ppf "@[<1>(Tu_aux (Tu_ty_id %a %a) %a);@]"
- pp_lem_typ typ pp_lem_id id pp_lem_l l
- | Tu_id(id) -> fprintf ppf "@[<1>(Tu_aux (Tu_id %a) %a);@]" pp_lem_id id pp_lem_l l
- in
- fprintf ppf "@[<0>(%a %a %a %a %a [%a] false)@]"
- kwd "KD_variant" pp_lem_kind kind pp_lem_id id pp_lem_namescm nm pp_lem_typquant typq (list_pp a_pp a_pp) ar
- | KD_enum(kind,id,ns,enums,_) ->
- let pp_id_semi ppf id = fprintf ppf "%a%a " pp_lem_id id kwd ";" in
- fprintf ppf "@[<0>(%a %a %a %a [%a] false)@]"
- kwd "KD_enum" pp_lem_kind kind pp_lem_id id pp_lem_namescm ns (list_pp pp_id_semi pp_lem_id) enums
- | KD_register(kind,id,n1,n2,rs) ->
- let pp_rid ppf (r,id) = fprintf ppf "(%a, %a)%a " pp_lem_range r pp_lem_id id kwd ";" in
- let pp_rids = (list_pp pp_rid pp_rid) in
- fprintf ppf "@[<0>(%a %a %a %a %a [%a])@]"
- kwd "KD_register" pp_lem_kind kind pp_lem_id id pp_lem_nexp n1 pp_lem_nexp n2 pp_rids rs
- in
- fprintf ppf "@[<0>(KD_aux %a (%a, %a))@]" print_kd kd pp_lem_l l pp_annot annot
-
-let pp_lem_rec ppf (Rec_aux(r,l)) =
- match r with
- | Rec_nonrec -> fprintf ppf "(Rec_aux Rec_nonrec %a)" pp_lem_l l
- | Rec_rec -> fprintf ppf "(Rec_aux Rec_rec %a)" pp_lem_l l
-
-let pp_lem_tannot_opt ppf (Typ_annot_opt_aux(t,l)) =
- match t with
- | Typ_annot_opt_some(tq,typ) ->
- fprintf ppf "(Typ_annot_opt_aux (Typ_annot_opt_some %a %a) %a)" pp_lem_typquant tq pp_lem_typ typ pp_lem_l l
-
-let pp_lem_effects_opt ppf (Effect_opt_aux(e,l)) =
- match e with
- | Effect_opt_pure -> fprintf ppf "(Effect_opt_aux Effect_opt_pure %a)" pp_lem_l l
- | Effect_opt_effect e -> fprintf ppf "(Effect_opt_aux (Effect_opt_effect %a) %a)" pp_lem_effects e pp_lem_l l
-
-let pp_lem_funcl ppf (FCL_aux(FCL_Funcl(id,pat,exp),(l,annot))) =
- fprintf ppf "@[<0>(FCL_aux (%a %a %a %a) (%a,%a))@]@\n"
- kwd "FCL_Funcl" pp_lem_id id pp_lem_pat pat pp_lem_exp exp pp_lem_l l pp_annot annot
-
-let pp_lem_fundef ppf (FD_aux(FD_function(r, typa, efa, fcls),(l,annot))) =
- let pp_funcls ppf funcl = fprintf ppf "%a %a" pp_lem_funcl funcl kwd ";" in
- fprintf ppf "@[<0>(FD_aux (%a %a %a %a [%a]) (%a, %a))@]"
- kwd "FD_function" pp_lem_rec r pp_lem_tannot_opt typa pp_lem_effects_opt efa (list_pp pp_funcls pp_funcls) fcls
- pp_lem_l l pp_annot annot
-
-let pp_lem_aspec ppf (AL_aux(aspec,(l,annot))) =
- let pp_reg_id ppf (RI_aux((RI_id ri),(l,annot))) =
- fprintf ppf "@[<0>(RI_aux (RI_id %a) (%a,%a))@]" pp_lem_id ri pp_lem_l l pp_annot annot in
- match aspec with
- | AL_subreg(reg,subreg) ->
- fprintf ppf "@[<0>(AL_aux (AL_subreg %a %a) (%a,%a))@]"
- pp_reg_id reg pp_lem_id subreg pp_lem_l l pp_annot annot
- | AL_bit(reg,ac) ->
- fprintf ppf "@[<0>(AL_aux (AL_bit %a %a) (%a,%a))@]" pp_reg_id reg pp_lem_exp ac pp_lem_l l pp_annot annot
- | AL_slice(reg,b,e) ->
- fprintf ppf "@[<0>(AL_aux (AL_slice %a %a %a) (%a,%a))@]"
- pp_reg_id reg pp_lem_exp b pp_lem_exp e pp_lem_l l pp_annot annot
- | AL_concat(f,s) ->
- fprintf ppf "@[<0>(AL_aux (AL_concat %a %a) (%a,%a))@]" pp_reg_id f pp_reg_id s pp_lem_l l pp_annot annot
-
-let pp_lem_dec ppf (DEC_aux(reg,(l,annot))) =
- match reg with
- | DEC_reg(typ,id) ->
- fprintf ppf "@[<0>(DEC_aux (DEC_reg %a %a) (%a,%a))@]" pp_lem_typ typ pp_lem_id id pp_lem_l l pp_annot annot
- | DEC_alias(id,alias_spec) ->
- fprintf ppf "@[<0>(DEC_aux (DEC_alias %a %a) (%a, %a))@]"
- pp_lem_id id pp_lem_aspec alias_spec pp_lem_l l pp_annot annot
- | DEC_typ_alias(typ,id,alias_spec) ->
- fprintf ppf "@[<0>(DEC_aux (DEC_typ_alias %a %a %a) (%a, %a))@]"
- pp_lem_typ typ pp_lem_id id pp_lem_aspec alias_spec pp_lem_l l pp_annot annot
-
-let pp_lem_def ppf d =
- match d with
- | DEF_default(df) -> fprintf ppf "(DEF_default %a);@\n" pp_lem_default df
- | DEF_spec(v_spec) -> fprintf ppf "(DEF_spec %a);@\n" pp_lem_spec v_spec
- | DEF_type(t_def) -> fprintf ppf "(DEF_type %a);@\n" pp_lem_typdef t_def
- | DEF_kind(k_def) -> fprintf ppf "(DEF_kind %a);@\n" pp_lem_kindef k_def
- | DEF_fundef(f_def) -> fprintf ppf "(DEF_fundef %a);@\n" pp_lem_fundef f_def
- | DEF_val(lbind) -> fprintf ppf "(DEF_val %a);@\n" pp_lem_let lbind
- | DEF_reg_dec(dec) -> fprintf ppf "(DEF_reg_dec %a);@\n" pp_lem_dec dec
- | DEF_comm d -> fprintf ppf ""
- | _ -> raise (Reporting_basic.err_unreachable Parse_ast.Unknown "initial_check didn't remove all scattered Defs")
-
-let pp_lem_defs ppf (Defs(defs)) =
- fprintf ppf "Defs [@[%a@]]@\n" (list_pp pp_lem_def pp_lem_def) defs
-
-
-
-(* **************************************************************************
- * pp from tannot to ASCII source, for pp of built-in type environment
-*)
-
-
-
-let rec pp_format_t_ascii t =
- match t.t with
- | Tid i -> i
- | Tvar i -> "'" ^ i
- | Tfn(t1,t2,_,e) -> (pp_format_t_ascii t1) ^ " -> " ^ (pp_format_t_ascii t2) ^ (match e.effect with Eset [] -> "" | _ -> " effect " ^ pp_format_e_ascii e)
- | Ttup(tups) -> "(" ^ (list_format ", " pp_format_t_ascii tups) ^ ")"
- | Tapp(i,args) -> i ^ "<" ^ list_format ", " pp_format_targ_ascii args ^ ">"
- | Tabbrev(ti,ta) -> (pp_format_t_ascii ti) (* (pp_format_t_ascii ta) *)
- | Tuvar(_) -> failwith "Tuvar in pp_format_t_ascii"
- | Toptions _ -> failwith "Toptions in pp_format_t_ascii"
-and pp_format_targ_ascii = function
- | TA_typ t -> pp_format_t_ascii t
- | TA_nexp n -> pp_format_n_ascii n
- | TA_eft e -> pp_format_e_ascii e
- | TA_ord o -> pp_format_o_ascii o
-and pp_format_n_ascii n =
- match n.nexp with
- | Nid (i, n) -> i (* from an abbreviation *)
- | Nvar i -> "'" ^ i
- | Nconst i -> (string_of_int (int_of_big_int i))
- | Npos_inf -> "infinity"
- | Nadd(n1,n2) -> (pp_format_n_ascii n1) ^ "+" ^ (pp_format_n_ascii n2)
- | Nsub(n1,n2) -> (pp_format_n_ascii n1) ^ "-" ^ (pp_format_n_ascii n2)
- | Nmult(n1,n2) -> (pp_format_n_ascii n1) ^ "*" ^ (pp_format_n_ascii n2)
- | N2n(n,_) -> "2**"^(pp_format_n_ascii n) (* string_of_big_int i ^ *)
- | Nneg n -> "-" ^ (pp_format_n_ascii n)
- | Nuvar _ -> failwith "Nuvar in pp_format_n_ascii"
- | Nneg_inf -> "-infinity"
- | Npow _ -> failwith "Npow in pp_format_n_ascii"
- | Ninexact -> failwith "Ninexact in pp_format_n_ascii"
-and pp_format_e_ascii e =
- match e.effect with
- | Evar i -> "'" ^ i
- | Eset es -> "{" ^
- (list_format ", " pp_format_base_effect_ascii es) ^ "}"
- | Euvar(_) -> failwith "Euvar in pp_format_e_ascii"
-and pp_format_o_ascii o =
- match o.order with
- | Ovar i -> "'" ^ i
- | Oinc -> "inc"
- | Odec -> "dec"
- | Ouvar(_) -> failwith "Ouvar in pp_format_o_ascii"
-and pp_format_base_effect_ascii (BE_aux(e,l)) =
- match e with
- | BE_rreg -> "rreg"
- | BE_wreg -> "wreg"
- | BE_rmem -> "rmem"
- | BE_wmem -> "wmem"
- | BE_wmv -> "wmv"
- | BE_eamem -> "eamem"
- | BE_barr -> "barr"
- | BE_depend -> "depend"
- | BE_undef -> "undef"
- | BE_unspec -> "unspec"
- | BE_nondet -> "nondet"
- | BE_lset -> "lset"
- | BE_lret -> "lret"
- | BE_escape -> "escape"
-
-and pp_format_nes_ascii nes =
- list_format ", " pp_format_ne_ascii nes
-
-and pp_format_ne_ascii ne =
- match ne with
- | Lt(_,_,n1,n2) -> pp_format_n_ascii n1 ^ " < " ^ pp_format_n_ascii n2
- | LtEq(_,_,n1,n2) -> pp_format_n_ascii n1 ^ " <= " ^ pp_format_n_ascii n2
- | NtEq(_,n1,n2) -> pp_format_n_ascii n1 ^ " != " ^ pp_format_n_ascii n2
- | Eq(_,n1,n2) -> pp_format_n_ascii n1 ^ " = " ^ pp_format_n_ascii n2
- | GtEq(_,_,n1,n2) -> pp_format_n_ascii n1 ^ " >= " ^ pp_format_n_ascii n2
- | Gt(_,_,n1,n2) -> pp_format_n_ascii n1 ^ " > " ^ pp_format_n_ascii n2
- | In(_,i,ns) | InS(_,{nexp=Nvar i},ns) ->
- i ^ " IN {" ^ (list_format ", " string_of_int ns)^ "}"
- | InS(_,_,ns) -> (* when the variable has been replaced by a unification variable, we use this *)
- failwith "InS in pp_format_nes_ascii" (*"(Nec_in \"fresh\" [" ^ (list_format "; " string_of_int ns)^ "])"*)
- | Predicate(_,n1,n2) -> "flow_constraints(" ^ pp_format_ne_ascii n1 ^", "^ pp_format_ne_ascii n2 ^")"
- | CondCons(_,_,_,nes_c,nes_t) ->
- failwith "CondCons in pp_format_nes_ascii" (*"(Nec_cond " ^ (pp_format_nes nes_c) ^ " " ^ (pp_format_nes nes_t) ^ ")"*)
- | BranchCons(_,_,nes_b) ->
- failwith "BranchCons in pp_format_nes_ascii" (*"(Nec_branch " ^ (pp_format_nes nes_b) ^ ")"*)
-
-
-
-let rec pp_format_annot_ascii = function
- | NoTyp -> "Nothing"
- | Base((targs,t),tag,nes,efct,efctsum,_) ->
- (*TODO print out bindings for use in pattern match in interpreter*)
- (match tag with External (Some s) -> "("^s^") " | _ -> "") ^
- (match (targs,nes) with ([],[]) -> "\n" | _ ->
- "forall " ^ list_format ", " (function (i,k) -> kind_to_string k ^" '"^ i) targs ^
- (match nes with [] -> "" | _ -> ", " ^ pp_format_nes_ascii nes)
- ^ ".\n") ^ " "
- ^ pp_format_t_ascii t
- ^ "\n"
-(*
-^ " ********** " ^ pp_format_tag tag ^ ", " ^ pp_format_nes nes ^ ", " ^
- pp_format_e_lem efct ^ ", " ^ pp_format_e_lem efctsum ^ "))"
-*)
- | Overload (tannot, return_type_overloading_allowed, tannots) ->
- (*pp_format_annot_ascii tannot*) "\n" ^ String.concat "" (List.map (function tannot' -> " " ^ pp_format_annot_ascii tannot' ) tannots)
-
-
-
-
-
-
-(****************************************************************************
- * PPrint-based source-to-source pretty printer
-****************************************************************************)
-
-open PPrint
-
-let doc_id (Id_aux(i,_)) =
- match i with
- | Id i -> string 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 [string "deinfix"; string x; empty])
-
-let doc_var (Kid_aux(Var v,_)) = string v
-
-let doc_int i = string (string_of_int i)
-
-let doc_bkind (BK_aux(k,_)) =
- string (match k with
- | BK_type -> "Type"
- | BK_nat -> "Nat"
- | BK_order -> "Order"
- | BK_effect -> "Effect")
-
-let doc_op symb a b = infix 2 1 symb a b
-let doc_unop symb a = prefix 2 1 symb a
-
-let pipe = string "|"
-let arrow = string "->"
-let dotdot = string ".."
-let coloneq = string ":="
-let lsquarebar = string "[|"
-let rsquarebar = string "|]"
-let squarebars = enclose lsquarebar rsquarebar
-let lsquarebarbar = string "[||"
-let rsquarebarbar = string "||]"
-let squarebarbars = enclose lsquarebarbar rsquarebarbar
-let lsquarecolon = string "[:"
-let rsquarecolon = string ":]"
-let squarecolons = enclose lsquarecolon rsquarecolon
-let lcomment = string "(*"
-let rcomment = string "*)"
-let comment = enclose lcomment rcomment
-let string_lit = enclose dquote dquote
-let spaces op = enclose space space op
-let semi_sp = semi ^^ space
-let comma_sp = comma ^^ space
-let colon_sp = spaces colon
-
-let doc_kind (K_aux(K_kind(klst),_)) =
- separate_map (spaces arrow) doc_bkind klst
-
-let doc_effect (BE_aux (e,_)) =
- string (match e with
- | BE_rreg -> "rreg"
- | BE_wreg -> "wreg"
- | BE_rmem -> "rmem"
- | BE_wmem -> "wmem"
- | BE_wmv -> "wmv"
- | BE_eamem -> "eamem"
- | BE_barr -> "barr"
- | BE_depend -> "depend"
- | BE_escape -> "escape"
- | BE_undef -> "undef"
- | BE_unspec -> "unspec"
- | BE_nondet -> "nondet")
-
-let doc_effects (Effect_aux(e,_)) = match e with
- | Effect_var v -> doc_var v
- | Effect_set [] -> string "pure"
- | Effect_set s -> braces (separate_map comma_sp doc_effect s)
-
-let doc_ord (Ord_aux(o,_)) = match o with
- | Ord_var v -> doc_var v
- | Ord_inc -> string "inc"
- | Ord_dec -> string "dec"
-
-let doc_typ, doc_atomic_typ, doc_nexp =
- (* following the structure of parser for precedence *)
- let rec typ ty = fn_typ ty
- and fn_typ ((Typ_aux (t, _)) as ty) = match t with
- | Typ_fn(arg,ret,efct) ->
- separate space [tup_typ arg; arrow; fn_typ ret; string "effect"; doc_effects efct]
- | _ -> tup_typ ty
- and tup_typ ((Typ_aux (t, _)) as ty) = match t with
- | Typ_tup typs -> parens (separate_map comma_sp app_typ typs)
- | _ -> app_typ ty
- and app_typ ((Typ_aux (t, _)) as ty) = match t with
- (*TODO Need to un bid-endian-ify this here, since both can transform to the shorthand, especially with <: and :> *)
- (* Special case simple vectors to improve legibility
- * XXX we assume big-endian here, as usual *)
- | Typ_app(Id_aux (Id "vector", _), [
- Typ_arg_aux(Typ_arg_nexp (Nexp_aux(Nexp_constant n, _)), _);
- Typ_arg_aux(Typ_arg_nexp (Nexp_aux(Nexp_constant m, _)), _);
- Typ_arg_aux (Typ_arg_order (Ord_aux (Ord_inc, _)), _);
- Typ_arg_aux (Typ_arg_typ (Typ_aux (Typ_id id, _)), _)]) ->
- (doc_id id) ^^ (brackets (if n = 0 then doc_int m else doc_op colon (doc_int n) (doc_int (n+m-1))))
- | Typ_app(Id_aux (Id "vector", _), [
- Typ_arg_aux(Typ_arg_nexp (Nexp_aux(Nexp_constant n, _)), _);
- Typ_arg_aux(Typ_arg_nexp (Nexp_aux(Nexp_constant m, _)), _);
- Typ_arg_aux (Typ_arg_order (Ord_aux (Ord_dec, _)), _);
- Typ_arg_aux (Typ_arg_typ (Typ_aux (Typ_id id, _)), _)]) ->
- (doc_id id) ^^ (brackets (if n = m-1 then doc_int m else doc_op colon (doc_int n) (doc_int (m+1 -n))))
- | Typ_app(Id_aux (Id "vector", _), [
- Typ_arg_aux(Typ_arg_nexp
- (Nexp_aux(Nexp_minus (Nexp_aux(Nexp_constant n, _),
- Nexp_aux(Nexp_constant 1, _)),_)),_);
- Typ_arg_aux(Typ_arg_nexp (Nexp_aux(Nexp_constant m, _)), _);
- Typ_arg_aux (Typ_arg_order (Ord_aux (Ord_dec, _)), _);
- Typ_arg_aux (Typ_arg_typ (Typ_aux (Typ_id id, _)), _)]) ->
- (doc_id id) ^^ (brackets (if n = m then doc_int m else doc_op colon (doc_int m) (doc_int (n-1))))
- | Typ_app(Id_aux (Id "vector", _), [
- Typ_arg_aux(Typ_arg_nexp
- (Nexp_aux(Nexp_minus (n', Nexp_aux((Nexp_constant 1), _)),_) as n_n),_);
- Typ_arg_aux(Typ_arg_nexp m_nexp, _);
- Typ_arg_aux (Typ_arg_order (Ord_aux (Ord_dec, _)), _);
- Typ_arg_aux (Typ_arg_typ (Typ_aux (Typ_id id, _)), _)]) ->
- (doc_id id) ^^ (brackets (if n' = m_nexp then nexp m_nexp else doc_op colon (nexp m_nexp) (nexp n_n)))
- | Typ_app(Id_aux (Id "vector", _), [
- Typ_arg_aux(Typ_arg_nexp
- (Nexp_aux(Nexp_sum (n', Nexp_aux((Nexp_constant -1), _)),_) as n_n),_);
- Typ_arg_aux(Typ_arg_nexp m_nexp, _);
- Typ_arg_aux (Typ_arg_order (Ord_aux (Ord_dec, _)), _);
- Typ_arg_aux (Typ_arg_typ (Typ_aux (Typ_id id, _)), _)]) ->
- (doc_id id) ^^ (brackets (if n' = m_nexp then nexp m_nexp else doc_op colon (nexp m_nexp) (nexp n_n)))
- | Typ_app(Id_aux (Id "range", _), [
- Typ_arg_aux(Typ_arg_nexp (Nexp_aux(Nexp_constant n, _)), _);
- Typ_arg_aux(Typ_arg_nexp m, _);]) ->
- (squarebars (if n = 0 then nexp m else doc_op colon (doc_int n) (nexp m)))
- | Typ_app(Id_aux (Id "atom", _), [Typ_arg_aux(Typ_arg_nexp n,_)]) ->
- (squarecolons (nexp n))
- | Typ_app(id,args) ->
- (* trailing space to avoid >> token in case of nested app types *)
- (doc_id id) ^^ (angles (separate_map comma_sp doc_typ_arg args)) ^^ space
- | _ -> atomic_typ ty (* for simplicity, skip vec_typ - which is only sugar *)
- and atomic_typ ((Typ_aux (t, _)) as ty) = match t with
- | Typ_id id -> doc_id 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 *)
- group (parens (typ ty))
- and doc_typ_arg (Typ_arg_aux(t,_)) = match t with
- (* Be careful here because typ_arg is implemented as nexp in the
- * parser - in practice falling through app_typ after all the proper nexp
- * cases; so Typ_arg_typ has the same precedence as a Typ_app *)
- | Typ_arg_typ t -> app_typ t
- | Typ_arg_nexp n -> nexp n
- | Typ_arg_order o -> doc_ord o
- | Typ_arg_effect e -> doc_effects e
-
- (* same trick to handle precedence of nexp *)
- and nexp ne = sum_typ ne
- and sum_typ ((Nexp_aux(n,_)) as ne) = match n with
- | Nexp_sum(n1,n2) -> doc_op plus (sum_typ n1) (star_typ n2)
- | Nexp_minus(n1,n2) -> doc_op minus (sum_typ n1) (star_typ n2)
- | _ -> star_typ ne
- and star_typ ((Nexp_aux(n,_)) as ne) = match n with
- | Nexp_times(n1,n2) -> doc_op star (star_typ n1) (exp_typ n2)
- | _ -> exp_typ ne
- and exp_typ ((Nexp_aux(n,_)) as ne) = match n with
- | Nexp_exp n1 -> doc_unop (string "2**") (atomic_nexp_typ n1)
- | _ -> neg_typ ne
- and neg_typ ((Nexp_aux(n,_)) as ne) = match n with
- | Nexp_neg n1 ->
- (* XXX this is not valid Sail, only an internal representation -
- * work around by commenting it *)
- let minus = concat [string "(*"; minus; string "*)"] in
- minus ^^ (atomic_nexp_typ n1)
- | _ -> atomic_nexp_typ ne
- and atomic_nexp_typ ((Nexp_aux(n,_)) as ne) = match n with
- | Nexp_var v -> doc_var v
- | Nexp_id i -> doc_id i
- | Nexp_constant i -> doc_int i
- | Nexp_neg _ | Nexp_exp _ | Nexp_times _ | Nexp_sum _ | Nexp_minus _->
- group (parens (nexp ne))
-
- (* expose doc_typ, doc_atomic_typ and doc_nexp *)
- in typ, atomic_typ, nexp
-
-let doc_nexp_constraint (NC_aux(nc,_)) = match nc with
- | NC_fixed(n1,n2) -> doc_op equals (doc_nexp n1) (doc_nexp n2)
- | NC_bounded_ge(n1,n2) -> doc_op (string ">=") (doc_nexp n1) (doc_nexp n2)
- | NC_bounded_le(n1,n2) -> doc_op (string "<=") (doc_nexp n1) (doc_nexp n2)
- | NC_nat_set_bounded(v,bounds) ->
- doc_op (string "IN") (doc_var v)
- (braces (separate_map comma_sp doc_int bounds))
-
-let doc_qi (QI_aux(qi,_)) = match qi with
- | QI_const n_const -> doc_nexp_constraint n_const
- | QI_id(KOpt_aux(ki,_)) ->
- match ki with
- | KOpt_none v -> doc_var v
- | KOpt_kind(k,v) -> separate space [doc_kind k; doc_var v]
-
-(* typ_doc is the doc for the type being quantified *)
-let doc_typquant (TypQ_aux(tq,_)) typ_doc = match tq with
- | TypQ_no_forall -> typ_doc
- | TypQ_tq [] -> failwith "TypQ_tq with empty list"
- | TypQ_tq qlist ->
- (* include trailing break because the caller doesn't know if tq is empty *)
- doc_op dot
- (separate space [string "forall"; separate_map comma_sp doc_qi qlist])
- typ_doc
-
-let doc_typscm (TypSchm_aux(TypSchm_ts(tq,t),_)) =
- (doc_typquant tq (doc_typ t))
-
-let doc_typscm_atomic (TypSchm_aux(TypSchm_ts(tq,t),_)) =
- (doc_typquant tq (doc_atomic_typ t))
-
-let doc_lit (L_aux(l,_)) =
- utf8string (match l with
- | L_unit -> "()"
- | L_zero -> "bitzero"
- | L_one -> "bitone"
- | L_true -> "true"
- | L_false -> "false"
- | L_num i -> string_of_int i
- | L_hex n -> "0x" ^ n
- | L_bin n -> "0b" ^ n
- | L_undef -> "undefined"
- | L_string s -> "\"" ^ s ^ "\"")
-
-let doc_pat, doc_atomic_pat =
- let rec pat pa = pat_colons pa
- and pat_colons ((P_aux(p,l)) as pa) = match p with
- (* XXX add leading indentation if not flat - we need to define our own
- * combinator for that *)
- | P_vector_concat pats -> separate_map (space ^^ colon ^^ break 1) atomic_pat pats
- | _ -> app_pat pa
- and app_pat ((P_aux(p,l)) as pa) = match p with
- | P_app(id, ((_ :: _) as pats)) -> doc_unop (doc_id id) (parens (separate_map comma_sp atomic_pat pats))
- | _ -> atomic_pat pa
- and atomic_pat ((P_aux(p,(l,annot))) as pa) = match p with
- | P_lit lit -> doc_lit lit
- | P_wild -> underscore
- | P_id id -> doc_id id
- | P_as(p,id) -> parens (separate space [pat p; string "as"; doc_id id])
- | P_typ(typ,p) -> separate space [parens (doc_typ typ); atomic_pat p]
- | P_app(id,[]) -> doc_id id
- | P_record(fpats,_) -> braces (separate_map semi_sp fpat fpats)
- | P_vector pats -> brackets (separate_map comma_sp atomic_pat pats)
- | P_vector_indexed ipats -> brackets (separate_map comma_sp npat ipats)
- | P_tup pats -> parens (separate_map comma_sp atomic_pat pats)
- | P_list pats -> squarebarbars (separate_map semi_sp atomic_pat pats)
- | P_app(_, _ :: _) | P_vector_concat _ ->
- group (parens (pat pa))
- and fpat (FP_aux(FP_Fpat(id,fpat),_)) = doc_op equals (doc_id id) (pat fpat)
- and npat (i,p) = doc_op equals (doc_int i) (pat p)
-
- (* expose doc_pat and doc_atomic_pat *)
- in pat, atomic_pat
-
-let doc_exp, doc_let =
- let rec exp e = group (or_exp e)
- and or_exp ((E_aux(e,_)) as expr) = match e with
- | E_app_infix(l,(Id_aux(Id ("|" | "||"),_) as op),r) ->
- doc_op (doc_id op) (and_exp l) (or_exp r)
- | _ -> and_exp expr
- and and_exp ((E_aux(e,_)) as expr) = match e with
- | E_app_infix(l,(Id_aux(Id ("&" | "&&"),_) as op),r) ->
- doc_op (doc_id op) (eq_exp l) (and_exp r)
- | _ -> eq_exp expr
- and eq_exp ((E_aux(e,_)) as expr) = match e with
- | E_app_infix(l,(Id_aux(Id (
- (* XXX this is not very consistent - is the parser bogus here? *)
- "=" | "==" | "!="
- | ">=" | ">=_s" | ">=_u" | ">" | ">_s" | ">_u"
- | "<=" | "<=_s" | "<" | "<_s" | "<_si" | "<_u"
- ),_) as op),r) ->
- doc_op (doc_id op) (eq_exp l) (at_exp r)
- (* XXX assignment should not have the same precedence as equal etc. *)
- | E_assign(le,exp) -> doc_op coloneq (doc_lexp le) (at_exp exp)
- | _ -> at_exp expr
- and at_exp ((E_aux(e,_)) as expr) = match e with
- | E_app_infix(l,(Id_aux(Id ("@" | "^^" | "^" | "~^"),_) as op),r) ->
- doc_op (doc_id op) (cons_exp l) (at_exp r)
- | _ -> cons_exp expr
- and cons_exp ((E_aux(e,_)) as expr) = match e with
- | E_vector_append(l,r) ->
- doc_op colon (shift_exp l) (cons_exp r)
- | E_cons(l,r) ->
- doc_op colon (shift_exp l) (cons_exp r)
- | _ -> shift_exp expr
- and shift_exp ((E_aux(e,_)) as expr) = match e with
- | E_app_infix(l,(Id_aux(Id (">>" | ">>>" | "<<" | "<<<"),_) as op),r) ->
- doc_op (doc_id op) (shift_exp l) (plus_exp r)
- | _ -> plus_exp expr
- and plus_exp ((E_aux(e,_)) as expr) = match e with
- | E_app_infix(l,(Id_aux(Id ("+" | "-" | "+_s" | "-_s"),_) as op),r) ->
- doc_op (doc_id op) (plus_exp l) (star_exp r)
- | _ -> star_exp expr
- and star_exp ((E_aux(e,_)) as expr) = match e with
- | E_app_infix(l,(Id_aux(Id (
- "*" | "/"
- | "div" | "quot" | "quot_s" | "rem" | "mod"
- | "*_s" | "*_si" | "*_u" | "*_ui"),_) as op),r) ->
- doc_op (doc_id op) (star_exp l) (starstar_exp r)
- | _ -> starstar_exp expr
- and starstar_exp ((E_aux(e,_)) as expr) = match e with
- | E_app_infix(l,(Id_aux(Id "**",_) as op),r) ->
- doc_op (doc_id op) (starstar_exp l) (app_exp r)
- | E_if _ | E_for _ | E_let _ -> right_atomic_exp expr
- | _ -> app_exp expr
- and right_atomic_exp ((E_aux(e,_)) as expr) = match e with
- (* Special case: omit "else ()" when the else branch is empty. *)
- | E_if(c,t,E_aux(E_block [], _)) ->
- string "if" ^^ space ^^ group (exp c) ^/^
- string "then" ^^ space ^^ group (exp t)
- | E_if(c,t,e) ->
- string "if" ^^ space ^^ group (exp c) ^/^
- string "then" ^^ space ^^ group (exp t) ^/^
- string "else" ^^ space ^^ group (exp e)
- | E_for(id,exp1,exp2,exp3,order,exp4) ->
- string "foreach" ^^ space ^^
- group (parens (
- separate (break 1) [
- doc_id id;
- string "from " ^^ atomic_exp exp1;
- string "to " ^^ atomic_exp exp2;
- string "by " ^^ atomic_exp exp3;
- string "in " ^^ doc_ord order
- ]
- )) ^/^
- exp exp4
- | E_let(leb,e) -> doc_op (string "in") (let_exp leb) (exp e)
- | _ -> group (parens (exp expr))
- and app_exp ((E_aux(e,_)) as expr) = match e with
- | E_app(f,args) ->
- (doc_id f) ^^ (parens (separate_map comma exp args))
- | _ -> vaccess_exp expr
- and vaccess_exp ((E_aux(e,_)) as expr) = match e with
- | E_vector_access(v,e) ->
- atomic_exp v ^^ brackets (exp e)
- | E_vector_subrange(v,e1,e2) ->
- atomic_exp v ^^ brackets (doc_op dotdot (exp e1) (exp e2))
- | _ -> field_exp expr
- and field_exp ((E_aux(e,_)) as expr) = match e with
- | E_field(fexp,id) -> atomic_exp fexp ^^ dot ^^ doc_id id
- | _ -> atomic_exp expr
- and atomic_exp ((E_aux(e,_)) as expr) = match e with
- (* Special case: an empty block is equivalent to unit, but { } would
- * be parsed as a struct. *)
- | E_block [] -> string "()"
- | E_block exps ->
- let exps_doc = separate_map (semi ^^ hardline) exp exps in
- surround 2 1 lbrace exps_doc rbrace
- | E_nondet exps ->
- let exps_doc = separate_map (semi ^^ hardline) exp exps in
- string "nondet" ^^ space ^^ (surround 2 1 lbrace exps_doc rbrace)
- | E_comment s -> string ("(*" ^ s ^ "*) ()")
- | E_comment_struc e -> string "(*" ^^ exp e ^^ string "*) ()"
- | E_id id -> doc_id id
- | E_lit lit -> doc_lit lit
- | E_cast(typ,e) -> prefix 2 1 (parens (doc_typ typ)) (group (atomic_exp e))
- | E_internal_cast((_,NoTyp),e) -> atomic_exp e
- | E_internal_cast((_,Base((_,t),_,_,_,_,bindings)), (E_aux(_,(_,eannot)) as e)) ->
- (match t.t,eannot with
- (* XXX I don't understand why we can hide the internal cast here
- AAA Because an internal cast between vectors is only generated to reset the base access;
- the type checker generates far more than are needed and they're pruned off here, after constraint resolution *)
- | Tapp("vector",[TA_nexp n1;_;_;_]),Base((_,{t=Tapp("vector",[TA_nexp n2;_;_;_])}),_,_,_,_,_)
- when nexp_eq n1 n2 -> atomic_exp e
- | _ -> prefix 2 1 (parens (doc_typ (t_to_typ t))) (group (atomic_exp e)))
- | E_tuple exps ->
- parens (separate_map comma exp exps)
- | E_record(FES_aux(FES_Fexps(fexps,_),_)) ->
- (* XXX E_record is not handled by parser currently
- AAA The parser can't handle E_record due to ambiguity with blocks; initial_check looks for blocks that are all field assignments and converts *)
- braces (separate_map semi_sp doc_fexp fexps)
- | E_record_update(e,(FES_aux(FES_Fexps(fexps,_),_))) ->
- braces (doc_op (string "with") (exp e) (separate_map semi_sp doc_fexp fexps))
- | E_vector exps ->
- let default_print _ = brackets (separate_map comma exp exps) in
- (match exps with
- | [] -> default_print ()
- | E_aux(e,_)::es ->
- (match e with
- | E_lit (L_aux(L_one, _)) | E_lit (L_aux(L_zero, _)) ->
- utf8string
- ("0b" ^
- (List.fold_right (fun (E_aux( e,_)) rst ->
- (match e with
- | E_lit(L_aux(l, _)) ->
- ((match l with | L_one -> "1" | L_zero -> "0" | L_undef -> "u" | _ -> assert false) ^ rst)
- | _ -> assert false)) exps ""))
- | _ -> default_print ()))
- | E_vector_indexed (iexps, (Def_val_aux (default,_))) ->
- let default_string =
- (match default with
- | Def_val_empty -> string ""
- | Def_val_dec e -> concat [semi; space; string "default"; equals; (exp e)]) in
- let iexp (i,e) = doc_op equals (doc_int i) (exp e) in
- brackets (concat [(separate_map comma iexp iexps); default_string])
- | E_vector_update(v,e1,e2) ->
- brackets (doc_op (string "with") (exp v) (doc_op equals (atomic_exp e1) (exp e2)))
- | E_vector_update_subrange(v,e1,e2,e3) ->
- brackets (
- doc_op (string "with") (exp v)
- (doc_op equals (atomic_exp e1 ^^ colon ^^ atomic_exp e2) (exp e3)))
- | E_list exps ->
- squarebarbars (separate_map comma exp exps)
- | E_case(e,pexps) ->
- let opening = separate space [string "switch"; exp e; lbrace] in
- let cases = separate_map (break 1) doc_case pexps in
- surround 2 1 opening cases rbrace
- | E_sizeof n ->
- separate space [string "sizeof"; doc_nexp n]
- | E_exit e ->
- separate space [string "exit"; atomic_exp e;]
- | E_return e ->
- separate space [string "return"; atomic_exp e;]
- | E_assert(c,m) ->
- separate space [string "assert"; parens (separate comma [exp c; exp m])]
- (* adding parens and loop for lower precedence *)
- | E_app (_, _)|E_vector_access (_, _)|E_vector_subrange (_, _, _)
- | E_cons (_, _)|E_field (_, _)|E_assign (_, _)
- | E_if _ | E_for _ | E_let _
- | E_vector_append _
- | E_app_infix (_,
- (* for every app_infix operator caught at a higher precedence,
- * we need to wrap around with parens *)
- (Id_aux(Id("|" | "||"
- | "&" | "&&"
- | "=" | "==" | "!="
- | ">=" | ">=_s" | ">=_u" | ">" | ">_s" | ">_u"
- | "<=" | "<=_s" | "<" | "<_s" | "<_si" | "<_u"
- | "@" | "^^" | "^" | "~^"
- | ">>" | ">>>" | "<<" | "<<<"
- | "+" | "-" | "+_s" | "-_s"
- | "*" | "/"
- | "div" | "quot" | "quot_s" | "rem" | "mod"
- | "*_s" | "*_si" | "*_u" | "*_ui"
- | "**"), _))
- , _) ->
- group (parens (exp expr))
- (* XXX default precedence for app_infix? *)
- | E_app_infix(l,op,r) ->
- failwith ("unexpected app_infix operator " ^ (pp_format_id op))
- (* doc_op (doc_id op) (exp l) (exp r) *)
- | E_comment s -> comment (string s)
- | E_comment_struc e -> comment (exp e)
- | E_internal_exp((l, Base((_,t),_,_,_,_,bindings))) -> (*TODO use bindings, and other params*)
- (match t.t with
- | Tapp("register",[TA_typ {t=Tapp("vector",[TA_nexp _;TA_nexp r;_;_])}])
- | Tapp("vector",[TA_nexp _;TA_nexp r;_;_]) ->
- (match r.nexp with
- | Nvar v -> utf8string v
- | Nconst bi -> utf8string (Big_int.string_of_big_int bi)
- | _ -> raise (Reporting_basic.err_unreachable l
- ("Internal exp given vector without known length, instead given " ^ n_to_string r)))
- | Tapp("implicit",[TA_nexp r]) ->
- (match r.nexp with
- | Nconst bi -> utf8string (Big_int.string_of_big_int bi)
- | Nvar v -> utf8string v
- | _ -> raise (Reporting_basic.err_unreachable l "Internal exp given implicit without var or const"))
- | _ -> raise (Reporting_basic.err_unreachable l ("Internal exp given non-vector, non-implicit " ^ t_to_string t)))
- | E_internal_exp_user _ -> raise (Reporting_basic.err_unreachable Unknown ("internal_exp_user not rewritten away"))
- | E_internal_cast ((_, Overload (_, _,_ )), _) | E_internal_exp _ -> assert false
-
- and let_exp (LB_aux(lb,_)) = match lb with
- | LB_val_explicit(ts,pat,e) ->
- (match ts with
- | TypSchm_aux (TypSchm_ts (TypQ_aux (TypQ_no_forall,_),_),_) ->
- prefix 2 1
- (separate space [string "let"; parens (doc_typscm_atomic ts); doc_atomic_pat pat; equals])
- (atomic_exp e)
- | _ ->
- prefix 2 1
- (separate space [string "let"; doc_typscm_atomic ts; doc_atomic_pat pat; equals])
- (atomic_exp e))
- | LB_val_implicit(pat,e) ->
- prefix 2 1
- (separate space [string "let"; doc_atomic_pat pat; equals])
- (atomic_exp e)
-
- and doc_fexp (FE_aux(FE_Fexp(id,e),_)) = doc_op equals (doc_id id) (exp e)
-
- and doc_case (Pat_aux(Pat_exp(pat,e),_)) =
- doc_op arrow (separate space [string "case"; doc_atomic_pat pat]) (group (exp e))
-
- (* lexps are parsed as eq_exp - we need to duplicate the precedence
- * structure for them *)
- and doc_lexp le = app_lexp le
- and app_lexp ((LEXP_aux(lexp,_)) as le) = match lexp with
- | LEXP_memory(id,args) -> doc_id id ^^ parens (separate_map comma exp args)
- | _ -> vaccess_lexp le
- and vaccess_lexp ((LEXP_aux(lexp,_)) as le) = match lexp with
- | LEXP_vector(v,e) -> atomic_lexp v ^^ brackets (exp e)
- | LEXP_vector_range(v,e1,e2) ->
- atomic_lexp v ^^ brackets (exp e1 ^^ dotdot ^^ exp e2)
- | _ -> field_lexp le
- and field_lexp ((LEXP_aux(lexp,_)) as le) = match lexp with
- | LEXP_field(v,id) -> atomic_lexp v ^^ dot ^^ doc_id id
- | _ -> atomic_lexp le
- and atomic_lexp ((LEXP_aux(lexp,_)) as le) = match lexp with
- | LEXP_id id -> doc_id id
- | LEXP_cast(typ,id) -> prefix 2 1 (parens (doc_typ typ)) (doc_id id)
- | LEXP_memory _ | LEXP_vector _ | LEXP_vector_range _
- | LEXP_field _ -> group (parens (doc_lexp le))
- | LEXP_tup tups -> parens (separate_map comma doc_lexp tups)
-
- (* expose doc_exp and doc_let *)
- in exp, let_exp
-
-let doc_default (DT_aux(df,_)) = match df with
- | DT_kind(bk,v) -> separate space [string "default"; doc_bkind bk; doc_var v]
- | DT_typ(ts,id) -> separate space [string "default"; doc_typscm ts; doc_id id]
- | DT_order(ord) -> separate space [string "default"; string "order"; doc_ord ord]
-
-let doc_spec (VS_aux(v,_)) = match v with
- | VS_val_spec(ts,id) ->
- separate space [string "val"; doc_typscm ts; doc_id id]
- | VS_extern_no_rename(ts,id) ->
- separate space [string "val"; string "extern"; doc_typscm ts; doc_id id]
- | VS_extern_spec(ts,id,s) ->
- separate space [string "val"; string "extern"; doc_typscm ts;
- doc_op equals (doc_id id) (dquotes (string s))]
-
-let doc_namescm (Name_sect_aux(ns,_)) = match ns with
- | Name_sect_none -> empty
- (* include leading space because the caller doesn't know if ns is
- * empty, and trailing break already added by the following equals *)
- | Name_sect_some s -> space ^^ brackets (doc_op equals (string "name") (dquotes (string s)))
-
-let rec doc_range (BF_aux(r,_)) = match r with
- | BF_single i -> doc_int i
- | BF_range(i1,i2) -> doc_op dotdot (doc_int i1) (doc_int i2)
- | BF_concat(ir1,ir2) -> (doc_range ir1) ^^ comma ^^ (doc_range ir2)
-
-let doc_type_union (Tu_aux(typ_u,_)) = match typ_u with
- | Tu_ty_id(typ,id) -> separate space [doc_typ typ; doc_id id]
- | Tu_id id -> doc_id id
-
-let doc_typdef (TD_aux(td,_)) = match td with
- | TD_abbrev(id,nm,typschm) ->
- doc_op equals (concat [string "typedef"; space; doc_id id; doc_namescm nm]) (doc_typscm typschm)
- | TD_record(id,nm,typq,fs,_) ->
- let f_pp (typ,id) = concat [doc_typ typ; space; doc_id id; semi] in
- let fs_doc = group (separate_map (break 1) f_pp fs) in
- doc_op equals
- (concat [string "typedef"; space; doc_id id; doc_namescm nm])
- (string "const struct" ^^ space ^^ doc_typquant typq (braces fs_doc))
- | TD_variant(id,nm,typq,ar,_) ->
- let ar_doc = group (separate_map (semi ^^ break 1) doc_type_union ar) in
- doc_op equals
- (concat [string "typedef"; space; doc_id id; doc_namescm nm])
- (string "const union" ^^ space ^^ doc_typquant typq (braces ar_doc))
- | TD_enum(id,nm,enums,_) ->
- let enums_doc = group (separate_map (semi ^^ break 1) doc_id enums) in
- doc_op equals
- (concat [string "typedef"; space; doc_id id; doc_namescm nm])
- (string "enumerate" ^^ space ^^ braces enums_doc)
- | TD_register(id,n1,n2,rs) ->
- let doc_rid (r,id) = separate space [doc_range r; colon; doc_id id] ^^ semi in
- let doc_rids = group (separate_map (break 1) doc_rid rs) in
- doc_op equals
- (string "typedef" ^^ space ^^ doc_id id)
- (separate space [
- string "register bits";
- brackets (doc_nexp n1 ^^ colon ^^ doc_nexp n2);
- braces doc_rids;
- ])
-
-let doc_kindef (KD_aux(kd,_)) = match kd with
- | KD_abbrev(kind,id,nm,typschm) ->
- doc_op equals (concat [string "def"; space; doc_kind kind; space; doc_id id; doc_namescm nm]) (doc_typscm typschm)
- | KD_nabbrev(kind,id,nm,n) ->
- doc_op equals (concat [string "def"; space; doc_kind kind; space; doc_id id; doc_namescm nm]) (doc_nexp n)
- | KD_record(kind,id,nm,typq,fs,_) ->
- let f_pp (typ,id) = concat [doc_typ typ; space; doc_id id; semi] in
- let fs_doc = group (separate_map (break 1) f_pp fs) in
- doc_op equals
- (concat [string "def"; space;doc_kind kind; space; doc_id id; doc_namescm nm])
- (string "const struct" ^^ space ^^ doc_typquant typq (braces fs_doc))
- | KD_variant(kind,id,nm,typq,ar,_) ->
- let ar_doc = group (separate_map (semi ^^ break 1) doc_type_union ar) in
- doc_op equals
- (concat [string "def"; space; doc_kind kind; space; doc_id id; doc_namescm nm])
- (string "const union" ^^ space ^^ doc_typquant typq (braces ar_doc))
- | KD_enum(kind,id,nm,enums,_) ->
- let enums_doc = group (separate_map (semi ^^ break 1) doc_id enums) in
- doc_op equals
- (concat [string "def"; space; doc_kind kind; space; doc_id id; doc_namescm nm])
- (string "enumerate" ^^ space ^^ braces enums_doc)
- | KD_register(kind,id,n1,n2,rs) ->
- let doc_rid (r,id) = separate space [doc_range r; colon; doc_id id] ^^ semi in
- let doc_rids = group (separate_map (break 1) doc_rid rs) in
- doc_op equals
- (string "def" ^^ space ^^ doc_kind kind ^^ space ^^ doc_id id)
- (separate space [
- string "register bits";
- brackets (doc_nexp n1 ^^ colon ^^ doc_nexp n2);
- braces doc_rids;
- ])
-
-
-let doc_rec (Rec_aux(r,_)) = match r with
- | Rec_nonrec -> empty
- (* include trailing space because caller doesn't know if we return
- * empty *)
- | Rec_rec -> string "rec" ^^ space
-
-let doc_tannot_opt (Typ_annot_opt_aux(t,_)) = match t with
- | Typ_annot_opt_some(tq,typ) -> doc_typquant tq (doc_typ typ)
-
-let doc_effects_opt (Effect_opt_aux(e,_)) = match e with
- | Effect_opt_pure -> string "pure"
- | Effect_opt_effect e -> doc_effects e
-
-let doc_funcl (FCL_aux(FCL_Funcl(id,pat,exp),_)) =
- group (doc_op equals (separate space [doc_id id; doc_atomic_pat pat]) (doc_exp exp))
-
-let doc_fundef (FD_aux(FD_function(r, typa, efa, fcls),_)) =
- match fcls with
- | [] -> failwith "FD_function with empty function list"
- | _ ->
- let sep = hardline ^^ string "and" ^^ space in
- let clauses = separate_map sep doc_funcl fcls in
- separate space ([string "function";
- doc_rec r ^^ doc_tannot_opt typa;]@
- (match efa with
- | Effect_opt_aux (Effect_opt_pure,_) -> []
- | _ -> [string "effect";
- doc_effects_opt efa;])
- @[clauses])
-
-let doc_alias (AL_aux (alspec,_)) =
- match alspec with
- | AL_subreg((RI_aux (RI_id id,_)),subid) -> doc_id id ^^ dot ^^ doc_id subid
- | AL_bit((RI_aux (RI_id id,_)),ac) -> doc_id id ^^ brackets (doc_exp ac)
- | AL_slice((RI_aux (RI_id id,_)),b,e) -> doc_id id ^^ brackets (doc_op dotdot (doc_exp b) (doc_exp e))
- | AL_concat((RI_aux (RI_id f,_)),(RI_aux (RI_id s,_))) -> doc_op colon (doc_id f) (doc_id s)
-
-let doc_dec (DEC_aux (reg,_)) =
- match reg with
- | DEC_reg(typ,id) -> separate space [string "register"; doc_typ typ; doc_id id]
- | DEC_alias(id,alspec) ->
- doc_op equals (string "register alias" ^^ space ^^ doc_id id) (doc_alias alspec)
- | DEC_typ_alias(typ,id,alspec) ->
- doc_op equals (string "register alias" ^^ space ^^ doc_typ typ) (doc_alias alspec)
-
-let doc_scattered (SD_aux (sdef, _)) = match sdef with
- | SD_scattered_function (r, typa, efa, id) ->
- separate space ([
- string "scattered function";
- doc_rec r ^^ doc_tannot_opt typa;]@
- (match efa with
- | Effect_opt_aux (Effect_opt_pure,_) -> []
- | _ -> [string "effect"; doc_effects_opt efa;])
- @[doc_id id])
- | SD_scattered_variant (id, ns, tq) ->
- doc_op equals
- (string "scattered typedef" ^^ space ^^ doc_id id ^^ doc_namescm ns)
- (string "const union" ^^ space ^^ (doc_typquant tq empty))
- | SD_scattered_funcl funcl ->
- string "function clause" ^^ space ^^ doc_funcl funcl
- | SD_scattered_unioncl (id, tu) ->
- separate space [string "union"; doc_id id;
- string "member"; doc_type_union tu]
- | SD_scattered_end id -> string "end" ^^ space ^^ doc_id id
-
-let rec doc_def def = group (match def with
- | DEF_default df -> doc_default df
- | DEF_spec v_spec -> doc_spec v_spec
- | DEF_type t_def -> doc_typdef t_def
- | DEF_kind k_def -> doc_kindef k_def
- | DEF_fundef f_def -> doc_fundef f_def
- | DEF_val lbind -> doc_let lbind
- | DEF_reg_dec dec -> doc_dec dec
- | DEF_scattered sdef -> doc_scattered sdef
- | DEF_comm (DC_comm s) -> comment (string s)
- | DEF_comm (DC_comm_struct d) -> comment (doc_def d)
- ) ^^ hardline
-
-let doc_defs (Defs(defs)) =
- separate_map hardline doc_def defs
-
-let print ?(len=100) channel doc = ToChannel.pretty 1. len channel doc
-let to_buf ?(len=100) buf doc = ToBuffer.pretty 1. len buf doc
-
-let pp_defs f d = print f (doc_defs d)
-let pp_exp b e = to_buf b (doc_exp e)
-let pat_to_string p =
- let b = Buffer.create 20 in
- to_buf b (doc_pat p);
- Buffer.contents b
-
-(****************************************************************************
- * PPrint-based sail-to-ocaml pretty printer
-****************************************************************************)
-
-let star_sp = star ^^ space
-
-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_ocaml (Id_aux(i,_)) =
- match i with
- | Id("bit") -> string "vbit"
- | Id i -> string ("_" ^ 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_ocaml_type (Id_aux(i,_)) =
- match i with
- | Id("bit") -> string "vbit"
- | Id i -> string ("_" ^ 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 (String.uncapitalize x); empty])
-
-let doc_id_ocaml_ctor n (Id_aux(i,_)) =
- match i with
- | Id("bit") -> string "vbit"
- | Id i -> string ((if n > 246 then "`" else "") ^ (String.capitalize 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 (String.capitalize x); empty])
-
-let doc_typ_ocaml, doc_atomic_typ_ocaml =
- (* following the structure of parser for precedence *)
- let rec typ ty = fn_typ ty
- and fn_typ ((Typ_aux (t, _)) as ty) = match t with
- | Typ_fn(arg,ret,efct) ->
- separate space [tup_typ arg; arrow; fn_typ ret]
- | _ -> tup_typ ty
- and tup_typ ((Typ_aux (t, _)) as ty) = match t with
- | Typ_tup typs -> parens (separate_map star app_typ typs)
- | _ -> app_typ ty
- and app_typ ((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 typ, _)]) ->
- string "value"
- | Typ_app(Id_aux (Id "range", _), [
- Typ_arg_aux(Typ_arg_nexp n, _);
- Typ_arg_aux(Typ_arg_nexp m, _);]) ->
- (string "number")
- | Typ_app(Id_aux (Id "atom", _), [Typ_arg_aux(Typ_arg_nexp n,_)]) ->
- (string "number")
- | Typ_app(id,args) ->
- (separate_map space doc_typ_arg_ocaml args) ^^ space ^^ (doc_id_ocaml_type id)
- | _ -> atomic_typ ty
- and atomic_typ ((Typ_aux (t, _)) as ty) = match t with
- | Typ_id id -> doc_id_ocaml_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 *)
- group (parens (typ ty))
- and doc_typ_arg_ocaml (Typ_arg_aux(t,_)) = match t with
- | Typ_arg_typ t -> app_typ t
- | Typ_arg_nexp n -> empty
- | Typ_arg_order o -> empty
- | Typ_arg_effect e -> empty
- in typ, atomic_typ
-
-let doc_lit_ocaml in_pat (L_aux(l,_)) =
- utf8string (match l with
- | L_unit -> "()"
- | L_zero -> "Vzero"
- | L_one -> "Vone"
- | L_true -> "Vone"
- | L_false -> "Vzero"
- | L_num i -> "(big_int_of_int " ^ (string_of_int i) ^ ")"
- | L_hex n -> "(num_to_vec " ^ ("0x" ^ n) ^ ")" (*shouldn't happen*)
- | L_bin n -> "(num_to_vec " ^ ("0b" ^ n) ^ ")" (*shouldn't happen*)
- | L_undef -> "Vundef"
- | L_string s -> "\"" ^ s ^ "\"")
-
-(* typ_doc is the doc for the type being quantified *)
-let doc_typquant_ocaml (TypQ_aux(tq,_)) typ_doc = typ_doc
-
-let doc_typscm_ocaml (TypSchm_aux(TypSchm_ts(tq,t),_)) =
- (doc_typquant tq (doc_typ_ocaml t))
-
-(*Note: vector concatenation, literal vectors, indexed vectors, and record should
- be removed prior to pp. The latter two have never yet been seen
-*)
-let doc_pat_ocaml =
- let rec pat pa = app_pat pa
- and app_pat ((P_aux(p,(l,annot))) as pa) = match p with
- | P_app(id, ((_ :: _) as pats)) ->
- (match annot with
- | Base(_,Constructor n,_,_,_,_) ->
- doc_unop (doc_id_ocaml_ctor n id) (parens (separate_map comma_sp pat pats))
- | _ -> empty)
- | P_lit lit -> doc_lit_ocaml true lit
- | P_wild -> underscore
- | P_id id -> doc_id_ocaml id
- | P_as(p,id) -> parens (separate space [pat p; string "as"; doc_id_ocaml id])
- | P_typ(typ,p) -> doc_op colon (pat p) (doc_typ_ocaml typ)
- | P_app(id,[]) ->
- (match annot with
- | Base(_,(Constructor n | Enum n),_,_,_,_) ->
- doc_id_ocaml_ctor n id
- | _ -> failwith "encountered unexpected P_app pattern")
- | P_vector pats ->
- let non_bit_print () =
- parens
- (separate space [string "VvectorR";
- parens (separate comma_sp [squarebars (separate_map semi pat pats);
- underscore;
- underscore])]) in
- (match annot with
- | Base(([],t),_,_,_,_,_) ->
- if is_bit_vector t
- then parens (separate space [string "Vvector";
- parens (separate comma_sp [squarebars (separate_map semi pat pats);
- underscore;
- underscore])])
- else non_bit_print()
- | _ -> non_bit_print ())
- | P_tup pats -> parens (separate_map comma_sp pat pats)
- | P_list pats -> brackets (separate_map semi pat pats) (*Never seen but easy in ocaml*)
- in pat
-
-let doc_exp_ocaml, doc_let_ocaml =
- let rec top_exp read_registers (E_aux (e, (_,annot))) =
- let exp = top_exp read_registers in
- match e with
- | E_assign((LEXP_aux(le_act,tannot) as le),e) ->
- (match annot with
- | Base(_,(Emp_local | Emp_set),_,_,_,_) ->
- (match le_act with
- | LEXP_id _ | LEXP_cast _ ->
- (*Setting local variable fully *)
- doc_op coloneq (doc_lexp_ocaml true le) (exp e)
- | LEXP_vector _ ->
- doc_op (string "<-") (doc_lexp_array_ocaml le) (exp e)
- | LEXP_vector_range _ ->
- doc_lexp_rwrite le e)
- | _ ->
- (match le_act with
- | LEXP_vector _ | LEXP_vector_range _ | LEXP_cast _ | LEXP_field _ | LEXP_id _ ->
- (doc_lexp_rwrite le e)
- | LEXP_memory _ -> (doc_lexp_fcall le e)))
- | E_vector_append(l,r) ->
- parens ((string "vector_concat ") ^^ (exp l) ^^ space ^^ (exp r))
- | E_cons(l,r) -> doc_op (group (colon^^colon)) (exp l) (exp r)
- | E_if(c,t,E_aux(E_block [], _)) ->
- parens (string "if" ^^ space ^^ string "to_bool" ^^ parens (exp c) ^/^
- string "then" ^^ space ^^ (exp t))
- | E_if(c,t,e) ->
- parens (
- string "if" ^^ space ^^ string "to_bool" ^^ parens (exp c) ^/^
- string "then" ^^ space ^^ group (exp t) ^/^
- string "else" ^^ space ^^ group (exp e))
- | E_for(id,exp1,exp2,exp3,(Ord_aux(order,_)),exp4) ->
- let var= doc_id_ocaml id in
- let (compare,next) = if order = Ord_inc then string "<=",string "+" else string ">=",string "-" in
- let by = exp exp3 in
- let stop = exp exp2 in
- (*takes over two names but doesn't require building a closure*)
- parens
- (separate space [(string "let (__stop,__by) = ") ^^ (parens (doc_op comma stop by));
- string "in" ^/^ empty;
- string "let rec foreach";
- var;
- equals;
- string "if";
- parens (doc_op compare var (string "__stop") );
- string "then";
- parens (exp exp4 ^^ space ^^ semi ^^ (string "foreach") ^^
- parens (doc_op next var (string "__by")));
- string "in";
- string "foreach";
- exp exp1])
- (*Requires fewer introduced names but introduces a closure*)
- (*let forL = if order = Ord_inc then string "foreach_inc" else string "foreach_dec" in
- forL ^^ space ^^ (group (exp exp1)) ^^ (group (exp exp2)) ^^ (group (exp full_exp3)) ^/^
- group ((string "fun") ^^ space ^^ (doc_id id) ^^ space ^^ arrow ^/^ (exp exp4))
-
- (* this way requires the following OCaml declarations first
-
- let rec foreach_inc i stop by body =
- if i <= stop then (body i; foreach_inc (i + by) stop by body) else ()
-
- let rec foreach_dec i stop by body =
- if i >= stop then (body i; foreach_dec (i - by) stop by body) else ()
-
- *)*)
- | E_let(leb,e) -> doc_op (string "in") (let_exp leb) (exp e)
- | E_app(f,args) ->
- let call,ctor = match annot with
- | Base(_,External (Some n),_,_,_,_) -> string n,false
- | Base(_,Constructor i,_,_,_,_) -> doc_id_ocaml_ctor i f,true
- | _ -> doc_id_ocaml f,false in
- let base_print () = parens (doc_unop call (parens (separate_map comma exp args))) in
- if not(ctor)
- then base_print ()
- else (match args with
- | [] -> call
- | [arg] -> (match arg with
- | E_aux(E_lit (L_aux(L_unit,_)),_) -> call
- | _ -> base_print())
- | args -> base_print())
- | E_vector_access(v,e) ->
- let call = (match annot with
- | Base((_,t),_,_,_,_,_) ->
- (match t.t with
- | Tid "bit" | Tabbrev(_,{t=Tid "bit"}) -> (string "bit_vector_access")
- | _ -> (string "vector_access"))
- | _ -> (string "vector_access")) in
- parens (call ^^ space ^^ exp v ^^ space ^^ exp e)
- | E_vector_subrange(v,e1,e2) ->
- parens ((string "vector_subrange") ^^ space ^^ (exp v) ^^ space ^^ (exp e1) ^^ space ^^ (exp e2))
- | E_field((E_aux(_,(_,fannot)) as fexp),id) ->
- (match fannot with
- | Base((_,{t= Tapp("register",_)}),_,_,_,_,_) |
- Base((_,{t= Tabbrev(_,{t=Tapp("register",_)})}),_,_,_,_,_)->
- let field_f = match annot with
- | Base((_,{t = Tid "bit"}),_,_,_,_,_) |
- Base((_,{t = Tabbrev(_,{t=Tid "bit"})}),_,_,_,_,_) ->
- string "get_register_field_bit"
- | _ -> string "get_register_field_vec" in
- parens (field_f ^^ space ^^ (exp fexp) ^^ space ^^ string_lit (doc_id id))
- | _ -> exp fexp ^^ dot ^^ doc_id id)
- | E_block [] -> string "()"
- | E_block exps | E_nondet exps ->
- let exps_doc = separate_map (semi ^^ hardline) exp exps in
- surround 2 1 (string "begin") exps_doc (string "end")
- | E_id id ->
- (match annot with
- | Base((_, ({t = Tapp("reg",_)} | {t=Tabbrev(_,{t=Tapp("reg",_)})})),_,_,_,_,_) ->
- string "!" ^^ doc_id_ocaml id
- | Base((_, ({t = Tapp("register",_)} | {t=Tabbrev(_,{t=Tapp("register",_)})})),_,_,_,_,_) ->
- if read_registers
- then string "(read_register " ^^ doc_id_ocaml id ^^ string ")"
- else doc_id_ocaml id
- | Base(_,(Constructor i |Enum i),_,_,_,_) -> doc_id_ocaml_ctor i id
- | Base((_,t),Alias alias_info,_,_,_,_) ->
- (match alias_info with
- | Alias_field(reg,field) ->
- let field_f = match t.t with
- | Tid "bit" | Tabbrev(_,{t=Tid "bit"}) -> string "get_register_field_bit"
- | _ -> string "get_register_field_vec" in
- parens (separate space [field_f; string (String.uncapitalize reg); string_lit (string field)])
- | Alias_extract(reg,start,stop) ->
- if start = stop
- then parens (separate space [string "bit_vector_access";string (String.uncapitalize reg);doc_int start])
- else parens
- (separate space [string "vector_subrange"; string (String.uncapitalize reg); doc_int start; doc_int stop])
- | Alias_pair(reg1,reg2) ->
- parens (separate space [string "vector_concat";
- string (String.uncapitalize reg1);
- string (String.uncapitalize reg2)]))
- | _ -> doc_id_ocaml id)
- | E_lit lit -> doc_lit_ocaml false lit
- | E_cast(typ,e) ->
- (match annot with
- | Base(_,External _,_,_,_,_) ->
- if read_registers
- then parens (string "read_register" ^^ space ^^ exp e)
- else exp e
- | _ ->
- let (Typ_aux (t,_)) = typ in
- (match t with
- | Typ_app (Id_aux (Id "vector",_), [Typ_arg_aux (Typ_arg_nexp(Nexp_aux (Nexp_constant i,_)),_);_;_;_]) ->
- parens ((concat [string "set_start";space;string (string_of_int i)]) ^//^
- exp e)
- | Typ_var (Kid_aux (Var "length",_)) ->
- parens ((string "set_start_to_length") ^//^ exp e)
- | _ ->
- parens (doc_op colon (group (exp e)) (doc_typ_ocaml typ)))
-
-
-)
- | E_tuple exps ->
- parens (separate_map comma exp exps)
- | E_record(FES_aux(FES_Fexps(fexps,_),_)) ->
- braces (separate_map semi_sp doc_fexp fexps)
- | E_record_update(e,(FES_aux(FES_Fexps(fexps,_),_))) ->
- braces (doc_op (string "with") (exp e) (separate_map semi_sp doc_fexp fexps))
- | E_vector exps ->
- (match annot with
- | Base((_,t),_,_,_,_,_) ->
- match t.t with
- | Tapp("vector", [TA_nexp start; _; TA_ord order; _])
- | Tabbrev(_,{t= Tapp("vector", [TA_nexp start; _; TA_ord order; _])}) ->
- let call = if is_bit_vector t then (string "Vvector") else (string "VvectorR") in
- let dir,dir_out = match order.order with
- | Oinc -> true,"true"
- | _ -> false, "false" in
- let start = match start.nexp with
- | Nconst i -> string_of_big_int i
- | N2n(_,Some i) -> string_of_big_int i
- | _ -> if dir then "0" else string_of_int (List.length exps) in
- parens (separate space [call; parens (separate comma_sp [squarebars (separate_map semi exp exps);
- string start;
- string dir_out])]))
- | E_vector_indexed (iexps, (Def_val_aux (default,_))) ->
- (match annot with
- | Base((_,t),_,_,_,_,_) ->
- match t.t with
- | Tapp("vector", [TA_nexp start; TA_nexp len; TA_ord order; _])
- | Tabbrev(_,{t= Tapp("vector", [TA_nexp start; TA_nexp len; TA_ord order; _])})
- | Tapp("reg", [TA_typ {t =Tapp("vector", [TA_nexp start; TA_nexp len; TA_ord order; _])}]) ->
- let call = if is_bit_vector t then (string "make_indexed_bitv") else (string "make_indexed_v") in
- let dir,dir_out = match order.order with
- | Oinc -> true,"true"
- | _ -> false, "false" in
- let start = match start.nexp with
- | Nconst i | N2n(_,Some i)-> string_of_big_int i
- | N2n({nexp=Nconst i},_) -> string_of_int (Util.power 2 (int_of_big_int i))
- | _ -> if dir then "0" else string_of_int (List.length iexps) in
- let size = match len.nexp with
- | Nconst i | N2n(_,Some i)-> string_of_big_int i
- | N2n({nexp=Nconst i},_) -> string_of_int (Util.power 2 (int_of_big_int i))
- in
- let default_string =
- (match default with
- | Def_val_empty -> string "None"
- | Def_val_dec e -> parens (string "Some " ^^ (exp e))) in
- let iexp (i,e) = parens (separate_map comma_sp (fun x -> x) [(doc_int i); (exp e)]) in
- parens (separate space [call;
- (brackets (separate_map semi iexp iexps));
- default_string;
- string start;
- string size;
- string dir_out]))
- | E_vector_update(v,e1,e2) ->
- (*Has never happened to date*)
- brackets (doc_op (string "with") (exp v) (doc_op equals (exp e1) (exp e2)))
- | E_vector_update_subrange(v,e1,e2,e3) ->
- (*Has never happened to date*)
- brackets (
- doc_op (string "with") (exp v)
- (doc_op equals (exp e1 ^^ colon ^^ exp e2) (exp e3)))
- | E_list exps ->
- brackets (separate_map semi exp exps)
- | E_case(e,pexps) ->
- let opening = separate space [string "("; string "match"; top_exp false e; string "with"] in
- let cases = separate_map (break 1) doc_case pexps in
- surround 2 1 opening cases rparen
- | E_exit e ->
- separate space [string "exit"; exp e;]
- | E_app_infix (e1,id,e2) ->
- let call =
- match annot with
- | Base((_,t),External(Some name),_,_,_,_) -> string name
- | _ -> doc_id_ocaml id in
- parens (separate space [call; parens (separate_map comma exp [e1;e2])])
- | E_internal_let(lexp, eq_exp, in_exp) ->
- separate space [string "let";
- doc_lexp_ocaml true lexp; (*Rewriter/typecheck should ensure this is only cast or id*)
- equals;
- string "ref";
- exp eq_exp;
- string "in";
- exp in_exp]
-
- | E_internal_plet (pat,e1,e2) ->
- (separate space [(exp e1); string ">>= fun"; doc_pat_ocaml pat;arrow]) ^/^
- exp e2
-
- | E_internal_return (e1) ->
- separate space [string "return"; exp e1;]
- and let_exp (LB_aux(lb,_)) = match lb with
- | LB_val_explicit(ts,pat,e) ->
- prefix 2 1
- (separate space [string "let"; doc_pat_ocaml pat; equals])
- (top_exp false e)
- | LB_val_implicit(pat,e) ->
- prefix 2 1
- (separate space [string "let"; doc_pat_ocaml pat; equals])
- (top_exp false e)
-
- and doc_fexp (FE_aux(FE_Fexp(id,e),_)) = doc_op equals (doc_id_ocaml id) (top_exp false e)
-
- and doc_case (Pat_aux(Pat_exp(pat,e),_)) =
- doc_op arrow (separate space [pipe; doc_pat_ocaml pat]) (group (top_exp false e))
-
- and doc_lexp_ocaml top_call ((LEXP_aux(lexp,(l,annot))) as le) =
- let exp = top_exp false in
- match lexp with
- | LEXP_vector(v,e) -> doc_lexp_array_ocaml le
- | LEXP_vector_range(v,e1,e2) ->
- parens ((string "vector_subrange") ^^ space ^^ (doc_lexp_ocaml false v) ^^ space ^^ (exp e1) ^^ space ^^ (exp e2))
- | LEXP_field(v,id) -> (doc_lexp_ocaml false v) ^^ dot ^^ doc_id_ocaml id
- | LEXP_id id | LEXP_cast(_,id) ->
- let name = doc_id_ocaml id in
- match annot,top_call with
- | Base((_,{t=Tapp("reg",_)}),Emp_set,_,_,_,_),false | Base((_,{t=Tabbrev(_,{t=Tapp("reg",_)})}),Emp_set,_,_,_,_),false ->
- string "!" ^^ name
- | _ -> name
-
- and doc_lexp_array_ocaml ((LEXP_aux(lexp,(l,annot))) as le) = match lexp with
- | LEXP_vector(v,e) ->
- (match annot with
- | Base((_,t),_,_,_,_,_) ->
- let t_act = match t.t with | Tapp("reg",[TA_typ t]) | Tabbrev(_,{t=Tapp("reg",[TA_typ t])}) -> t | _ -> t in
- (match t_act.t with
- | Tid "bit" | Tabbrev(_,{t=Tid "bit"}) ->
- parens ((string "get_barray") ^^ space ^^ doc_lexp_ocaml false v) ^^ dot ^^ parens ((string "int_of_big_int") ^^ space ^^ (top_exp false e))
- | _ -> parens ((string "get_varray") ^^ space ^^ doc_lexp_ocaml false v) ^^ dot ^^ parens ((string "int_of_big_int") ^^ space ^^ (top_exp false e)))
- | _ ->
- parens ((string "get_varray") ^^ space ^^ doc_lexp_ocaml false v) ^^ dot ^^ parens ((string "int_of_big_int") ^^ space ^^ (top_exp false e)))
- | _ -> empty
-
- and doc_lexp_rwrite ((LEXP_aux(lexp,(l,annot))) as le) e_new_v =
- let exp = top_exp false in
- let (is_bit,is_bitv) = match e_new_v with
- | E_aux(_,(_,Base((_,t),_,_,_,_,_))) ->
- (match t.t with
- | Tapp("vector", [_;_;_;(TA_typ ({t=Tid "bit"} | {t=Tabbrev(_,{t=Tid "bit"})}))]) |
- Tabbrev(_,{t=Tapp("vector",[_;_;_;TA_typ ({t=Tid "bit"} | {t=Tabbrev(_,{t=Tid "bit"})})])}) |
- Tapp("reg", [TA_typ {t= Tapp("vector", [_;_;_;(TA_typ ({t=Tid "bit"} | {t=Tabbrev(_,{t=Tid "bit"})}))])}])
- ->
- (false,true)
- | Tid "bit" | Tabbrev(_,{t=Tid "bit"}) | Tapp("reg",[TA_typ ({t=Tid "bit"} | {t=Tabbrev(_,{t=Tid "bit"})})])
- -> (true,false)
- | _ -> (false,false))
- | _ -> (false,false) in
- match lexp with
- | LEXP_vector(v,e) ->
- doc_op (string "<-")
- (group (parens ((string (if is_bit then "get_barray" else "get_varray")) ^^ space ^^ doc_lexp_ocaml false v)) ^^
- dot ^^ parens ((string "int_of_big_int") ^^ space ^^ (exp e)))
- (exp e_new_v)
- | LEXP_vector_range(v,e1,e2) ->
- parens ((string (if is_bitv then "set_vector_subrange_bit" else "set_vector_subrange_vec")) ^^ space ^^
- doc_lexp_ocaml false v ^^ space ^^ exp e1 ^^ space ^^ exp e2 ^^ space ^^ exp e_new_v)
- | LEXP_field(v,id) ->
- parens ((string (if is_bit then "set_register_field_bit" else "set_register_field_v")) ^^ space ^^
- doc_lexp_ocaml false v ^^ space ^^string_lit (doc_id id) ^^ space ^^ exp e_new_v)
- | LEXP_id id | LEXP_cast (_,id) ->
- (match annot with
- | Base(_,Alias alias_info,_,_,_,_) ->
- (match alias_info with
- | Alias_field(reg,field) ->
- parens ((if is_bit then string "set_register_field_bit" else string "set_register_field_v") ^^ space ^^
- string (String.uncapitalize reg) ^^ space ^^string_lit (string field) ^^ space ^^ exp e_new_v)
- | Alias_extract(reg,start,stop) ->
- if start = stop
- then
- doc_op (string "<-")
- (group (parens ((string (if is_bit then "get_barray" else "get_varray")) ^^ space ^^ string reg)) ^^
- dot ^^ parens ((string "int_of_big_int") ^^ space ^^ (doc_int start)))
- (exp e_new_v)
- else
- parens ((string (if is_bitv then "set_vector_subrange_bit" else "set_vector_subrange_vec")) ^^ space ^^
- string reg ^^ space ^^ doc_int start ^^ space ^^ doc_int stop ^^ space ^^ exp e_new_v)
- | Alias_pair(reg1,reg2) ->
- parens ((string "set_two_regs") ^^ space ^^ string reg1 ^^ space ^^ string reg2 ^^ space ^^ exp e_new_v))
- | _ ->
- parens (separate space [string "set_register"; doc_id_ocaml id; exp e_new_v]))
-
- and doc_lexp_fcall ((LEXP_aux(lexp,(l,annot))) as le) e_new_v = match lexp with
- | LEXP_memory(id,args) -> doc_id_ocaml id ^^ parens (separate_map comma (top_exp false) (args@[e_new_v]))
-
- (* expose doc_exp and doc_let *)
- in top_exp false, let_exp
-
-(*TODO Upcase and downcase type and constructors as needed*)
-let doc_type_union_ocaml n (Tu_aux(typ_u,_)) = match typ_u with
- | Tu_ty_id(typ,id) -> separate space [pipe; doc_id_ocaml_ctor n id; string "of"; doc_typ_ocaml typ;]
- | Tu_id id -> separate space [pipe; doc_id_ocaml_ctor n id]
-
-let rec doc_range_ocaml (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_ocaml (TD_aux(td,_)) = match td with
- | TD_abbrev(id,nm,typschm) ->
- doc_op equals (concat [string "type"; space; doc_id_ocaml_type id;]) (doc_typscm_ocaml typschm)
- | TD_record(id,nm,typq,fs,_) ->
- let f_pp (typ,id) = concat [doc_id_ocaml_type id; space; colon; doc_typ_ocaml typ; semi] in
- let fs_doc = group (separate_map (break 1) f_pp fs) in
- doc_op equals
- (concat [string "type"; space; doc_id_ocaml_type id;]) (doc_typquant_ocaml typq (braces fs_doc))
- | TD_variant(id,nm,typq,ar,_) ->
- let n = List.length ar in
- let ar_doc = group (separate_map (break 1) (doc_type_union_ocaml n) ar) in
- doc_op equals
- (concat [string "type"; space; doc_id_ocaml_type id;])
- (if n > 246
- then brackets (space ^^(doc_typquant_ocaml typq ar_doc))
- else (doc_typquant_ocaml typq ar_doc))
- | TD_enum(id,nm,enums,_) ->
- let n = List.length enums in
- let enums_doc = group (separate_map (break 1 ^^ pipe) (doc_id_ocaml_ctor n) enums) in
- doc_op equals
- (concat [string "type"; space; doc_id_ocaml_type id;])
- (enums_doc)
- | TD_register(id,n1,n2,rs) ->
- let doc_rid (r,id) = parens (separate comma_sp [string_lit (doc_id id); doc_range_ocaml r;]) in
- let doc_rids = group (separate_map (semi ^^ (break 1)) doc_rid rs) in
- match n1,n2 with
- | Nexp_aux(Nexp_constant i1,_),Nexp_aux(Nexp_constant i2,_) ->
- let dir = i1 < i2 in
- let size = if dir then i2-i1 +1 else i1-i2+1 in
- doc_op equals
- ((string "let") ^^ space ^^ doc_id_ocaml id ^^ space ^^ (string "init_val"))
- (separate space [string "Vregister";
- (parens (separate comma_sp
- [parens (separate space
- [string "match init_val with";
- pipe;
- string "None";
- arrow;
- string "ref";
- string "(Array.make";
- doc_int size;
- string "Vzero)";
- pipe;
- string "Some init_val";
- arrow;
- string "ref init_val";]);
- doc_nexp n1;
- string (if dir then "true" else "false");
- brackets doc_rids]))])
-
-let doc_kdef_ocaml (KD_aux(kd,_)) = match kd with
- | KD_abbrev(_,id,nm,typschm) ->
- doc_op equals (concat [string "type"; space; doc_id_ocaml_type id;]) (doc_typscm_ocaml typschm)
- | KD_record(_,id,nm,typq,fs,_) ->
- let f_pp (typ,id) = concat [doc_id_ocaml_type id; space; colon; doc_typ_ocaml typ; semi] in
- let fs_doc = group (separate_map (break 1) f_pp fs) in
- doc_op equals
- (concat [string "type"; space; doc_id_ocaml_type id;]) (doc_typquant_ocaml typq (braces fs_doc))
- | KD_variant(_,id,nm,typq,ar,_) ->
- let n = List.length ar in
- let ar_doc = group (separate_map (break 1) (doc_type_union_ocaml n) ar) in
- doc_op equals
- (concat [string "type"; space; doc_id_ocaml_type id;])
- (if n > 246
- then brackets (space ^^(doc_typquant_ocaml typq ar_doc))
- else (doc_typquant_ocaml typq ar_doc))
- | KD_enum(_,id,nm,enums,_) ->
- let n = List.length enums in
- let enums_doc = group (separate_map (break 1 ^^ pipe) (doc_id_ocaml_ctor n) enums) in
- doc_op equals
- (concat [string "type"; space; doc_id_ocaml_type id;])
- (enums_doc)
- | KD_register(_,id,n1,n2,rs) ->
- let doc_rid (r,id) = parens (separate comma_sp [string_lit (doc_id id); doc_range_ocaml r;]) in
- let doc_rids = group (separate_map (semi ^^ (break 1)) doc_rid rs) in
- match n1,n2 with
- | Nexp_aux(Nexp_constant i1,_),Nexp_aux(Nexp_constant i2,_) ->
- let dir = i1 < i2 in
- let size = if dir then i2-i1 +1 else i1-i2 in
- doc_op equals
- ((string "let") ^^ space ^^ doc_id_ocaml id ^^ space ^^ (string "init_val"))
- (separate space [string "Vregister";
- (parens (separate comma_sp
- [parens (separate space
- [string "match init_val with";
- pipe;
- string "None";
- arrow;
- string "ref";
- string "(Array.make";
- doc_int size;
- string "Vzero)";
- pipe;
- string "Some init_val";
- arrow;
- string "ref init_val";]);
- doc_nexp n1;
- string (if dir then "true" else "false");
- brackets doc_rids]))])
-
-let doc_rec_ocaml (Rec_aux(r,_)) = match r with
- | Rec_nonrec -> empty
- | Rec_rec -> string "rec" ^^ space
-
-let doc_tannot_opt_ocaml (Typ_annot_opt_aux(t,_)) = match t with
- | Typ_annot_opt_some(tq,typ) -> doc_typquant_ocaml tq (doc_typ_ocaml typ)
-
-let doc_funcl_ocaml (FCL_aux(FCL_Funcl(id,pat,exp),_)) =
- group (doc_op arrow (doc_pat_ocaml pat) (doc_exp_ocaml exp))
-
-let get_id = function
- | [] -> failwith "FD_function with empty list"
- | (FCL_aux (FCL_Funcl (id,_,_),_))::_ -> id
-
-let doc_fundef_ocaml (FD_aux(FD_function(r, typa, efa, fcls),_)) =
- match fcls with
- | [] -> failwith "FD_function with empty function list"
- | [FCL_aux (FCL_Funcl(id,pat,exp),_)] ->
- (separate space [(string "let"); (doc_rec_ocaml r); (doc_id_ocaml id); (doc_pat_ocaml pat); equals]) ^^ hardline ^^ (doc_exp_ocaml exp)
- | _ ->
- let id = get_id fcls in
- let sep = hardline ^^ pipe ^^ space in
- let clauses = separate_map sep doc_funcl_ocaml fcls in
- separate space [string "let";
- doc_rec_ocaml r;
- doc_id_ocaml id;
- equals;
- (string "function");
- (hardline^^pipe);
- clauses]
-
-let doc_dec_ocaml (DEC_aux (reg,(l,annot))) =
- match reg with
- | DEC_reg(typ,id) ->
- (match annot with
- | Base((_,t),_,_,_,_,_) ->
- (match t.t with
- | Tapp("register", [TA_typ {t= Tapp("vector", [TA_nexp start; TA_nexp size; TA_ord order; TA_typ itemt])}])
- | Tapp("register", [TA_typ {t= Tabbrev(_,{t=Tapp("vector", [TA_nexp start; TA_nexp size; TA_ord order; TA_typ itemt])})}]) ->
- (match itemt.t,start.nexp,size.nexp with
- | Tid "bit", Nconst start, Nconst size ->
- let o = if order.order = Oinc then string "true" else string "false" in
- separate space [string "let";
- doc_id_ocaml id;
- equals;
- string "Vregister";
- parens (separate comma [separate space [string "ref";
- parens (separate space
- [string "Array.make";
- doc_int (int_of_big_int size);
- string "Vzero";])];
- doc_int (int_of_big_int start);
- o;
- brackets empty])]
- | _ -> empty)
- | Tapp("register", [TA_typ {t=Tid idt}]) |
- Tabbrev( {t= Tid idt}, _) ->
- separate space [string "let";
- doc_id_ocaml id;
- equals;
- doc_id_ocaml (Id_aux (Id idt, Unknown));
- string "None"]
- |_-> failwith "type was not handled in register declaration")
- | _ -> failwith "annot was not Base")
- | DEC_alias(id,alspec) -> empty (*
- doc_op equals (string "register alias" ^^ space ^^ doc_id id) (doc_alias alspec) *)
- | DEC_typ_alias(typ,id,alspec) -> empty (*
- doc_op equals (string "register alias" ^^ space ^^ doc_atomic_typ typ) (doc_alias alspec) *)
-
-let doc_def_ocaml def = group (match def with
- | DEF_default df -> empty
- | DEF_spec v_spec -> empty (*unless we want to have a separate pass to create mli files*)
- | DEF_type t_def -> doc_typdef_ocaml t_def
- | DEF_fundef f_def -> doc_fundef_ocaml f_def
- | DEF_val lbind -> doc_let_ocaml lbind
- | DEF_reg_dec dec -> doc_dec_ocaml dec
- | DEF_scattered sdef -> empty (*shoulnd't still be here*)
- | DEF_kind _ -> failwith "unhandled DEF_kind"
- | DEF_comm _ -> failwith "unhandled DEF_comm"
- ) ^^ hardline
-
-let doc_defs_ocaml (Defs(defs)) =
- separate_map hardline doc_def_ocaml defs
-let pp_defs_ocaml f d top_line opens =
- print f (string "(*" ^^ (string top_line) ^^ string "*)" ^/^
- (separate_map hardline (fun lib -> (string "open") ^^ space ^^ (string lib)) opens) ^/^
- (doc_defs_ocaml d))
-
-
-
-(****************************************************************************
- * PPrint-based sail-to-lem pprinter
-****************************************************************************)
-
-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 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 (Effect_aux (eff,_)) =
- match eff with
- | Effect_var _ -> failwith "effectful: Effect_var not supported"
- | Effect_set effs ->
- List.exists
- (fun (BE_aux (eff,_)) ->
- match eff with
- | BE_rreg | BE_wreg | BE_rmem | BE_wmem | BE_eamem | BE_wmv
- | BE_barr | BE_depend | BE_nondet | BE_escape -> true
- | _ -> false)
- effs
-
-let rec is_number {t=t} =
- match t with
- | Tabbrev (t1,t2) -> is_number t1 || is_number t2
- | Tapp ("range",_)
- | Tapp ("implicit",_)
- | Tapp ("atom",_) -> true
- | _ -> false
-
-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_typ typa, _)]) ->
- let tpp = string "vector" ^^ space ^^ typ regtypes typa in
- if atyp_needed then parens tpp else tpp
- | 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_aux (Id name,_)) as id) ->
- if List.exists ((=) name) 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 false t
- | Typ_arg_nexp n -> empty
- | Typ_arg_order o -> empty
- | Typ_arg_effect e -> empty
- in typ', atomic_typ
-
-(* 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 ->
- let (Base ((_,{t = t}),_,_,_,_,_)) = a in
- (match t with
- | Tid "bit"
- | Tabbrev ({t = Tid "bit"},_) -> "BU"
- | Tapp ("register",_)
- | Tabbrev ({t = Tapp ("register",_)},_) -> "UndefinedRegister 0"
- | Tid "string"
- | Tabbrev ({t = Tapp ("string",_)},_) -> "\"\""
- | _ -> "(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))
-
-(*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
- | Base(_,(Constructor _ | Enum _),_,_,_,_) ->
- 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
- | Base(_,(Constructor _| Enum _),_,_,_,_) -> 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*)
-
-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))) =
- 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 (_,(Base ((_,{t = t}),tag,_,_,_,_))) = tannot in
- (match le_act, t, tag with
- | LEXP_vector_range (le,e2,e3),_,_ ->
- (match le with
- | LEXP_aux (LEXP_field (le,id), (_,((Base ((_,{t = t}),_,_,_,_,_))))) ->
- if t = Tid "bit" 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), (Tid "bit" | Tabbrev (_,{t=Tid "bit"})),_ ->
- (match le with
- | LEXP_aux (LEXP_field (le,id), (_,((Base ((_,{t = t}),_,_,_,_,_))))) ->
- if t = Tid "bit" 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), (Tid "bit"| Tabbrev (_,{t=Tid "bit"})), _ ->
- (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(l,r) ->
- let epp =
- align (group (separate space [expY l;string "^^"] ^/^ expY r)) in
- if aexp_needed then parens epp else epp
- | E_cons(l,r) -> doc_op (group (colon^^colon)) (expY l) (expY r)
- | 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 epp = separate space [string "slice_raw";expY e1;expY e2;expY e3] in
- if aexp_needed then parens (align epp) else epp
- | _ ->
- begin match annot with
- | Base (_,External (Some "bitwise_not_bit"),_,_,_,_) ->
- let [a] = args in
- let epp = align (string "~" ^^ expY a) in
- if aexp_needed then parens (align epp) else epp
- | Base (_,Constructor _,_,_,_,_) ->
- let argpp a_needed arg =
- let (E_aux (_,(_,Base((_,{t=t}),_,_,_,_,_)))) = arg in
- match t with
- | Tapp("vector",_) ->
- let epp = concat [string "reset_vector_start";space;expY arg] in
- if a_needed then parens epp else epp
- | _ -> 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 (E_aux (_,(_,Base((_,{t=t}),_,_,_,_,_)))) = arg in
- match t with
- | Tapp("vector",_) ->
- let epp = concat [string "reset_vector_start";space;expY arg] in
- if a_needed then parens epp else epp
- | _ -> 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
- if aexp_needed then parens (align epp) else epp
- end
- end
- | E_vector_access (v,e) ->
- let (Base (_,_,_,_,eff,_)) = annot in
- let epp =
- if has_rreg_effect eff then
- separate space [string "read_reg_bit";expY v;expY e]
- else
- separate space [string "access";expY v;expY e] in
- if aexp_needed then parens (align epp) else epp
- | E_vector_subrange (v,e1,e2) ->
- let (Base (_,_,_,_,eff,_)) = annot in
- let epp =
- if has_rreg_effect eff then
- align (string "read_reg_range" ^^ space ^^ expY v ^//^ expY e1 ^//^ expY e2)
- else
- align (string "slice" ^^ space ^^ expY v ^//^ expY e1 ^//^ expY e2) in
- if aexp_needed then parens (align epp) else epp
- | E_field((E_aux(_,(l,fannot)) as fexp),id) ->
- let (Base ((_,{t = t}),_,_,_,_,_)) = fannot in
- (match t with
- | Tabbrev({t = Tid regtyp},{t=Tapp("register",_)}) ->
- let field_f = match annot with
- | Base((_,{t = Tid "bit"}),_,_,_,_,_)
- | Base((_,{t = Tabbrev(_,{t=Tid "bit"})}),_,_,_,_,_) ->
- string "read_reg_bitfield"
- | _ -> string "read_reg_field" in
- let epp = field_f ^^ space ^^ (expY fexp) ^^ space ^^ string_lit (doc_id_lem id) in
- if aexp_needed then parens (align epp) else epp
- | Tid recordtyp
- | Tabbrev ({t = Tid recordtyp},_) ->
- let fname =
- if prefix_recordtype
- then (string (recordtyp ^ "_")) ^^ 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 ->
- (match annot with
- | Base((_, ({t = Tapp("register",_)} | {t=Tabbrev(_,{t=Tapp("register",_)})})),
- External _,_,eff,_,_) ->
- if has_rreg_effect eff then
- separate space [string "read_reg";doc_id_lem id]
- else
- doc_id_lem id
- | Base(_,(Constructor i |Enum i),_,_,_,_) -> doc_id_lem_ctor id
- | Base((_,t),Alias alias_info,_,eff,_,_) ->
- (match alias_info with
- | Alias_field(reg,field) ->
- let epp = match t.t with
- | Tid "bit" | Tabbrev (_,{t=Tid "bit"}) ->
- (separate space)
- [string "read_reg_bitfield"; string reg;string_lit(string field)]
- | _ ->
- (separate space)
- [string "read_reg_field"; string reg; string_lit(string field)] in
- if aexp_needed then parens (align epp) else epp
- | Alias_pair(reg1,reg2) ->
- let epp =
- if has_rreg_effect eff then
- separate space [string "read_two_regs";string reg1;string reg2]
- else
- separate space [string "RegisterPair";string reg1;string reg2] in
- if aexp_needed then parens (align epp) else epp
- | Alias_extract(reg,start,stop) ->
- let epp =
- if start = stop then
- (separate space)
- [string "access";doc_int start;
- parens (string "read_reg" ^^ space ^^ string reg)]
- else
- (separate space)
- [string "slice"; doc_int start; doc_int stop;
- parens (string "read_reg" ^^ space ^^ string reg)] 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_aux (typ,_),e) ->
- (match annot with
- | Base(_,External _,_,_,_,_) -> string "read_reg" ^^ space ^^ expY e
- | _ ->
- (match typ with
- | Typ_app (Id_aux (Id "vector",_), [Typ_arg_aux (Typ_arg_nexp(Nexp_aux (Nexp_constant i,_)),_);_;_;_]) ->
- let epp = (concat [string "set_vector_start";space;string (string_of_int i)]) ^//^
- expY e in
- if aexp_needed then parens epp else epp
- | Typ_var (Kid_aux (Var "length",_)) ->
- let epp = (string "set_vector_start_to_length") ^//^ 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 (Base ((_,{t = t}),_,_,_,_,_)) = annot in
- let recordtyp = match t with
- | Tid recordtyp
- | Tabbrev ({t = Tid recordtyp},_) -> recordtyp
- | _ -> 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 (Base ((_,{t = t}),_,_,_,_,_)) = annot in
- let recordtyp = match t with
- | Tid recordtyp
- | Tabbrev ({t = Tid recordtyp},_) -> recordtyp
- | _ -> 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 ->
- (match annot with
- | Base((_,t),_,_,_,_,_) ->
- match t.t with
- | Tapp("vector", [TA_nexp start; _; TA_ord order; _])
- | Tabbrev(_,{t= Tapp("vector", [TA_nexp start; _; TA_ord order; _])}) ->
- let dir,dir_out = match order.order with
- | Oinc -> true,"true"
- | _ -> false, "false" in
- let start = match start.nexp with
- | Nconst i -> string_of_big_int i
- | N2n(_,Some i) -> string_of_big_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
- if aexp_needed then parens (align epp) else epp
- )
- | E_vector_indexed (iexps, (Def_val_aux (default,(dl,dannot)))) ->
- let (Base((_,t),_,_,_,_,_)) = annot in
- let call = string "make_indexed_vector" in
- let (start,len,order) = match t.t with
- | Tapp("vector", [TA_nexp start; TA_nexp len; TA_ord order; _])
- | Tabbrev(_,{t= Tapp("vector", [TA_nexp start; TA_nexp len; TA_ord order; _])})
- | Tapp("reg", [TA_typ {t =Tapp("vector", [TA_nexp start; TA_nexp len; TA_ord order; _])}]) ->
- (start,len,order.order) in
- let dir,dir_out = match order with
- | Oinc -> true,"true"
- | _ -> false, "false" in
- let start = match start.nexp with
- | Nconst i | N2n(_,Some i)-> string_of_big_int i
- | N2n({nexp=Nconst i},_) -> string_of_int (Util.power 2 (int_of_big_int i))
- | _ -> if dir then "0" else string_of_int (List.length iexps) in
- let size = match len.nexp with
- | Nconst i | N2n(_,Some i)-> string_of_big_int i
- | N2n({nexp=Nconst i},_) -> string_of_int (Util.power 2 (int_of_big_int i)) in
- let default_string =
- match default with
- | Def_val_empty ->
- if is_bit_vector 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})]) ->
-
- 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 epp =
- align (group (call ^//^ brackets expspp ^/^
- separate space [default_string;string start;string size;string dir_out])) in
- if aexp_needed then parens (align epp) else epp
- | E_vector_update(v,e1,e2) ->
- let epp = separate space [string "update_pos";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 epp = align (string "update" ^//^
- 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_aux(_,(_,annot)) as e) =
- match annot with
- | Base((_,t),_,_,_,_,_) ->
- if is_number t then
- let e_pp = expY e in
- align (string "toNatural" ^//^ e_pp)
- else
- (match t with
- | {t = Ttup ([t1;t2;t3;t4;t5] as ts)} when List.for_all is_number ts ->
- let e_pp = expY e in
- align (string "toNaturalFiveTup" ^//^ e_pp)
- | _ -> expY e)
- | _ -> 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) ->
- (match annot with
- | Base((_,t),External(Some name),_,_,_,_) ->
- let argpp arg =
- let (E_aux (_,(_,Base((_,{t=t}),_,_,_,_,_)))) = arg in
- match t with
- | Tapp("vector",_) -> parens (concat [string "reset_vector_start";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
- 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;]
- 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 (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 "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 "instruction_kind"),_) -> 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
- let clauses =
- clauses ^^ (break 1) ^^
- (separate space
- [pipe;doc_pat_lem regtypes false pat;arrow;
- string aux_fname;
- doc_pat_lem regtypes true (P_aux (P_tup argspat, pannot))]) 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 annot with
- | Base((_,t),_,_,_,_,_) ->
- (match t.t with
- | Tapp("register", [TA_typ {t= Tapp("vector", [TA_nexp start; TA_nexp size; TA_ord order; TA_typ itemt])}])
- | Tapp("register", [TA_typ {t= Tabbrev(_,{t=Tapp("vector", [TA_nexp start; TA_nexp size; TA_ord order; TA_typ itemt])})}]) ->
- (match itemt.t,start.nexp,size.nexp with
- | Tid "bit", Nconst start, Nconst size ->
- let o = if order.order = Oinc 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 (int_of_big_int size);
- doc_int (int_of_big_int start);
- string o;
- string "[]"]))
- ^/^ hardline
- | _ ->
- let (Id_aux (Id name,_)) = id in
- failwith ("can't deal with register " ^ name))
- | Tapp("register", [TA_typ {t=Tid idt}])
- | Tid idt
- | Tabbrev( {t= Tid idt}, _) ->
- separate space [string "let";doc_id_lem id;equals;
- string "build_" ^^ string idt;string_lit (doc_id_lem id)] ^/^ hardline
- |_-> empty)
- | _ -> 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) -> 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_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/pretty_print_common.ml b/src/pretty_print_common.ml
new file mode 100644
index 00000000..e90d9cf1
--- /dev/null
+++ b/src/pretty_print_common.ml
@@ -0,0 +1,227 @@
+(**************************************************************************)
+(* Sail *)
+(* *)
+(* Copyright (c) 2013-2017 *)
+(* Kathyrn Gray *)
+(* Shaked Flur *)
+(* Stephen Kell *)
+(* Gabriel Kerneis *)
+(* Robert Norton-Wright *)
+(* Christopher Pulte *)
+(* Peter Sewell *)
+(* *)
+(* 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 Ast
+open PPrint
+
+let pipe = string "|"
+let arrow = string "->"
+let dotdot = string ".."
+let coloneq = string ":="
+let lsquarebar = string "[|"
+let rsquarebar = string "|]"
+let squarebars = enclose lsquarebar rsquarebar
+let lsquarebarbar = string "[||"
+let rsquarebarbar = string "||]"
+let squarebarbars = enclose lsquarebarbar rsquarebarbar
+let lsquarecolon = string "[:"
+let rsquarecolon = string ":]"
+let squarecolons = enclose lsquarecolon rsquarecolon
+let lcomment = string "(*"
+let rcomment = string "*)"
+let comment = enclose lcomment rcomment
+let string_lit = enclose dquote dquote
+let spaces op = enclose space space op
+let semi_sp = semi ^^ space
+let comma_sp = comma ^^ space
+let colon_sp = spaces colon
+
+let doc_var (Kid_aux(Var v,_)) = string v
+let doc_int i = string (string_of_int i)
+let doc_op symb a b = infix 2 1 symb a b
+let doc_unop symb a = prefix 2 1 symb a
+
+let doc_id (Id_aux(i,_)) =
+ match i with
+ | Id i -> string 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 [string "deinfix"; string x; empty])
+
+let rec doc_range (BF_aux(r,_)) = match r with
+ | BF_single i -> doc_int i
+ | BF_range(i1,i2) -> doc_op dotdot (doc_int i1) (doc_int i2)
+ | BF_concat(ir1,ir2) -> (doc_range ir1) ^^ comma ^^ (doc_range ir2)
+
+let doc_effect (BE_aux (e,_)) =
+ string (match e with
+ | BE_rreg -> "rreg"
+ | BE_wreg -> "wreg"
+ | BE_rmem -> "rmem"
+ | BE_wmem -> "wmem"
+ | BE_wmv -> "wmv"
+ | BE_eamem -> "eamem"
+ | BE_barr -> "barr"
+ | BE_depend -> "depend"
+ | BE_escape -> "escape"
+ | BE_undef -> "undef"
+ | BE_unspec -> "unspec"
+ | BE_nondet -> "nondet")
+
+let doc_effects (Effect_aux(e,_)) = match e with
+ | Effect_var v -> doc_var v
+ | Effect_set [] -> string "pure"
+ | Effect_set s -> braces (separate_map comma_sp doc_effect s)
+
+let doc_ord (Ord_aux(o,_)) = match o with
+ | Ord_var v -> doc_var v
+ | Ord_inc -> string "inc"
+ | Ord_dec -> string "dec"
+
+let doc_typ, doc_atomic_typ, doc_nexp =
+ (* following the structure of parser for precedence *)
+ let rec typ ty = fn_typ ty
+ and fn_typ ((Typ_aux (t, _)) as ty) = match t with
+ | Typ_fn(arg,ret,efct) ->
+ separate space [tup_typ arg; arrow; fn_typ ret; string "effect"; doc_effects efct]
+ | _ -> tup_typ ty
+ and tup_typ ((Typ_aux (t, _)) as ty) = match t with
+ | Typ_tup typs -> parens (separate_map comma_sp app_typ typs)
+ | _ -> app_typ ty
+ and app_typ ((Typ_aux (t, _)) as ty) = match t with
+ (*TODO Need to un bid-endian-ify this here, since both can transform to the shorthand, especially with <: and :> *)
+ (* Special case simple vectors to improve legibility
+ * XXX we assume big-endian here, as usual *)
+ | Typ_app(Id_aux (Id "vector", _), [
+ Typ_arg_aux(Typ_arg_nexp (Nexp_aux(Nexp_constant n, _)), _);
+ Typ_arg_aux(Typ_arg_nexp (Nexp_aux(Nexp_constant m, _)), _);
+ Typ_arg_aux (Typ_arg_order (Ord_aux (Ord_inc, _)), _);
+ Typ_arg_aux (Typ_arg_typ (Typ_aux (Typ_id id, _)), _)]) ->
+ (doc_id id) ^^ (brackets (if n = 0 then doc_int m else doc_op colon (doc_int n) (doc_int (n+m-1))))
+ | Typ_app(Id_aux (Id "vector", _), [
+ Typ_arg_aux(Typ_arg_nexp (Nexp_aux(Nexp_constant n, _)), _);
+ Typ_arg_aux(Typ_arg_nexp (Nexp_aux(Nexp_constant m, _)), _);
+ Typ_arg_aux (Typ_arg_order (Ord_aux (Ord_dec, _)), _);
+ Typ_arg_aux (Typ_arg_typ (Typ_aux (Typ_id id, _)), _)]) ->
+ (doc_id id) ^^ (brackets (if n = m-1 then doc_int m else doc_op colon (doc_int n) (doc_int (m+1 -n))))
+ | Typ_app(Id_aux (Id "vector", _), [
+ Typ_arg_aux(Typ_arg_nexp
+ (Nexp_aux(Nexp_minus (Nexp_aux(Nexp_constant n, _),
+ Nexp_aux(Nexp_constant 1, _)),_)),_);
+ Typ_arg_aux(Typ_arg_nexp (Nexp_aux(Nexp_constant m, _)), _);
+ Typ_arg_aux (Typ_arg_order (Ord_aux (Ord_dec, _)), _);
+ Typ_arg_aux (Typ_arg_typ (Typ_aux (Typ_id id, _)), _)]) ->
+ (doc_id id) ^^ (brackets (if n = m then doc_int m else doc_op colon (doc_int m) (doc_int (n-1))))
+ | Typ_app(Id_aux (Id "vector", _), [
+ Typ_arg_aux(Typ_arg_nexp
+ (Nexp_aux(Nexp_minus (n', Nexp_aux((Nexp_constant 1), _)),_) as n_n),_);
+ Typ_arg_aux(Typ_arg_nexp m_nexp, _);
+ Typ_arg_aux (Typ_arg_order (Ord_aux (Ord_dec, _)), _);
+ Typ_arg_aux (Typ_arg_typ (Typ_aux (Typ_id id, _)), _)]) ->
+ (doc_id id) ^^ (brackets (if n' = m_nexp then nexp m_nexp else doc_op colon (nexp m_nexp) (nexp n_n)))
+ | Typ_app(Id_aux (Id "vector", _), [
+ Typ_arg_aux(Typ_arg_nexp
+ (Nexp_aux(Nexp_sum (n', Nexp_aux((Nexp_constant -1), _)),_) as n_n),_);
+ Typ_arg_aux(Typ_arg_nexp m_nexp, _);
+ Typ_arg_aux (Typ_arg_order (Ord_aux (Ord_dec, _)), _);
+ Typ_arg_aux (Typ_arg_typ (Typ_aux (Typ_id id, _)), _)]) ->
+ (doc_id id) ^^ (brackets (if n' = m_nexp then nexp m_nexp else doc_op colon (nexp m_nexp) (nexp n_n)))
+ | Typ_app(Id_aux (Id "range", _), [
+ Typ_arg_aux(Typ_arg_nexp (Nexp_aux(Nexp_constant n, _)), _);
+ Typ_arg_aux(Typ_arg_nexp m, _);]) ->
+ (squarebars (if n = 0 then nexp m else doc_op colon (doc_int n) (nexp m)))
+ | Typ_app(Id_aux (Id "atom", _), [Typ_arg_aux(Typ_arg_nexp n,_)]) ->
+ (squarecolons (nexp n))
+ | Typ_app(id,args) ->
+ (* trailing space to avoid >> token in case of nested app types *)
+ (doc_id id) ^^ (angles (separate_map comma_sp doc_typ_arg args)) ^^ space
+ | _ -> atomic_typ ty (* for simplicity, skip vec_typ - which is only sugar *)
+ and atomic_typ ((Typ_aux (t, _)) as ty) = match t with
+ | Typ_id id -> doc_id 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 *)
+ group (parens (typ ty))
+ and doc_typ_arg (Typ_arg_aux(t,_)) = match t with
+ (* Be careful here because typ_arg is implemented as nexp in the
+ * parser - in practice falling through app_typ after all the proper nexp
+ * cases; so Typ_arg_typ has the same precedence as a Typ_app *)
+ | Typ_arg_typ t -> app_typ t
+ | Typ_arg_nexp n -> nexp n
+ | Typ_arg_order o -> doc_ord o
+ | Typ_arg_effect e -> doc_effects e
+
+ (* same trick to handle precedence of nexp *)
+ and nexp ne = sum_typ ne
+ and sum_typ ((Nexp_aux(n,_)) as ne) = match n with
+ | Nexp_sum(n1,n2) -> doc_op plus (sum_typ n1) (star_typ n2)
+ | Nexp_minus(n1,n2) -> doc_op minus (sum_typ n1) (star_typ n2)
+ | _ -> star_typ ne
+ and star_typ ((Nexp_aux(n,_)) as ne) = match n with
+ | Nexp_times(n1,n2) -> doc_op star (star_typ n1) (exp_typ n2)
+ | _ -> exp_typ ne
+ and exp_typ ((Nexp_aux(n,_)) as ne) = match n with
+ | Nexp_exp n1 -> doc_unop (string "2**") (atomic_nexp_typ n1)
+ | _ -> neg_typ ne
+ and neg_typ ((Nexp_aux(n,_)) as ne) = match n with
+ | Nexp_neg n1 ->
+ (* XXX this is not valid Sail, only an internal representation -
+ * work around by commenting it *)
+ let minus = concat [string "(*"; minus; string "*)"] in
+ minus ^^ (atomic_nexp_typ n1)
+ | _ -> atomic_nexp_typ ne
+ and atomic_nexp_typ ((Nexp_aux(n,_)) as ne) = match n with
+ | Nexp_var v -> doc_var v
+ | Nexp_id i -> doc_id i
+ | Nexp_constant i -> doc_int i
+ | Nexp_neg _ | Nexp_exp _ | Nexp_times _ | Nexp_sum _ | Nexp_minus _->
+ group (parens (nexp ne))
+
+ (* expose doc_typ, doc_atomic_typ and doc_nexp *)
+ in typ, atomic_typ, nexp
+
+let pp_format_id (Id_aux(i,_)) =
+ match i with
+ | Id(i) -> i
+ | DeIid(x) -> "(deinfix " ^ x ^ ")"
+
+let rec list_format (sep : string) (fmt : 'a -> string) (ls : 'a list) : string =
+ match ls with
+ | [] -> ""
+ | [a] -> fmt a
+ | a::ls -> (fmt a) ^ sep ^ (list_format sep fmt ls)
+
+let print ?(len=100) channel doc = ToChannel.pretty 1. len channel doc
+let to_buf ?(len=100) buf doc = ToBuffer.pretty 1. len buf doc
diff --git a/src/pretty_print_lem.ml b/src/pretty_print_lem.ml
new file mode 100644
index 00000000..969bc5ba
--- /dev/null
+++ b/src/pretty_print_lem.ml
@@ -0,0 +1,1197 @@
+(**************************************************************************)
+(* Sail *)
+(* *)
+(* Copyright (c) 2013-2017 *)
+(* Kathyrn Gray *)
+(* Shaked Flur *)
+(* Stephen Kell *)
+(* Gabriel Kerneis *)
+(* Robert Norton-Wright *)
+(* Christopher Pulte *)
+(* Peter Sewell *)
+(* *)
+(* 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_internal
+open Ast
+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 (Effect_aux (eff,_)) =
+ match eff with
+ | Effect_var _ -> failwith "effectful: Effect_var not supported"
+ | Effect_set effs ->
+ List.exists
+ (fun (BE_aux (eff,_)) ->
+ match eff with
+ | BE_rreg | BE_wreg | BE_rmem | BE_wmem | BE_eamem | BE_wmv
+ | BE_barr | BE_depend | BE_nondet | BE_escape -> true
+ | _ -> false)
+ effs
+
+let rec is_number {t=t} =
+ match t with
+ | Tabbrev (t1,t2) -> is_number t1 || is_number t2
+ | Tapp ("range",_)
+ | Tapp ("implicit",_)
+ | Tapp ("atom",_) -> true
+ | _ -> false
+
+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_typ typa, _)]) ->
+ let tpp = string "vector" ^^ space ^^ typ regtypes typa in
+ if atyp_needed then parens tpp else tpp
+ | 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_aux (Id name,_)) as id) ->
+ if List.exists ((=) name) 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 false t
+ | Typ_arg_nexp n -> empty
+ | Typ_arg_order o -> empty
+ | Typ_arg_effect e -> empty
+ in typ', atomic_typ
+
+(* 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 ->
+ let (Base ((_,{t = t}),_,_,_,_,_)) = a in
+ (match t with
+ | Tid "bit"
+ | Tabbrev ({t = Tid "bit"},_) -> "BU"
+ | Tapp ("register",_)
+ | Tabbrev ({t = Tapp ("register",_)},_) -> "UndefinedRegister 0"
+ | Tid "string"
+ | Tabbrev ({t = Tapp ("string",_)},_) -> "\"\""
+ | _ -> "(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))
+
+(*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
+ | Base(_,(Constructor _ | Enum _),_,_,_,_) ->
+ 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
+ | Base(_,(Constructor _| Enum _),_,_,_,_) -> 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*)
+
+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))) =
+ 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 (_,(Base ((_,{t = t}),tag,_,_,_,_))) = tannot in
+ (match le_act, t, tag with
+ | LEXP_vector_range (le,e2,e3),_,_ ->
+ (match le with
+ | LEXP_aux (LEXP_field (le,id), (_,((Base ((_,{t = t}),_,_,_,_,_))))) ->
+ if t = Tid "bit" 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), (Tid "bit" | Tabbrev (_,{t=Tid "bit"})),_ ->
+ (match le with
+ | LEXP_aux (LEXP_field (le,id), (_,((Base ((_,{t = t}),_,_,_,_,_))))) ->
+ if t = Tid "bit" 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), (Tid "bit"| Tabbrev (_,{t=Tid "bit"})), _ ->
+ (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(l,r) ->
+ let epp =
+ align (group (separate space [expY l;string "^^"] ^/^ expY r)) in
+ if aexp_needed then parens epp else epp
+ | E_cons(l,r) -> doc_op (group (colon^^colon)) (expY l) (expY r)
+ | 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 epp = separate space [string "slice_raw";expY e1;expY e2;expY e3] in
+ if aexp_needed then parens (align epp) else epp
+ | _ ->
+ begin match annot with
+ | Base (_,External (Some "bitwise_not_bit"),_,_,_,_) ->
+ let [a] = args in
+ let epp = align (string "~" ^^ expY a) in
+ if aexp_needed then parens (align epp) else epp
+ | Base (_,Constructor _,_,_,_,_) ->
+ let argpp a_needed arg =
+ let (E_aux (_,(_,Base((_,{t=t}),_,_,_,_,_)))) = arg in
+ match t with
+ | Tapp("vector",_) ->
+ let epp = concat [string "reset_vector_start";space;expY arg] in
+ if a_needed then parens epp else epp
+ | _ -> 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 (E_aux (_,(_,Base((_,{t=t}),_,_,_,_,_)))) = arg in
+ match t with
+ | Tapp("vector",_) ->
+ let epp = concat [string "reset_vector_start";space;expY arg] in
+ if a_needed then parens epp else epp
+ | _ -> 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
+ if aexp_needed then parens (align epp) else epp
+ end
+ end
+ | E_vector_access (v,e) ->
+ let (Base (_,_,_,_,eff,_)) = annot in
+ let epp =
+ if has_rreg_effect eff then
+ separate space [string "read_reg_bit";expY v;expY e]
+ else
+ separate space [string "access";expY v;expY e] in
+ if aexp_needed then parens (align epp) else epp
+ | E_vector_subrange (v,e1,e2) ->
+ let (Base (_,_,_,_,eff,_)) = annot in
+ let epp =
+ if has_rreg_effect eff then
+ align (string "read_reg_range" ^^ space ^^ expY v ^//^ expY e1 ^//^ expY e2)
+ else
+ align (string "slice" ^^ space ^^ expY v ^//^ expY e1 ^//^ expY e2) in
+ if aexp_needed then parens (align epp) else epp
+ | E_field((E_aux(_,(l,fannot)) as fexp),id) ->
+ let (Base ((_,{t = t}),_,_,_,_,_)) = fannot in
+ (match t with
+ | Tabbrev({t = Tid regtyp},{t=Tapp("register",_)}) ->
+ let field_f = match annot with
+ | Base((_,{t = Tid "bit"}),_,_,_,_,_)
+ | Base((_,{t = Tabbrev(_,{t=Tid "bit"})}),_,_,_,_,_) ->
+ string "read_reg_bitfield"
+ | _ -> string "read_reg_field" in
+ let epp = field_f ^^ space ^^ (expY fexp) ^^ space ^^ string_lit (doc_id_lem id) in
+ if aexp_needed then parens (align epp) else epp
+ | Tid recordtyp
+ | Tabbrev ({t = Tid recordtyp},_) ->
+ let fname =
+ if prefix_recordtype
+ then (string (recordtyp ^ "_")) ^^ 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 ->
+ (match annot with
+ | Base((_, ({t = Tapp("register",_)} | {t=Tabbrev(_,{t=Tapp("register",_)})})),
+ External _,_,eff,_,_) ->
+ if has_rreg_effect eff then
+ separate space [string "read_reg";doc_id_lem id]
+ else
+ doc_id_lem id
+ | Base(_,(Constructor i |Enum i),_,_,_,_) -> doc_id_lem_ctor id
+ | Base((_,t),Alias alias_info,_,eff,_,_) ->
+ (match alias_info with
+ | Alias_field(reg,field) ->
+ let epp = match t.t with
+ | Tid "bit" | Tabbrev (_,{t=Tid "bit"}) ->
+ (separate space)
+ [string "read_reg_bitfield"; string reg;string_lit(string field)]
+ | _ ->
+ (separate space)
+ [string "read_reg_field"; string reg; string_lit(string field)] in
+ if aexp_needed then parens (align epp) else epp
+ | Alias_pair(reg1,reg2) ->
+ let epp =
+ if has_rreg_effect eff then
+ separate space [string "read_two_regs";string reg1;string reg2]
+ else
+ separate space [string "RegisterPair";string reg1;string reg2] in
+ if aexp_needed then parens (align epp) else epp
+ | Alias_extract(reg,start,stop) ->
+ let epp =
+ if start = stop then
+ (separate space)
+ [string "access";doc_int start;
+ parens (string "read_reg" ^^ space ^^ string reg)]
+ else
+ (separate space)
+ [string "slice"; doc_int start; doc_int stop;
+ parens (string "read_reg" ^^ space ^^ string reg)] 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_aux (typ,_),e) ->
+ (match annot with
+ | Base(_,External _,_,_,_,_) -> string "read_reg" ^^ space ^^ expY e
+ | _ ->
+ (match typ with
+ | Typ_app (Id_aux (Id "vector",_), [Typ_arg_aux (Typ_arg_nexp(Nexp_aux (Nexp_constant i,_)),_);_;_;_]) ->
+ let epp = (concat [string "set_vector_start";space;string (string_of_int i)]) ^//^
+ expY e in
+ if aexp_needed then parens epp else epp
+ | Typ_var (Kid_aux (Var "length",_)) ->
+ let epp = (string "set_vector_start_to_length") ^//^ 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 (Base ((_,{t = t}),_,_,_,_,_)) = annot in
+ let recordtyp = match t with
+ | Tid recordtyp
+ | Tabbrev ({t = Tid recordtyp},_) -> recordtyp
+ | _ -> 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 (Base ((_,{t = t}),_,_,_,_,_)) = annot in
+ let recordtyp = match t with
+ | Tid recordtyp
+ | Tabbrev ({t = Tid recordtyp},_) -> recordtyp
+ | _ -> 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 ->
+ (match annot with
+ | Base((_,t),_,_,_,_,_) ->
+ match t.t with
+ | Tapp("vector", [TA_nexp start; _; TA_ord order; _])
+ | Tabbrev(_,{t= Tapp("vector", [TA_nexp start; _; TA_ord order; _])}) ->
+ let dir,dir_out = match order.order with
+ | Oinc -> true,"true"
+ | _ -> false, "false" in
+ let start = match start.nexp with
+ | Nconst i -> string_of_big_int i
+ | N2n(_,Some i) -> string_of_big_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
+ if aexp_needed then parens (align epp) else epp
+ )
+ | E_vector_indexed (iexps, (Def_val_aux (default,(dl,dannot)))) ->
+ let (Base((_,t),_,_,_,_,_)) = annot in
+ let call = string "make_indexed_vector" in
+ let (start,len,order) = match t.t with
+ | Tapp("vector", [TA_nexp start; TA_nexp len; TA_ord order; _])
+ | Tabbrev(_,{t= Tapp("vector", [TA_nexp start; TA_nexp len; TA_ord order; _])})
+ | Tapp("reg", [TA_typ {t =Tapp("vector", [TA_nexp start; TA_nexp len; TA_ord order; _])}]) ->
+ (start,len,order.order) in
+ let dir,dir_out = match order with
+ | Oinc -> true,"true"
+ | _ -> false, "false" in
+ let start = match start.nexp with
+ | Nconst i | N2n(_,Some i)-> string_of_big_int i
+ | N2n({nexp=Nconst i},_) -> string_of_int (Util.power 2 (int_of_big_int i))
+ | _ -> if dir then "0" else string_of_int (List.length iexps) in
+ let size = match len.nexp with
+ | Nconst i | N2n(_,Some i)-> string_of_big_int i
+ | N2n({nexp=Nconst i},_) -> string_of_int (Util.power 2 (int_of_big_int i)) in
+ let default_string =
+ match default with
+ | Def_val_empty ->
+ if is_bit_vector 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})]) ->
+
+ 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 epp =
+ align (group (call ^//^ brackets expspp ^/^
+ separate space [default_string;string start;string size;string dir_out])) in
+ if aexp_needed then parens (align epp) else epp
+ | E_vector_update(v,e1,e2) ->
+ let epp = separate space [string "update_pos";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 epp = align (string "update" ^//^
+ 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_aux(_,(_,annot)) as e) =
+ match annot with
+ | Base((_,t),_,_,_,_,_) ->
+ if is_number t then
+ let e_pp = expY e in
+ align (string "toNatural" ^//^ e_pp)
+ else
+ (match t with
+ | {t = Ttup ([t1;t2;t3;t4;t5] as ts)} when List.for_all is_number ts ->
+ let e_pp = expY e in
+ align (string "toNaturalFiveTup" ^//^ e_pp)
+ | _ -> expY e)
+ | _ -> 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) ->
+ (match annot with
+ | Base((_,t),External(Some name),_,_,_,_) ->
+ let argpp arg =
+ let (E_aux (_,(_,Base((_,{t=t}),_,_,_,_,_)))) = arg in
+ match t with
+ | Tapp("vector",_) -> parens (concat [string "reset_vector_start";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
+ 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;]
+ 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 (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 "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 "instruction_kind"),_) -> 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
+ let clauses =
+ clauses ^^ (break 1) ^^
+ (separate space
+ [pipe;doc_pat_lem regtypes false pat;arrow;
+ string aux_fname;
+ doc_pat_lem regtypes true (P_aux (P_tup argspat, pannot))]) 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 annot with
+ | Base((_,t),_,_,_,_,_) ->
+ (match t.t with
+ | Tapp("register", [TA_typ {t= Tapp("vector", [TA_nexp start; TA_nexp size; TA_ord order; TA_typ itemt])}])
+ | Tapp("register", [TA_typ {t= Tabbrev(_,{t=Tapp("vector", [TA_nexp start; TA_nexp size; TA_ord order; TA_typ itemt])})}]) ->
+ (match itemt.t,start.nexp,size.nexp with
+ | Tid "bit", Nconst start, Nconst size ->
+ let o = if order.order = Oinc 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 (int_of_big_int size);
+ doc_int (int_of_big_int start);
+ string o;
+ string "[]"]))
+ ^/^ hardline
+ | _ ->
+ let (Id_aux (Id name,_)) = id in
+ failwith ("can't deal with register " ^ name))
+ | Tapp("register", [TA_typ {t=Tid idt}])
+ | Tid idt
+ | Tabbrev( {t= Tid idt}, _) ->
+ separate space [string "let";doc_id_lem id;equals;
+ string "build_" ^^ string idt;string_lit (doc_id_lem id)] ^/^ hardline
+ |_-> empty)
+ | _ -> 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) -> 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_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/pretty_print_lem_ast.ml b/src/pretty_print_lem_ast.ml
new file mode 100644
index 00000000..03b8bdf5
--- /dev/null
+++ b/src/pretty_print_lem_ast.ml
@@ -0,0 +1,711 @@
+(**************************************************************************)
+(* Sail *)
+(* *)
+(* Copyright (c) 2013-2017 *)
+(* Kathyrn Gray *)
+(* Shaked Flur *)
+(* Stephen Kell *)
+(* Gabriel Kerneis *)
+(* Robert Norton-Wright *)
+(* Christopher Pulte *)
+(* Peter Sewell *)
+(* *)
+(* 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_internal
+open Ast
+open Format
+open Big_int
+open Pretty_print_common
+
+(****************************************************************************
+ * annotated source to Lem ast pretty printer
+****************************************************************************)
+
+let rec list_pp i_format l_format =
+ fun ppf l ->
+ match l with
+ | [] -> fprintf ppf ""
+ | [i] -> fprintf ppf "%a" l_format i
+ | i::is -> fprintf ppf "%a%a" i_format i (list_pp i_format l_format) is
+
+let kwd ppf s = fprintf ppf "%s" s
+let base ppf s = fprintf ppf "%s" s
+
+let lemnum default n = match n with
+ | 0 -> "zero"
+ | 1 -> "one"
+ | 2 -> "two"
+ | 3 -> "three"
+ | 4 -> "four"
+ | 5 -> "five"
+ | 6 -> "six"
+ | 7 -> "seven"
+ | 8 -> "eight"
+ | 15 -> "fifteen"
+ | 16 -> "sixteen"
+ | 20 -> "twenty"
+ | 23 -> "twentythree"
+ | 24 -> "twentyfour"
+ | 30 -> "thirty"
+ | 31 -> "thirtyone"
+ | 32 -> "thirtytwo"
+ | 35 -> "thirtyfive"
+ | 39 -> "thirtynine"
+ | 40 -> "forty"
+ | 47 -> "fortyseven"
+ | 48 -> "fortyeight"
+ | 55 -> "fiftyfive"
+ | 56 -> "fiftysix"
+ | 57 -> "fiftyseven"
+ | 61 -> "sixtyone"
+ | 63 -> "sixtythree"
+ | 64 -> "sixtyfour"
+ | 127 -> "onetwentyseven"
+ | 128 -> "onetwentyeight"
+ | _ -> if n >= 0 then default n else ("(zero - " ^ (default (abs n)) ^ ")")
+
+let pp_format_id (Id_aux(i,_)) =
+ match i with
+ | Id(i) -> i
+ | DeIid(x) -> "(deinfix " ^ x ^ ")"
+
+let pp_format_var (Kid_aux(Var v,_)) = v
+
+let rec pp_format_l_lem = function
+ | Parse_ast.Unknown -> "Unknown"
+ | _ -> "Unknown"(*
+ | Parse_ast.Int(s,None) -> "(Int \"" ^ s ^ "\" Nothing)"
+ | Parse_ast.Int(s,(Some l)) -> "(Int \"" ^ s ^ "\" (Just " ^ (pp_format_l_lem l) ^ "))"
+ | Parse_ast.Range(p1,p2) -> "(Range \"" ^ p1.Lexing.pos_fname ^ "\" " ^
+ (string_of_int p1.Lexing.pos_lnum) ^ " " ^
+ (string_of_int (p1.Lexing.pos_cnum - p1.Lexing.pos_bol)) ^ " " ^
+ (string_of_int p2.Lexing.pos_lnum) ^ " " ^
+ (string_of_int (p2.Lexing.pos_cnum - p2.Lexing.pos_bol)) ^ ")"
+ | Parse_ast.Generated l -> "(Generated " ^ (pp_format_l_lem l) ^ ")"
+ | _ -> "Unknown"*)
+
+let pp_lem_l ppf l = base ppf (pp_format_l_lem l)
+
+let pp_format_id_lem (Id_aux(i,l)) =
+ "(Id_aux " ^
+ (match i with
+ | Id(i) -> "(Id \"" ^ i ^ "\")"
+ | DeIid(x) -> "(DeIid \"" ^ x ^ "\")") ^ " " ^
+ (pp_format_l_lem l) ^ ")"
+
+let pp_lem_id ppf id = base ppf (pp_format_id_lem id)
+
+let pp_format_var_lem (Kid_aux(Var v,l)) = "(Kid_aux (Var \"" ^ v ^ "\") " ^ (pp_format_l_lem l) ^ ")"
+
+let pp_lem_var ppf var = base ppf (pp_format_var_lem var)
+
+let pp_format_bkind_lem (BK_aux(k,l)) =
+ "(BK_aux " ^
+ (match k with
+ | BK_type -> "BK_type"
+ | BK_nat -> "BK_nat"
+ | BK_order -> "BK_order"
+ | BK_effect -> "BK_effect") ^ " " ^
+ (pp_format_l_lem l) ^ ")"
+
+let pp_lem_bkind ppf bk = base ppf (pp_format_bkind_lem bk)
+
+let pp_format_kind_lem (K_aux(K_kind(klst),l)) =
+ "(K_aux (K_kind [" ^ list_format "; " pp_format_bkind_lem klst ^ "]) " ^ (pp_format_l_lem l) ^ ")"
+
+let pp_lem_kind ppf k = base ppf (pp_format_kind_lem k)
+
+let rec pp_format_typ_lem (Typ_aux(t,l)) =
+ "(Typ_aux " ^
+ (match t with
+ | Typ_id(id) -> "(Typ_id " ^ pp_format_id_lem id ^ ")"
+ | Typ_var(var) -> "(Typ_var " ^ pp_format_var_lem var ^ ")"
+ | Typ_fn(arg,ret,efct) -> "(Typ_fn " ^ pp_format_typ_lem arg ^ " " ^
+ pp_format_typ_lem ret ^ " " ^
+ (pp_format_effects_lem efct) ^ ")"
+ | Typ_tup(typs) -> "(Typ_tup [" ^ (list_format "; " pp_format_typ_lem typs) ^ "])"
+ | Typ_app(id,args) -> "(Typ_app " ^ (pp_format_id_lem id) ^ " [" ^ (list_format "; " pp_format_typ_arg_lem args) ^ "])"
+ | Typ_wild -> "Typ_wild") ^ " " ^
+ (pp_format_l_lem l) ^ ")"
+and pp_format_nexp_lem (Nexp_aux(n,l)) =
+ "(Nexp_aux " ^
+ (match n with
+ | Nexp_id(i) -> "(Nexp_id " ^ pp_format_id_lem i ^ ")"
+ | Nexp_var(v) -> "(Nexp_var " ^ pp_format_var_lem v ^ ")"
+ | Nexp_constant(i) -> "(Nexp_constant " ^ (lemnum string_of_int i) ^ ")"
+ | Nexp_sum(n1,n2) -> "(Nexp_sum " ^ (pp_format_nexp_lem n1) ^ " " ^ (pp_format_nexp_lem n2) ^ ")"
+ | Nexp_minus(n1,n2) -> "(Nexp_minus " ^ (pp_format_nexp_lem n1)^ " " ^ (pp_format_nexp_lem n2) ^ ")"
+ | Nexp_times(n1,n2) -> "(Nexp_times " ^ (pp_format_nexp_lem n1) ^ " " ^ (pp_format_nexp_lem n2) ^ ")"
+ | Nexp_exp(n1) -> "(Nexp_exp " ^ (pp_format_nexp_lem n1) ^ ")"
+ | Nexp_neg(n1) -> "(Nexp_neg " ^ (pp_format_nexp_lem n1) ^ ")") ^ " " ^
+ (pp_format_l_lem l) ^ ")"
+and pp_format_ord_lem (Ord_aux(o,l)) =
+ "(Ord_aux " ^
+ (match o with
+ | Ord_var(v) -> "(Ord_var " ^ pp_format_var_lem v ^ ")"
+ | Ord_inc -> "Ord_inc"
+ | Ord_dec -> "Ord_dec") ^ " " ^
+ (pp_format_l_lem l) ^ ")"
+and pp_format_base_effect_lem (BE_aux(e,l)) =
+ "(BE_aux " ^
+ (match e with
+ | BE_rreg -> "BE_rreg"
+ | BE_wreg -> "BE_wreg"
+ | BE_rmem -> "BE_rmem"
+ | BE_wmem -> "BE_wmem"
+ | BE_wmv -> "BE_wmv"
+ | BE_eamem -> "BE_eamem"
+ | BE_barr -> "BE_barr"
+ | BE_depend -> "BE_depend"
+ | BE_undef -> "BE_undef"
+ | BE_unspec -> "BE_unspec"
+ | BE_nondet -> "BE_nondet"
+ | BE_lset -> "BE_lset"
+ | BE_lret -> "BE_lret"
+ | BE_escape -> "BE_escape") ^ " " ^
+ (pp_format_l_lem l) ^ ")"
+and pp_format_effects_lem (Effect_aux(e,l)) =
+ "(Effect_aux " ^
+ (match e with
+ | Effect_var(v) -> "(Effect_var " ^ pp_format_var v ^ ")"
+ | Effect_set(efcts) ->
+ "(Effect_set [" ^
+ (list_format "; " pp_format_base_effect_lem efcts) ^ " ])") ^ " " ^
+ (pp_format_l_lem l) ^ ")"
+and pp_format_typ_arg_lem (Typ_arg_aux(t,l)) =
+ "(Typ_arg_aux " ^
+ (match t with
+ | Typ_arg_typ(t) -> "(Typ_arg_typ " ^ pp_format_typ_lem t ^ ")"
+ | Typ_arg_nexp(n) -> "(Typ_arg_nexp " ^ pp_format_nexp_lem n ^ ")"
+ | Typ_arg_order(o) -> "(Typ_arg_order " ^ pp_format_ord_lem o ^ ")"
+ | Typ_arg_effect(e) -> "(Typ_arg_effect " ^ pp_format_effects_lem e ^ ")") ^ " " ^
+ (pp_format_l_lem l) ^ ")"
+
+let pp_lem_typ ppf t = base ppf (pp_format_typ_lem t)
+let pp_lem_nexp ppf n = base ppf (pp_format_nexp_lem n)
+let pp_lem_ord ppf o = base ppf (pp_format_ord_lem o)
+let pp_lem_effects ppf e = base ppf (pp_format_effects_lem e)
+let pp_lem_beffect ppf be = base ppf (pp_format_base_effect_lem be)
+
+let pp_format_nexp_constraint_lem (NC_aux(nc,l)) =
+ "(NC_aux " ^
+ (match nc with
+ | NC_fixed(n1,n2) -> "(NC_fixed " ^ pp_format_nexp_lem n1 ^ " " ^ pp_format_nexp_lem n2 ^ ")"
+ | NC_bounded_ge(n1,n2) -> "(NC_bounded_ge " ^ pp_format_nexp_lem n1 ^ " " ^ pp_format_nexp_lem n2 ^ ")"
+ | NC_bounded_le(n1,n2) -> "(NC_bounded_le " ^ pp_format_nexp_lem n1 ^ " " ^ pp_format_nexp_lem n2 ^ ")"
+ | NC_nat_set_bounded(id,bounds) -> "(NC_nat_set_bounded " ^
+ pp_format_var_lem id ^
+ " [" ^
+ list_format "; " string_of_int bounds ^
+ "])") ^ " " ^
+ (pp_format_l_lem l) ^ ")"
+
+let pp_lem_nexp_constraint ppf nc = base ppf (pp_format_nexp_constraint_lem nc)
+
+let pp_format_qi_lem (QI_aux(qi,lq)) =
+ "(QI_aux " ^
+ (match qi with
+ | QI_const(n_const) -> "(QI_const " ^ pp_format_nexp_constraint_lem n_const ^ ")"
+ | QI_id(KOpt_aux(ki,lk)) ->
+ "(QI_id (KOpt_aux " ^
+ (match ki with
+ | KOpt_none(var) -> "(KOpt_none " ^ pp_format_var_lem var ^ ")"
+ | KOpt_kind(k,var) -> "(KOpt_kind " ^ pp_format_kind_lem k ^ " " ^ pp_format_var_lem var ^ ")") ^ " " ^
+ (pp_format_l_lem lk) ^ "))") ^ " " ^
+ (pp_format_l_lem lq) ^ ")"
+
+let pp_lem_qi ppf qi = base ppf (pp_format_qi_lem qi)
+
+let pp_format_typquant_lem (TypQ_aux(tq,l)) =
+ "(TypQ_aux " ^
+ (match tq with
+ | TypQ_no_forall -> "TypQ_no_forall"
+ | TypQ_tq(qlist) ->
+ "(TypQ_tq [" ^
+ (list_format "; " pp_format_qi_lem qlist) ^
+ "])") ^ " " ^
+ (pp_format_l_lem l) ^ ")"
+
+let pp_lem_typquant ppf tq = base ppf (pp_format_typquant_lem tq)
+
+let pp_format_typscm_lem (TypSchm_aux(TypSchm_ts(tq,t),l)) =
+ "(TypSchm_aux (TypSchm_ts " ^ (pp_format_typquant_lem tq) ^ " " ^ pp_format_typ_lem t ^ ") " ^
+ (pp_format_l_lem l) ^ ")"
+
+let pp_lem_typscm ppf ts = base ppf (pp_format_typscm_lem ts)
+
+let pp_format_lit_lem (L_aux(lit,l)) =
+ "(L_aux " ^
+ (match lit with
+ | L_unit -> "L_unit"
+ | L_zero -> "L_zero"
+ | L_one -> "L_one"
+ | L_true -> "L_true"
+ | L_false -> "L_false"
+ | L_num(i) -> "(L_num " ^ (lemnum string_of_int i) ^ ")"
+ | L_hex(n) -> "(L_hex \"" ^ n ^ "\")"
+ | L_bin(n) -> "(L_bin \"" ^ n ^ "\")"
+ | L_undef -> "L_undef"
+ | L_string(s) -> "(L_string \"" ^ s ^ "\")") ^ " " ^
+ (pp_format_l_lem l) ^ ")"
+
+let pp_lem_lit ppf l = base ppf (pp_format_lit_lem l)
+
+
+let rec pp_format_t_lem t =
+ match t.t with
+ | Tid i -> "(T_id \"" ^ i ^ "\")"
+ | Tvar i -> "(T_var \"" ^ i ^ "\")"
+ | Tfn(t1,t2,_,e) -> "(T_fn " ^ (pp_format_t_lem t1) ^ " " ^ (pp_format_t_lem t2) ^ " " ^ pp_format_e_lem e ^ ")"
+ | Ttup(tups) -> "(T_tup [" ^ (list_format "; " pp_format_t_lem tups) ^ "])"
+ | Tapp(i,args) -> "(T_app \"" ^ i ^ "\" (T_args [" ^ list_format "; " pp_format_targ_lem args ^ "]))"
+ | Tabbrev(ti,ta) -> "(T_abbrev " ^ (pp_format_t_lem ti) ^ " " ^ (pp_format_t_lem ta) ^ ")"
+ | Tuvar(_) -> "(T_var \"fresh_v\")"
+ | Toptions _ -> "(T_var \"fresh_v\")"
+and pp_format_targ_lem = function
+ | TA_typ t -> "(T_arg_typ " ^ pp_format_t_lem t ^ ")"
+ | TA_nexp n -> "(T_arg_nexp " ^ pp_format_n_lem n ^ ")"
+ | TA_eft e -> "(T_arg_effect " ^ pp_format_e_lem e ^ ")"
+ | TA_ord o -> "(T_arg_order " ^ pp_format_o_lem o ^ ")"
+and pp_format_n_lem n =
+ match n.nexp with
+ | Nid (i, n) -> "(Ne_id \"" ^ i ^ " " ^ "\")"
+ | Nvar i -> "(Ne_var \"" ^ i ^ "\")"
+ | Nconst i -> "(Ne_const " ^ (lemnum string_of_int (int_of_big_int i)) ^ ")"
+ | Npos_inf -> "Ne_inf"
+ | Nadd(n1,n2) -> "(Ne_add [" ^ (pp_format_n_lem n1) ^ "; " ^ (pp_format_n_lem n2) ^ "])"
+ | Nsub(n1,n2) -> "(Ne_minus "^ (pp_format_n_lem n1) ^ " " ^ (pp_format_n_lem n2) ^ ")"
+ | Nmult(n1,n2) -> "(Ne_mult " ^ (pp_format_n_lem n1) ^ " " ^ (pp_format_n_lem n2) ^ ")"
+ | N2n(n,Some i) -> "(Ne_exp " ^ (pp_format_n_lem n) ^ "(*" ^ string_of_big_int i ^ "*)" ^ ")"
+ | N2n(n,None) -> "(Ne_exp " ^ (pp_format_n_lem n) ^ ")"
+ | Nneg n -> "(Ne_unary " ^ (pp_format_n_lem n) ^ ")"
+ | Nuvar _ -> "(Ne_var \"fresh_v_" ^ string_of_int (get_index n) ^ "\")"
+ | Nneg_inf -> "(Ne_unary Ne_inf)"
+ | Npow _ -> "power_not_implemented"
+ | Ninexact -> "(Ne_add Ne_inf (Ne_unary Ne_inf)"
+and pp_format_e_lem e =
+ "(Effect_aux " ^
+ (match e.effect with
+ | Evar i -> "(Effect_var (Kid_aux (Var \"" ^ i ^ "\") Unknown))"
+ | Eset es -> "(Effect_set [" ^
+ (list_format "; " pp_format_base_effect_lem es) ^ " ])"
+ | Euvar(_) -> "(Effect_var (Kid_aux (Var \"fresh_v\") Unknown))")
+ ^ " Unknown)"
+and pp_format_o_lem o =
+ "(Ord_aux " ^
+ (match o.order with
+ | Ovar i -> "(Ord_var (Kid_aux (Var \"" ^ i ^ "\") Unknown))"
+ | Oinc -> "Ord_inc"
+ | Odec -> "Ord_dec"
+ | Ouvar(_) -> "(Ord_var (Kid_aux (Var \"fresh_v\") Unknown))")
+ ^ " Unknown)"
+
+let rec pp_format_tag = function
+ | Emp_local -> "Tag_empty"
+ | Emp_intro -> "Tag_intro"
+ | Emp_set -> "Tag_set"
+ | Emp_global -> "Tag_global"
+ | Tuple_assign tags -> (*"(Tag_tuple_assign [" ^ list_format " ;" pp_format_tag tags ^ "])"*) "Tag_tuple_assign"
+ | External (Some s) -> "(Tag_extern (Just \""^s^"\"))"
+ | External None -> "(Tag_extern Nothing)"
+ | Default -> "Tag_default"
+ | Constructor _ -> "Tag_ctor"
+ | Enum i -> "(Tag_enum " ^ (lemnum string_of_int i) ^ ")"
+ | Alias alias_inf -> "Tag_alias"
+ | Spec -> "Tag_spec"
+
+let rec pp_format_nes nes =
+ "[" ^ (*
+ (list_format "; "
+ (fun ne -> match ne with
+ | LtEq(_,n1,n2) -> "(Nec_lteq " ^ pp_format_n_lem n1 ^ " " ^ pp_format_n_lem n2 ^ ")"
+ | Eq(_,n1,n2) -> "(Nec_eq " ^ pp_format_n_lem n1 ^ " " ^ pp_format_n_lem n2 ^ ")"
+ | GtEq(_,n1,n2) -> "(Nec_gteq " ^ pp_format_n_lem n1 ^ " " ^ pp_format_n_lem n2 ^ ")"
+ | In(_,i,ns) | InS(_,{nexp=Nvar i},ns) ->
+ "(Nec_in \"" ^ i ^ "\" [" ^ (list_format "; " string_of_int ns)^ "])"
+ | InS(_,_,ns) ->
+ "(Nec_in \"fresh\" [" ^ (list_format "; " string_of_int ns)^ "])"
+ | CondCons(_,nes_c,nes_t) ->
+ "(Nec_cond " ^ (pp_format_nes nes_c) ^ " " ^ (pp_format_nes nes_t) ^ ")"
+ | BranchCons(_,nes_b) ->
+ "(Nec_branch " ^ (pp_format_nes nes_b) ^ ")"
+ )
+ nes) ^*) "]"
+
+let pp_format_annot = function
+ | NoTyp -> "Nothing"
+ | Base((_,t),tag,nes,efct,efctsum,_) ->
+ (*TODO print out bindings for use in pattern match in interpreter*)
+ "(Just (" ^ pp_format_t_lem t ^ ", " ^ pp_format_tag tag ^ ", " ^ pp_format_nes nes ^ ", " ^
+ pp_format_e_lem efct ^ ", " ^ pp_format_e_lem efctsum ^ "))"
+ | Overload _ -> "Nothing"
+
+let pp_annot ppf ant = base ppf (pp_format_annot ant)
+
+
+let rec pp_format_pat_lem (P_aux(p,(l,annot))) =
+ "(P_aux " ^
+ (match p with
+ | P_lit(lit) -> "(P_lit " ^ pp_format_lit_lem lit ^ ")"
+ | P_wild -> "P_wild"
+ | P_id(id) -> "(P_id " ^ pp_format_id_lem id ^ ")"
+ | P_as(pat,id) -> "(P_as " ^ pp_format_pat_lem pat ^ " " ^ pp_format_id_lem id ^ ")"
+ | P_typ(typ,pat) -> "(P_typ " ^ pp_format_typ_lem typ ^ " " ^ pp_format_pat_lem pat ^ ")"
+ | P_app(id,pats) -> "(P_app " ^ pp_format_id_lem id ^ " [" ^
+ list_format "; " pp_format_pat_lem pats ^ "])"
+ | P_record(fpats,_) -> "(P_record [" ^
+ list_format "; " (fun (FP_aux(FP_Fpat(id,fpat),_)) ->
+ "(FP_Fpat " ^ pp_format_id_lem id ^ " " ^ pp_format_pat_lem fpat ^ ")") fpats
+ ^ "])"
+ | P_vector(pats) -> "(P_vector [" ^ list_format "; " pp_format_pat_lem pats ^ "])"
+ | P_vector_indexed(ipats) ->
+ "(P_vector_indexed [" ^ list_format "; " (fun (i,p) -> Printf.sprintf "(%d, %s)" i (pp_format_pat_lem p)) ipats ^ "])"
+ | P_vector_concat(pats) -> "(P_vector_concat [" ^ list_format "; " pp_format_pat_lem pats ^ "])"
+ | P_tup(pats) -> "(P_tup [" ^ (list_format "; " pp_format_pat_lem pats) ^ "])"
+ | P_list(pats) -> "(P_list [" ^ (list_format "; " pp_format_pat_lem pats) ^ "])") ^
+ " (" ^ pp_format_l_lem l ^ ", " ^ pp_format_annot annot ^ "))"
+
+let pp_lem_pat ppf p = base ppf (pp_format_pat_lem p)
+
+let rec pp_lem_let ppf (LB_aux(lb,(l,annot))) =
+ let print_lb ppf lb =
+ match lb with
+ | LB_val_explicit(ts,pat,exp) ->
+ fprintf ppf "@[<0>(%a %a %a %a)@]" kwd "LB_val_explicit" pp_lem_typscm ts pp_lem_pat pat pp_lem_exp exp
+ | LB_val_implicit(pat,exp) ->
+ fprintf ppf "@[<0>(%a %a %a)@]" kwd "LB_val_implicit" pp_lem_pat pat pp_lem_exp exp in
+ fprintf ppf "@[<0>(LB_aux %a (%a, %a))@]" print_lb lb pp_lem_l l pp_annot annot
+
+and pp_lem_exp ppf (E_aux(e,(l,annot))) =
+ let print_e ppf e =
+ match e with
+ | E_block(exps) -> fprintf ppf "@[<0>(E_aux %a [%a] %a (%a, %a))@]"
+ kwd "(E_block"
+ (list_pp pp_semi_lem_exp pp_lem_exp) exps
+ kwd ")" pp_lem_l l pp_annot annot
+ | E_nondet(exps) -> fprintf ppf "@[<0>(E_aux %a [%a] %a (%a, %a))@]"
+ kwd "(E_nondet"
+ (list_pp pp_semi_lem_exp pp_lem_exp) exps
+ kwd ")" pp_lem_l l pp_annot annot
+ | E_id(id) -> fprintf ppf "(E_aux (%a %a) (%a, %a))" kwd "E_id" pp_lem_id id pp_lem_l l pp_annot annot
+ | E_lit(lit) -> fprintf ppf "(E_aux (%a %a) (%a, %a))" kwd "E_lit" pp_lem_lit lit pp_lem_l l pp_annot annot
+ | E_cast(typ,exp) ->
+ fprintf ppf "@[<0>(E_aux (E_cast %a %a) (%a, %a))@]" pp_lem_typ typ pp_lem_exp exp pp_lem_l l pp_annot annot
+ | E_internal_cast((_,NoTyp),e) -> pp_lem_exp ppf e
+ | E_app(f,args) -> fprintf ppf "@[<0>(E_aux (E_app %a [%a]) (%a, %a))@]"
+ pp_lem_id f (list_pp pp_semi_lem_exp pp_lem_exp) args pp_lem_l l pp_annot annot
+ | E_app_infix(l',op,r) -> fprintf ppf "@[<0>(E_aux (E_app_infix %a %a %a) (%a, %a))@]"
+ pp_lem_exp l' pp_lem_id op pp_lem_exp r pp_lem_l l pp_annot annot
+ | E_tuple(exps) -> fprintf ppf "@[<0>(E_aux (E_tuple [%a]) (%a, %a))@]"
+ (list_pp pp_semi_lem_exp pp_lem_exp) exps pp_lem_l l pp_annot annot
+ | E_if(c,t,e) -> fprintf ppf "@[<0>(E_aux (E_if %a @[<1>%a@] @[<1> %a@]) (%a, %a))@]"
+ pp_lem_exp c pp_lem_exp t pp_lem_exp e pp_lem_l l pp_annot annot
+ | E_for(id,exp1,exp2,exp3,order,exp4) ->
+ fprintf ppf "@[<0>(E_aux (E_for %a %a %a %a %a @ @[<1> %a @]) (%a, %a))@]"
+ pp_lem_id id pp_lem_exp exp1 pp_lem_exp exp2 pp_lem_exp exp3
+ pp_lem_ord order pp_lem_exp exp4 pp_lem_l l pp_annot annot
+ | E_vector(exps) -> fprintf ppf "@[<0>(E_aux (%a [%a]) (%a, %a))@]"
+ kwd "E_vector" (list_pp pp_semi_lem_exp pp_lem_exp) exps pp_lem_l l pp_annot annot
+ | E_vector_indexed(iexps,(Def_val_aux (default, (dl,dannot)))) ->
+ let iformat ppf (i,e) = fprintf ppf "@[<1>(%i %a %a) %a@]" i kwd ", " pp_lem_exp e kwd ";" in
+ let lformat ppf (i,e) = fprintf ppf "@[<1>(%i %a %a) @]" i kwd ", " pp_lem_exp e in
+ let default_string ppf _ = (match default with
+ | Def_val_empty -> fprintf ppf "(Def_val_aux Def_val_empty (%a,%a))" pp_lem_l dl pp_annot dannot
+ | Def_val_dec e -> fprintf ppf "(Def_val_aux (Def_val_dec %a) (%a,%a))"
+ pp_lem_exp e pp_lem_l dl pp_annot dannot) in
+ fprintf ppf "@[<0>(E_aux (%a [%a] %a) (%a, %a))@]" kwd "E_vector_indexed"
+ (list_pp iformat lformat) iexps default_string () pp_lem_l l pp_annot annot
+ | E_vector_access(v,e) ->
+ fprintf ppf "@[<0>(E_aux (%a %a %a) (%a, %a))@]"
+ kwd "E_vector_access" pp_lem_exp v pp_lem_exp e pp_lem_l l pp_annot annot
+ | E_vector_subrange(v,e1,e2) ->
+ fprintf ppf "@[<0>(E_aux (E_vector_subrange %a %a %a) (%a, %a))@]"
+ pp_lem_exp v pp_lem_exp e1 pp_lem_exp e2 pp_lem_l l pp_annot annot
+ | E_vector_update(v,e1,e2) ->
+ fprintf ppf "@[<0>(E_aux (E_vector_update %a %a %a) (%a, %a))@]"
+ pp_lem_exp v pp_lem_exp e1 pp_lem_exp e2 pp_lem_l l pp_annot annot
+ | E_vector_update_subrange(v,e1,e2,e3) ->
+ fprintf ppf "@[<0>(E_aux (E_vector_update_subrange %a %a %a %a) (%a, %a))@]"
+ pp_lem_exp v pp_lem_exp e1 pp_lem_exp e2 pp_lem_exp e3 pp_lem_l l pp_annot annot
+ | E_vector_append(v1,v2) ->
+ fprintf ppf "@[<0>(E_aux (E_vector_append %a %a) (%a, %a))@]"
+ pp_lem_exp v1 pp_lem_exp v2 pp_lem_l l pp_annot annot
+ | E_list(exps) -> fprintf ppf "@[<0>(E_aux (E_list [%a]) (%a, %a))@]"
+ (list_pp pp_semi_lem_exp pp_lem_exp) exps pp_lem_l l pp_annot annot
+ | E_cons(e1,e2) -> fprintf ppf "@[<0>(E_aux (E_cons %a %a) (%a, %a))@]"
+ pp_lem_exp e1 pp_lem_exp e2 pp_lem_l l pp_annot annot
+ | E_record(FES_aux(FES_Fexps(fexps,_),(fl,fannot))) ->
+ fprintf ppf "@[<0>(E_aux (E_record (FES_aux (FES_Fexps [%a] false) (%a,%a))) (%a, %a))@]"
+ (list_pp pp_semi_lem_fexp pp_lem_fexp) fexps pp_lem_l fl pp_annot fannot pp_lem_l l pp_annot annot
+ | E_record_update(exp,(FES_aux(FES_Fexps(fexps,_),(fl,fannot)))) ->
+ fprintf ppf "@[<0>(E_aux (E_record_update %a (FES_aux (FES_Fexps [%a] false) (%a,%a))) (%a,%a))@]"
+ pp_lem_exp exp (list_pp pp_semi_lem_fexp pp_lem_fexp) fexps
+ pp_lem_l fl pp_annot fannot pp_lem_l l pp_annot annot
+ | E_field(fexp,id) -> fprintf ppf "@[<0>(E_aux (E_field %a %a) (%a, %a))@]"
+ pp_lem_exp fexp pp_lem_id id pp_lem_l l pp_annot annot
+ | E_case(exp,pexps) ->
+ fprintf ppf "@[<0>(E_aux (E_case %a [%a]) (%a, %a))@]"
+ pp_lem_exp exp (list_pp pp_semi_lem_case pp_lem_case) pexps pp_lem_l l pp_annot annot
+ | E_let(leb,exp) -> fprintf ppf "@[<0>(E_aux (E_let %a %a) (%a, %a))@]"
+ pp_lem_let leb pp_lem_exp exp pp_lem_l l pp_annot annot
+ | E_assign(lexp,exp) -> fprintf ppf "@[<0>(E_aux (E_assign %a %a) (%a, %a))@]"
+ pp_lem_lexp lexp pp_lem_exp exp pp_lem_l l pp_annot annot
+ | E_sizeof nexp ->
+ fprintf ppf "@[<0>(E_aux (E_sizeof %a) (%a, %a))@]" pp_lem_nexp nexp pp_lem_l l pp_annot annot
+ | E_exit exp ->
+ fprintf ppf "@[<0>(E_aux (E_exit %a) (%a, %a))@]" pp_lem_exp exp pp_lem_l l pp_annot annot
+ | E_return exp ->
+ fprintf ppf "@[<0>(E_aux (E_return %a) (%a, %a))@]" pp_lem_exp exp pp_lem_l l pp_annot annot
+ | E_assert(c,msg) ->
+ fprintf ppf "@[<0>(E_aux (E_assert %a %a) (%a, %a))@]" pp_lem_exp c pp_lem_exp msg pp_lem_l l pp_annot annot
+ | E_internal_exp ((l, Base((_,t),_,_,_,_,bindings))) ->
+ (*TODO use bindings where appropriate*)
+ (match t.t with
+ | Tapp("register",[TA_typ {t=Tapp("vector",[TA_nexp _;TA_nexp r;_;_])}])
+ | Tapp("vector",[TA_nexp _;TA_nexp r;_;_]) ->
+ (match r.nexp with
+ | Nconst bi -> fprintf ppf "@[<0>(E_aux (E_lit (L_aux (L_num %a) %a)) (%a, %a))@]"
+ kwd (lemnum string_of_int (int_of_big_int bi)) pp_lem_l l pp_lem_l l pp_annot (Base(([],nat_t),Emp_local,[],pure_e,pure_e,nob))
+ | Nvar v -> fprintf ppf "@[<0>(E_aux (E_id (Id_aux (Id \"%a\") %a)) (%a,%a))@]"
+ kwd v pp_lem_l l pp_lem_l l pp_annot (Base(([],nat_t),Emp_local,[],pure_e,pure_e,nob))
+ | _ -> raise (Reporting_basic.err_unreachable l "Internal exp given vector without known length"))
+ | Tapp("implicit",[TA_nexp r]) ->
+ (match r.nexp with
+ | Nconst bi -> fprintf ppf "@[<0>(E_aux (E_lit (L_aux (L_num %a) %a)) (%a, %a))@]"
+ kwd (lemnum string_of_int (int_of_big_int bi)) pp_lem_l l pp_lem_l l pp_annot (Base(([],nat_t),Emp_local,[],pure_e,pure_e,nob))
+ | Nvar v -> fprintf ppf "@[<0>(E_aux (E_id (Id_aux (Id \"%a\") %a)) (%a,%a))@]"
+ kwd v pp_lem_l l pp_lem_l l pp_annot (Base(([],nat_t),Emp_local,[],pure_e,pure_e,nob))
+ | _ -> raise (Reporting_basic.err_unreachable l "Internal_exp given implicit without variable or const"))
+ | _ -> raise (Reporting_basic.err_unreachable l "Internal exp given non-vector or implicit"))
+ | E_comment _ | E_comment_struc _ ->
+ fprintf ppf "@[(E_aux (E_lit (L_aux L_unit %a)) (%a,%a))@]" pp_lem_l l pp_lem_l l pp_annot annot
+ | E_internal_cast _ | E_internal_exp _ ->
+ raise (Reporting_basic.err_unreachable l "Found internal cast or exp")
+ | E_internal_exp_user _ -> (raise (Reporting_basic.err_unreachable l "Found non-rewritten internal_exp_user"))
+ | E_sizeof_internal _ -> (raise (Reporting_basic.err_unreachable l "Internal sizeof not removed"))
+ | E_internal_let _ -> (raise (Reporting_basic.err_unreachable l "Found non-rewritten internal_let"))
+ | E_internal_return _ -> (raise (Reporting_basic.err_unreachable l "Found non-rewritten internal_return"))
+ | E_internal_plet _ -> raise (Reporting_basic.err_unreachable l "Found non-rewritten internal_plet")
+ in
+ print_e ppf e
+
+and pp_semi_lem_exp ppf e = fprintf ppf "@[<1>%a%a@]" pp_lem_exp e kwd ";"
+
+and pp_lem_fexp ppf (FE_aux(FE_Fexp(id,exp),(l,annot))) =
+ fprintf ppf "@[<1>(FE_aux (FE_Fexp %a %a) (%a, %a))@]" pp_lem_id id pp_lem_exp exp pp_lem_l l pp_annot annot
+and pp_semi_lem_fexp ppf fexp = fprintf ppf "@[<1>%a %a@]" pp_lem_fexp fexp kwd ";"
+
+and pp_lem_case ppf (Pat_aux(Pat_exp(pat,exp),(l,annot))) =
+ fprintf ppf "@[<1>(Pat_aux (Pat_exp %a@ %a) (%a, %a))@]" pp_lem_pat pat pp_lem_exp exp pp_lem_l l pp_annot annot
+and pp_semi_lem_case ppf case = fprintf ppf "@[<1>%a %a@]" pp_lem_case case kwd ";"
+
+and pp_lem_lexp ppf (LEXP_aux(lexp,(l,annot))) =
+ let print_le ppf lexp =
+ match lexp with
+ | LEXP_id(id) -> fprintf ppf "(%a %a)" kwd "LEXP_id" pp_lem_id id
+ | LEXP_memory(id,args) ->
+ fprintf ppf "(LEXP_memory %a [%a])" pp_lem_id id (list_pp pp_semi_lem_exp pp_lem_exp) args
+ | LEXP_cast(typ,id) -> fprintf ppf "(LEXP_cast %a %a)" pp_lem_typ typ pp_lem_id id
+ | LEXP_tup tups -> fprintf ppf "(LEXP_tup [%a])" (list_pp pp_semi_lem_lexp pp_lem_lexp) tups
+ | LEXP_vector(v,exp) -> fprintf ppf "@[(%a %a %a)@]" kwd "LEXP_vector" pp_lem_lexp v pp_lem_exp exp
+ | LEXP_vector_range(v,e1,e2) ->
+ fprintf ppf "@[(%a %a %a %a)@]" kwd "LEXP_vector_range" pp_lem_lexp v pp_lem_exp e1 pp_lem_exp e2
+ | LEXP_field(v,id) -> fprintf ppf "@[(%a %a %a)@]" kwd "LEXP_field" pp_lem_lexp v pp_lem_id id
+ in
+ fprintf ppf "@[(LEXP_aux %a (%a, %a))@]" print_le lexp pp_lem_l l pp_annot annot
+and pp_semi_lem_lexp ppf le = fprintf ppf "@[<1>%a%a@]" pp_lem_lexp le kwd ";"
+
+
+let pp_lem_default ppf (DT_aux(df,l)) =
+ let print_de ppf df =
+ match df with
+ | DT_kind(bk,var) -> fprintf ppf "@[<0>(%a %a %a)@]" kwd "DT_kind" pp_lem_bkind bk pp_lem_var var
+ | DT_typ(ts,id) -> fprintf ppf "@[<0>(%a %a %a)@]" kwd "DT_typ" pp_lem_typscm ts pp_lem_id id
+ | DT_order(ord) -> fprintf ppf "@[<0>(DT_order %a)@]" pp_lem_ord ord
+ in
+ fprintf ppf "@[<0>(DT_aux %a %a)@]" print_de df pp_lem_l l
+
+let pp_lem_spec ppf (VS_aux(v,(l,annot))) =
+ let print_spec ppf v =
+ match v with
+ | VS_val_spec(ts,id) ->
+ fprintf ppf "@[<0>(%a %a %a)@]@\n" kwd "VS_val_spec" pp_lem_typscm ts pp_lem_id id
+ | VS_extern_spec(ts,id,s) ->
+ fprintf ppf "@[<0>(%a %a %a \"%s\")@]@\n" kwd "VS_extern_spec" pp_lem_typscm ts pp_lem_id id s
+ | VS_extern_no_rename(ts,id) ->
+ fprintf ppf "@[<0>(%a %a %a)@]@\n" kwd "VS_extern_no_rename" pp_lem_typscm ts pp_lem_id id
+ in
+ fprintf ppf "@[<0>(VS_aux %a (%a, %a))@]" print_spec v pp_lem_l l pp_annot annot
+
+let pp_lem_namescm ppf (Name_sect_aux(ns,l)) =
+ match ns with
+ | Name_sect_none -> fprintf ppf "(Name_sect_aux Name_sect_none %a)" pp_lem_l l
+ | Name_sect_some(s) -> fprintf ppf "(Name_sect_aux (Name_sect_some \"%s\") %a)" s pp_lem_l l
+
+let rec pp_lem_range ppf (BF_aux(r,l)) =
+ match r with
+ | BF_single(i) -> fprintf ppf "(BF_aux (BF_single %i) %a)" i pp_lem_l l
+ | BF_range(i1,i2) -> fprintf ppf "(BF_aux (BF_range %i %i) %a)" i1 i2 pp_lem_l l
+ | BF_concat(ir1,ir2) -> fprintf ppf "(BF_aux (BF_concat %a %a) %a)" pp_lem_range ir1 pp_lem_range ir2 pp_lem_l l
+
+let pp_lem_typdef ppf (TD_aux(td,(l,annot))) =
+ let print_td ppf td =
+ match td with
+ | TD_abbrev(id,namescm,typschm) ->
+ fprintf ppf "@[<0>(%a %a %a %a)@]" kwd "TD_abbrev" pp_lem_id id pp_lem_namescm namescm pp_lem_typscm typschm
+ | TD_record(id,nm,typq,fs,_) ->
+ let f_pp ppf (typ,id) =
+ fprintf ppf "@[<1>(%a, %a)%a@]" pp_lem_typ typ pp_lem_id id kwd ";" in
+ fprintf ppf "@[<0>(%a %a %a %a [%a] false)@]"
+ kwd "TD_record" pp_lem_id id pp_lem_namescm nm pp_lem_typquant typq (list_pp f_pp f_pp) fs
+ | TD_variant(id,nm,typq,ar,_) ->
+ let a_pp ppf (Tu_aux(typ_u,l)) =
+ match typ_u with
+ | Tu_ty_id(typ,id) -> fprintf ppf "@[<1>(Tu_aux (Tu_ty_id %a %a) %a);@]"
+ pp_lem_typ typ pp_lem_id id pp_lem_l l
+ | Tu_id(id) -> fprintf ppf "@[<1>(Tu_aux (Tu_id %a) %a);@]" pp_lem_id id pp_lem_l l
+ in
+ fprintf ppf "@[<0>(%a %a %a %a [%a] false)@]"
+ kwd "TD_variant" pp_lem_id id pp_lem_namescm nm pp_lem_typquant typq (list_pp a_pp a_pp) ar
+ | TD_enum(id,ns,enums,_) ->
+ let pp_id_semi ppf id = fprintf ppf "%a%a " pp_lem_id id kwd ";" in
+ fprintf ppf "@[<0>(%a %a %a [%a] false)@]"
+ kwd "TD_enum" pp_lem_id id pp_lem_namescm ns (list_pp pp_id_semi pp_lem_id) enums
+ | TD_register(id,n1,n2,rs) ->
+ let pp_rid ppf (r,id) = fprintf ppf "(%a, %a)%a " pp_lem_range r pp_lem_id id kwd ";" in
+ let pp_rids = (list_pp pp_rid pp_rid) in
+ fprintf ppf "@[<0>(%a %a %a %a [%a])@]"
+ kwd "TD_register" pp_lem_id id pp_lem_nexp n1 pp_lem_nexp n2 pp_rids rs
+ in
+ fprintf ppf "@[<0>(TD_aux %a (%a, %a))@]" print_td td pp_lem_l l pp_annot annot
+
+let pp_lem_kindef ppf (KD_aux(kd,(l,annot))) =
+ let print_kd ppf kd =
+ match kd with
+ | KD_abbrev(kind,id,namescm,typschm) ->
+ fprintf ppf "@[<0>(KD_abbrev %a %a %a %a)@]"
+ pp_lem_kind kind pp_lem_id id pp_lem_namescm namescm pp_lem_typscm typschm
+ | KD_nabbrev(kind,id,namescm,n) ->
+ fprintf ppf "@[<0>(KD_nabbrev %a %a %a %a)@]"
+ pp_lem_kind kind pp_lem_id id pp_lem_namescm namescm pp_lem_nexp n
+ | KD_record(kind,id,nm,typq,fs,_) ->
+ let f_pp ppf (typ,id) =
+ fprintf ppf "@[<1>(%a, %a)%a@]" pp_lem_typ typ pp_lem_id id kwd ";" in
+ fprintf ppf "@[<0>(%a %a %a %a %a [%a] false)@]"
+ kwd "KD_record" pp_lem_kind kind pp_lem_id id pp_lem_namescm nm pp_lem_typquant typq (list_pp f_pp f_pp) fs
+ | KD_variant(kind,id,nm,typq,ar,_) ->
+ let a_pp ppf (Tu_aux(typ_u,l)) =
+ match typ_u with
+ | Tu_ty_id(typ,id) -> fprintf ppf "@[<1>(Tu_aux (Tu_ty_id %a %a) %a);@]"
+ pp_lem_typ typ pp_lem_id id pp_lem_l l
+ | Tu_id(id) -> fprintf ppf "@[<1>(Tu_aux (Tu_id %a) %a);@]" pp_lem_id id pp_lem_l l
+ in
+ fprintf ppf "@[<0>(%a %a %a %a %a [%a] false)@]"
+ kwd "KD_variant" pp_lem_kind kind pp_lem_id id pp_lem_namescm nm pp_lem_typquant typq (list_pp a_pp a_pp) ar
+ | KD_enum(kind,id,ns,enums,_) ->
+ let pp_id_semi ppf id = fprintf ppf "%a%a " pp_lem_id id kwd ";" in
+ fprintf ppf "@[<0>(%a %a %a %a [%a] false)@]"
+ kwd "KD_enum" pp_lem_kind kind pp_lem_id id pp_lem_namescm ns (list_pp pp_id_semi pp_lem_id) enums
+ | KD_register(kind,id,n1,n2,rs) ->
+ let pp_rid ppf (r,id) = fprintf ppf "(%a, %a)%a " pp_lem_range r pp_lem_id id kwd ";" in
+ let pp_rids = (list_pp pp_rid pp_rid) in
+ fprintf ppf "@[<0>(%a %a %a %a %a [%a])@]"
+ kwd "KD_register" pp_lem_kind kind pp_lem_id id pp_lem_nexp n1 pp_lem_nexp n2 pp_rids rs
+ in
+ fprintf ppf "@[<0>(KD_aux %a (%a, %a))@]" print_kd kd pp_lem_l l pp_annot annot
+
+let pp_lem_rec ppf (Rec_aux(r,l)) =
+ match r with
+ | Rec_nonrec -> fprintf ppf "(Rec_aux Rec_nonrec %a)" pp_lem_l l
+ | Rec_rec -> fprintf ppf "(Rec_aux Rec_rec %a)" pp_lem_l l
+
+let pp_lem_tannot_opt ppf (Typ_annot_opt_aux(t,l)) =
+ match t with
+ | Typ_annot_opt_some(tq,typ) ->
+ fprintf ppf "(Typ_annot_opt_aux (Typ_annot_opt_some %a %a) %a)" pp_lem_typquant tq pp_lem_typ typ pp_lem_l l
+
+let pp_lem_effects_opt ppf (Effect_opt_aux(e,l)) =
+ match e with
+ | Effect_opt_pure -> fprintf ppf "(Effect_opt_aux Effect_opt_pure %a)" pp_lem_l l
+ | Effect_opt_effect e -> fprintf ppf "(Effect_opt_aux (Effect_opt_effect %a) %a)" pp_lem_effects e pp_lem_l l
+
+let pp_lem_funcl ppf (FCL_aux(FCL_Funcl(id,pat,exp),(l,annot))) =
+ fprintf ppf "@[<0>(FCL_aux (%a %a %a %a) (%a,%a))@]@\n"
+ kwd "FCL_Funcl" pp_lem_id id pp_lem_pat pat pp_lem_exp exp pp_lem_l l pp_annot annot
+
+let pp_lem_fundef ppf (FD_aux(FD_function(r, typa, efa, fcls),(l,annot))) =
+ let pp_funcls ppf funcl = fprintf ppf "%a %a" pp_lem_funcl funcl kwd ";" in
+ fprintf ppf "@[<0>(FD_aux (%a %a %a %a [%a]) (%a, %a))@]"
+ kwd "FD_function" pp_lem_rec r pp_lem_tannot_opt typa pp_lem_effects_opt efa (list_pp pp_funcls pp_funcls) fcls
+ pp_lem_l l pp_annot annot
+
+let pp_lem_aspec ppf (AL_aux(aspec,(l,annot))) =
+ let pp_reg_id ppf (RI_aux((RI_id ri),(l,annot))) =
+ fprintf ppf "@[<0>(RI_aux (RI_id %a) (%a,%a))@]" pp_lem_id ri pp_lem_l l pp_annot annot in
+ match aspec with
+ | AL_subreg(reg,subreg) ->
+ fprintf ppf "@[<0>(AL_aux (AL_subreg %a %a) (%a,%a))@]"
+ pp_reg_id reg pp_lem_id subreg pp_lem_l l pp_annot annot
+ | AL_bit(reg,ac) ->
+ fprintf ppf "@[<0>(AL_aux (AL_bit %a %a) (%a,%a))@]" pp_reg_id reg pp_lem_exp ac pp_lem_l l pp_annot annot
+ | AL_slice(reg,b,e) ->
+ fprintf ppf "@[<0>(AL_aux (AL_slice %a %a %a) (%a,%a))@]"
+ pp_reg_id reg pp_lem_exp b pp_lem_exp e pp_lem_l l pp_annot annot
+ | AL_concat(f,s) ->
+ fprintf ppf "@[<0>(AL_aux (AL_concat %a %a) (%a,%a))@]" pp_reg_id f pp_reg_id s pp_lem_l l pp_annot annot
+
+let pp_lem_dec ppf (DEC_aux(reg,(l,annot))) =
+ match reg with
+ | DEC_reg(typ,id) ->
+ fprintf ppf "@[<0>(DEC_aux (DEC_reg %a %a) (%a,%a))@]" pp_lem_typ typ pp_lem_id id pp_lem_l l pp_annot annot
+ | DEC_alias(id,alias_spec) ->
+ fprintf ppf "@[<0>(DEC_aux (DEC_alias %a %a) (%a, %a))@]"
+ pp_lem_id id pp_lem_aspec alias_spec pp_lem_l l pp_annot annot
+ | DEC_typ_alias(typ,id,alias_spec) ->
+ fprintf ppf "@[<0>(DEC_aux (DEC_typ_alias %a %a %a) (%a, %a))@]"
+ pp_lem_typ typ pp_lem_id id pp_lem_aspec alias_spec pp_lem_l l pp_annot annot
+
+let pp_lem_def ppf d =
+ match d with
+ | DEF_default(df) -> fprintf ppf "(DEF_default %a);@\n" pp_lem_default df
+ | DEF_spec(v_spec) -> fprintf ppf "(DEF_spec %a);@\n" pp_lem_spec v_spec
+ | DEF_type(t_def) -> fprintf ppf "(DEF_type %a);@\n" pp_lem_typdef t_def
+ | DEF_kind(k_def) -> fprintf ppf "(DEF_kind %a);@\n" pp_lem_kindef k_def
+ | DEF_fundef(f_def) -> fprintf ppf "(DEF_fundef %a);@\n" pp_lem_fundef f_def
+ | DEF_val(lbind) -> fprintf ppf "(DEF_val %a);@\n" pp_lem_let lbind
+ | DEF_reg_dec(dec) -> fprintf ppf "(DEF_reg_dec %a);@\n" pp_lem_dec dec
+ | DEF_comm d -> fprintf ppf ""
+ | _ -> raise (Reporting_basic.err_unreachable Parse_ast.Unknown "initial_check didn't remove all scattered Defs")
+
+let pp_lem_defs ppf (Defs(defs)) =
+ fprintf ppf "Defs [@[%a@]]@\n" (list_pp pp_lem_def pp_lem_def) defs
+
diff --git a/src/pretty_print_ocaml.ml b/src/pretty_print_ocaml.ml
new file mode 100644
index 00000000..47aacf0c
--- /dev/null
+++ b/src/pretty_print_ocaml.ml
@@ -0,0 +1,717 @@
+(**************************************************************************)
+(* Sail *)
+(* *)
+(* Copyright (c) 2013-2017 *)
+(* Kathyrn Gray *)
+(* Shaked Flur *)
+(* Stephen Kell *)
+(* Gabriel Kerneis *)
+(* Robert Norton-Wright *)
+(* Christopher Pulte *)
+(* Peter Sewell *)
+(* *)
+(* 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 Big_int
+open Type_internal
+open Ast
+open PPrint
+open Pretty_print_common
+
+(****************************************************************************
+ * PPrint-based sail-to-ocaml pretty printer
+****************************************************************************)
+
+let star_sp = star ^^ space
+
+let doc_id_ocaml (Id_aux(i,_)) =
+ match i with
+ | Id("bit") -> string "vbit"
+ | Id i -> string ("_" ^ 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_ocaml_type (Id_aux(i,_)) =
+ match i with
+ | Id("bit") -> string "vbit"
+ | Id i -> string ("_" ^ 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 (String.uncapitalize x); empty])
+
+let doc_id_ocaml_ctor n (Id_aux(i,_)) =
+ match i with
+ | Id("bit") -> string "vbit"
+ | Id i -> string ((if n > 246 then "`" else "") ^ (String.capitalize 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 (String.capitalize x); empty])
+
+let doc_typ_ocaml, doc_atomic_typ_ocaml =
+ (* following the structure of parser for precedence *)
+ let rec typ ty = fn_typ ty
+ and fn_typ ((Typ_aux (t, _)) as ty) = match t with
+ | Typ_fn(arg,ret,efct) ->
+ separate space [tup_typ arg; arrow; fn_typ ret]
+ | _ -> tup_typ ty
+ and tup_typ ((Typ_aux (t, _)) as ty) = match t with
+ | Typ_tup typs -> parens (separate_map star app_typ typs)
+ | _ -> app_typ ty
+ and app_typ ((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 typ, _)]) ->
+ string "value"
+ | Typ_app(Id_aux (Id "range", _), [
+ Typ_arg_aux(Typ_arg_nexp n, _);
+ Typ_arg_aux(Typ_arg_nexp m, _);]) ->
+ (string "number")
+ | Typ_app(Id_aux (Id "atom", _), [Typ_arg_aux(Typ_arg_nexp n,_)]) ->
+ (string "number")
+ | Typ_app(id,args) ->
+ (separate_map space doc_typ_arg_ocaml args) ^^ space ^^ (doc_id_ocaml_type id)
+ | _ -> atomic_typ ty
+ and atomic_typ ((Typ_aux (t, _)) as ty) = match t with
+ | Typ_id id -> doc_id_ocaml_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 *)
+ group (parens (typ ty))
+ and doc_typ_arg_ocaml (Typ_arg_aux(t,_)) = match t with
+ | Typ_arg_typ t -> app_typ t
+ | Typ_arg_nexp n -> empty
+ | Typ_arg_order o -> empty
+ | Typ_arg_effect e -> empty
+ in typ, atomic_typ
+
+let doc_lit_ocaml in_pat (L_aux(l,_)) =
+ utf8string (match l with
+ | L_unit -> "()"
+ | L_zero -> "Vzero"
+ | L_one -> "Vone"
+ | L_true -> "Vone"
+ | L_false -> "Vzero"
+ | L_num i -> "(big_int_of_int " ^ (string_of_int i) ^ ")"
+ | L_hex n -> "(num_to_vec " ^ ("0x" ^ n) ^ ")" (*shouldn't happen*)
+ | L_bin n -> "(num_to_vec " ^ ("0b" ^ n) ^ ")" (*shouldn't happen*)
+ | L_undef -> "Vundef"
+ | L_string s -> "\"" ^ s ^ "\"")
+
+(* typ_doc is the doc for the type being quantified *)
+let doc_typquant_ocaml (TypQ_aux(tq,_)) typ_doc = typ_doc
+
+let doc_typscm_ocaml (TypSchm_aux(TypSchm_ts(tq,t),_)) =
+ (doc_typquant_ocaml tq (doc_typ_ocaml t))
+
+(*Note: vector concatenation, literal vectors, indexed vectors, and record should
+ be removed prior to pp. The latter two have never yet been seen
+*)
+let doc_pat_ocaml =
+ let rec pat pa = app_pat pa
+ and app_pat ((P_aux(p,(l,annot))) as pa) = match p with
+ | P_app(id, ((_ :: _) as pats)) ->
+ (match annot with
+ | Base(_,Constructor n,_,_,_,_) ->
+ doc_unop (doc_id_ocaml_ctor n id) (parens (separate_map comma_sp pat pats))
+ | _ -> empty)
+ | P_lit lit -> doc_lit_ocaml true lit
+ | P_wild -> underscore
+ | P_id id -> doc_id_ocaml id
+ | P_as(p,id) -> parens (separate space [pat p; string "as"; doc_id_ocaml id])
+ | P_typ(typ,p) -> doc_op colon (pat p) (doc_typ_ocaml typ)
+ | P_app(id,[]) ->
+ (match annot with
+ | Base(_,(Constructor n | Enum n),_,_,_,_) ->
+ doc_id_ocaml_ctor n id
+ | _ -> failwith "encountered unexpected P_app pattern")
+ | P_vector pats ->
+ let non_bit_print () =
+ parens
+ (separate space [string "VvectorR";
+ parens (separate comma_sp [squarebars (separate_map semi pat pats);
+ underscore;
+ underscore])]) in
+ (match annot with
+ | Base(([],t),_,_,_,_,_) ->
+ if is_bit_vector t
+ then parens (separate space [string "Vvector";
+ parens (separate comma_sp [squarebars (separate_map semi pat pats);
+ underscore;
+ underscore])])
+ else non_bit_print()
+ | _ -> non_bit_print ())
+ | P_tup pats -> parens (separate_map comma_sp pat pats)
+ | P_list pats -> brackets (separate_map semi pat pats) (*Never seen but easy in ocaml*)
+ in pat
+
+let doc_exp_ocaml, doc_let_ocaml =
+ let rec top_exp read_registers (E_aux (e, (_,annot))) =
+ let exp = top_exp read_registers in
+ match e with
+ | E_assign((LEXP_aux(le_act,tannot) as le),e) ->
+ (match annot with
+ | Base(_,(Emp_local | Emp_set),_,_,_,_) ->
+ (match le_act with
+ | LEXP_id _ | LEXP_cast _ ->
+ (*Setting local variable fully *)
+ doc_op coloneq (doc_lexp_ocaml true le) (exp e)
+ | LEXP_vector _ ->
+ doc_op (string "<-") (doc_lexp_array_ocaml le) (exp e)
+ | LEXP_vector_range _ ->
+ doc_lexp_rwrite le e)
+ | _ ->
+ (match le_act with
+ | LEXP_vector _ | LEXP_vector_range _ | LEXP_cast _ | LEXP_field _ | LEXP_id _ ->
+ (doc_lexp_rwrite le e)
+ | LEXP_memory _ -> (doc_lexp_fcall le e)))
+ | E_vector_append(l,r) ->
+ parens ((string "vector_concat ") ^^ (exp l) ^^ space ^^ (exp r))
+ | E_cons(l,r) -> doc_op (group (colon^^colon)) (exp l) (exp r)
+ | E_if(c,t,E_aux(E_block [], _)) ->
+ parens (string "if" ^^ space ^^ string "to_bool" ^^ parens (exp c) ^/^
+ string "then" ^^ space ^^ (exp t))
+ | E_if(c,t,e) ->
+ parens (
+ string "if" ^^ space ^^ string "to_bool" ^^ parens (exp c) ^/^
+ string "then" ^^ space ^^ group (exp t) ^/^
+ string "else" ^^ space ^^ group (exp e))
+ | E_for(id,exp1,exp2,exp3,(Ord_aux(order,_)),exp4) ->
+ let var= doc_id_ocaml id in
+ let (compare,next) = if order = Ord_inc then string "<=",string "+" else string ">=",string "-" in
+ let by = exp exp3 in
+ let stop = exp exp2 in
+ (*takes over two names but doesn't require building a closure*)
+ parens
+ (separate space [(string "let (__stop,__by) = ") ^^ (parens (doc_op comma stop by));
+ string "in" ^/^ empty;
+ string "let rec foreach";
+ var;
+ equals;
+ string "if";
+ parens (doc_op compare var (string "__stop") );
+ string "then";
+ parens (exp exp4 ^^ space ^^ semi ^^ (string "foreach") ^^
+ parens (doc_op next var (string "__by")));
+ string "in";
+ string "foreach";
+ exp exp1])
+ (*Requires fewer introduced names but introduces a closure*)
+ (*let forL = if order = Ord_inc then string "foreach_inc" else string "foreach_dec" in
+ forL ^^ space ^^ (group (exp exp1)) ^^ (group (exp exp2)) ^^ (group (exp full_exp3)) ^/^
+ group ((string "fun") ^^ space ^^ (doc_id id) ^^ space ^^ arrow ^/^ (exp exp4))
+
+ (* this way requires the following OCaml declarations first
+
+ let rec foreach_inc i stop by body =
+ if i <= stop then (body i; foreach_inc (i + by) stop by body) else ()
+
+ let rec foreach_dec i stop by body =
+ if i >= stop then (body i; foreach_dec (i - by) stop by body) else ()
+
+ *)*)
+ | E_let(leb,e) -> doc_op (string "in") (let_exp leb) (exp e)
+ | E_app(f,args) ->
+ let call,ctor = match annot with
+ | Base(_,External (Some n),_,_,_,_) -> string n,false
+ | Base(_,Constructor i,_,_,_,_) -> doc_id_ocaml_ctor i f,true
+ | _ -> doc_id_ocaml f,false in
+ let base_print () = parens (doc_unop call (parens (separate_map comma exp args))) in
+ if not(ctor)
+ then base_print ()
+ else (match args with
+ | [] -> call
+ | [arg] -> (match arg with
+ | E_aux(E_lit (L_aux(L_unit,_)),_) -> call
+ | _ -> base_print())
+ | args -> base_print())
+ | E_vector_access(v,e) ->
+ let call = (match annot with
+ | Base((_,t),_,_,_,_,_) ->
+ (match t.t with
+ | Tid "bit" | Tabbrev(_,{t=Tid "bit"}) -> (string "bit_vector_access")
+ | _ -> (string "vector_access"))
+ | _ -> (string "vector_access")) in
+ parens (call ^^ space ^^ exp v ^^ space ^^ exp e)
+ | E_vector_subrange(v,e1,e2) ->
+ parens ((string "vector_subrange") ^^ space ^^ (exp v) ^^ space ^^ (exp e1) ^^ space ^^ (exp e2))
+ | E_field((E_aux(_,(_,fannot)) as fexp),id) ->
+ (match fannot with
+ | Base((_,{t= Tapp("register",_)}),_,_,_,_,_) |
+ Base((_,{t= Tabbrev(_,{t=Tapp("register",_)})}),_,_,_,_,_)->
+ let field_f = match annot with
+ | Base((_,{t = Tid "bit"}),_,_,_,_,_) |
+ Base((_,{t = Tabbrev(_,{t=Tid "bit"})}),_,_,_,_,_) ->
+ string "get_register_field_bit"
+ | _ -> string "get_register_field_vec" in
+ parens (field_f ^^ space ^^ (exp fexp) ^^ space ^^ string_lit (doc_id id))
+ | _ -> exp fexp ^^ dot ^^ doc_id id)
+ | E_block [] -> string "()"
+ | E_block exps | E_nondet exps ->
+ let exps_doc = separate_map (semi ^^ hardline) exp exps in
+ surround 2 1 (string "begin") exps_doc (string "end")
+ | E_id id ->
+ (match annot with
+ | Base((_, ({t = Tapp("reg",_)} | {t=Tabbrev(_,{t=Tapp("reg",_)})})),_,_,_,_,_) ->
+ string "!" ^^ doc_id_ocaml id
+ | Base((_, ({t = Tapp("register",_)} | {t=Tabbrev(_,{t=Tapp("register",_)})})),_,_,_,_,_) ->
+ if read_registers
+ then string "(read_register " ^^ doc_id_ocaml id ^^ string ")"
+ else doc_id_ocaml id
+ | Base(_,(Constructor i |Enum i),_,_,_,_) -> doc_id_ocaml_ctor i id
+ | Base((_,t),Alias alias_info,_,_,_,_) ->
+ (match alias_info with
+ | Alias_field(reg,field) ->
+ let field_f = match t.t with
+ | Tid "bit" | Tabbrev(_,{t=Tid "bit"}) -> string "get_register_field_bit"
+ | _ -> string "get_register_field_vec" in
+ parens (separate space [field_f; string (String.uncapitalize reg); string_lit (string field)])
+ | Alias_extract(reg,start,stop) ->
+ if start = stop
+ then parens (separate space [string "bit_vector_access";string (String.uncapitalize reg);doc_int start])
+ else parens
+ (separate space [string "vector_subrange"; string (String.uncapitalize reg); doc_int start; doc_int stop])
+ | Alias_pair(reg1,reg2) ->
+ parens (separate space [string "vector_concat";
+ string (String.uncapitalize reg1);
+ string (String.uncapitalize reg2)]))
+ | _ -> doc_id_ocaml id)
+ | E_lit lit -> doc_lit_ocaml false lit
+ | E_cast(typ,e) ->
+ (match annot with
+ | Base(_,External _,_,_,_,_) ->
+ if read_registers
+ then parens (string "read_register" ^^ space ^^ exp e)
+ else exp e
+ | _ ->
+ let (Typ_aux (t,_)) = typ in
+ (match t with
+ | Typ_app (Id_aux (Id "vector",_), [Typ_arg_aux (Typ_arg_nexp(Nexp_aux (Nexp_constant i,_)),_);_;_;_]) ->
+ parens ((concat [string "set_start";space;string (string_of_int i)]) ^//^
+ exp e)
+ | Typ_var (Kid_aux (Var "length",_)) ->
+ parens ((string "set_start_to_length") ^//^ exp e)
+ | _ ->
+ parens (doc_op colon (group (exp e)) (doc_typ_ocaml typ)))
+
+
+)
+ | E_tuple exps ->
+ parens (separate_map comma exp exps)
+ | E_record(FES_aux(FES_Fexps(fexps,_),_)) ->
+ braces (separate_map semi_sp doc_fexp fexps)
+ | E_record_update(e,(FES_aux(FES_Fexps(fexps,_),_))) ->
+ braces (doc_op (string "with") (exp e) (separate_map semi_sp doc_fexp fexps))
+ | E_vector exps ->
+ (match annot with
+ | Base((_,t),_,_,_,_,_) ->
+ match t.t with
+ | Tapp("vector", [TA_nexp start; _; TA_ord order; _])
+ | Tabbrev(_,{t= Tapp("vector", [TA_nexp start; _; TA_ord order; _])}) ->
+ let call = if is_bit_vector t then (string "Vvector") else (string "VvectorR") in
+ let dir,dir_out = match order.order with
+ | Oinc -> true,"true"
+ | _ -> false, "false" in
+ let start = match start.nexp with
+ | Nconst i -> string_of_big_int i
+ | N2n(_,Some i) -> string_of_big_int i
+ | _ -> if dir then "0" else string_of_int (List.length exps) in
+ parens (separate space [call; parens (separate comma_sp [squarebars (separate_map semi exp exps);
+ string start;
+ string dir_out])]))
+ | E_vector_indexed (iexps, (Def_val_aux (default,_))) ->
+ (match annot with
+ | Base((_,t),_,_,_,_,_) ->
+ match t.t with
+ | Tapp("vector", [TA_nexp start; TA_nexp len; TA_ord order; _])
+ | Tabbrev(_,{t= Tapp("vector", [TA_nexp start; TA_nexp len; TA_ord order; _])})
+ | Tapp("reg", [TA_typ {t =Tapp("vector", [TA_nexp start; TA_nexp len; TA_ord order; _])}]) ->
+ let call = if is_bit_vector t then (string "make_indexed_bitv") else (string "make_indexed_v") in
+ let dir,dir_out = match order.order with
+ | Oinc -> true,"true"
+ | _ -> false, "false" in
+ let start = match start.nexp with
+ | Nconst i | N2n(_,Some i)-> string_of_big_int i
+ | N2n({nexp=Nconst i},_) -> string_of_int (Util.power 2 (int_of_big_int i))
+ | _ -> if dir then "0" else string_of_int (List.length iexps) in
+ let size = match len.nexp with
+ | Nconst i | N2n(_,Some i)-> string_of_big_int i
+ | N2n({nexp=Nconst i},_) -> string_of_int (Util.power 2 (int_of_big_int i))
+ in
+ let default_string =
+ (match default with
+ | Def_val_empty -> string "None"
+ | Def_val_dec e -> parens (string "Some " ^^ (exp e))) in
+ let iexp (i,e) = parens (separate_map comma_sp (fun x -> x) [(doc_int i); (exp e)]) in
+ parens (separate space [call;
+ (brackets (separate_map semi iexp iexps));
+ default_string;
+ string start;
+ string size;
+ string dir_out]))
+ | E_vector_update(v,e1,e2) ->
+ (*Has never happened to date*)
+ brackets (doc_op (string "with") (exp v) (doc_op equals (exp e1) (exp e2)))
+ | E_vector_update_subrange(v,e1,e2,e3) ->
+ (*Has never happened to date*)
+ brackets (
+ doc_op (string "with") (exp v)
+ (doc_op equals (exp e1 ^^ colon ^^ exp e2) (exp e3)))
+ | E_list exps ->
+ brackets (separate_map semi exp exps)
+ | E_case(e,pexps) ->
+ let opening = separate space [string "("; string "match"; top_exp false e; string "with"] in
+ let cases = separate_map (break 1) doc_case pexps in
+ surround 2 1 opening cases rparen
+ | E_exit e ->
+ separate space [string "exit"; exp e;]
+ | E_app_infix (e1,id,e2) ->
+ let call =
+ match annot with
+ | Base((_,t),External(Some name),_,_,_,_) -> string name
+ | _ -> doc_id_ocaml id in
+ parens (separate space [call; parens (separate_map comma exp [e1;e2])])
+ | E_internal_let(lexp, eq_exp, in_exp) ->
+ separate space [string "let";
+ doc_lexp_ocaml true lexp; (*Rewriter/typecheck should ensure this is only cast or id*)
+ equals;
+ string "ref";
+ exp eq_exp;
+ string "in";
+ exp in_exp]
+
+ | E_internal_plet (pat,e1,e2) ->
+ (separate space [(exp e1); string ">>= fun"; doc_pat_ocaml pat;arrow]) ^/^
+ exp e2
+
+ | E_internal_return (e1) ->
+ separate space [string "return"; exp e1;]
+ and let_exp (LB_aux(lb,_)) = match lb with
+ | LB_val_explicit(ts,pat,e) ->
+ prefix 2 1
+ (separate space [string "let"; doc_pat_ocaml pat; equals])
+ (top_exp false e)
+ | LB_val_implicit(pat,e) ->
+ prefix 2 1
+ (separate space [string "let"; doc_pat_ocaml pat; equals])
+ (top_exp false e)
+
+ and doc_fexp (FE_aux(FE_Fexp(id,e),_)) = doc_op equals (doc_id_ocaml id) (top_exp false e)
+
+ and doc_case (Pat_aux(Pat_exp(pat,e),_)) =
+ doc_op arrow (separate space [pipe; doc_pat_ocaml pat]) (group (top_exp false e))
+
+ and doc_lexp_ocaml top_call ((LEXP_aux(lexp,(l,annot))) as le) =
+ let exp = top_exp false in
+ match lexp with
+ | LEXP_vector(v,e) -> doc_lexp_array_ocaml le
+ | LEXP_vector_range(v,e1,e2) ->
+ parens ((string "vector_subrange") ^^ space ^^ (doc_lexp_ocaml false v) ^^ space ^^ (exp e1) ^^ space ^^ (exp e2))
+ | LEXP_field(v,id) -> (doc_lexp_ocaml false v) ^^ dot ^^ doc_id_ocaml id
+ | LEXP_id id | LEXP_cast(_,id) ->
+ let name = doc_id_ocaml id in
+ match annot,top_call with
+ | Base((_,{t=Tapp("reg",_)}),Emp_set,_,_,_,_),false | Base((_,{t=Tabbrev(_,{t=Tapp("reg",_)})}),Emp_set,_,_,_,_),false ->
+ string "!" ^^ name
+ | _ -> name
+
+ and doc_lexp_array_ocaml ((LEXP_aux(lexp,(l,annot))) as le) = match lexp with
+ | LEXP_vector(v,e) ->
+ (match annot with
+ | Base((_,t),_,_,_,_,_) ->
+ let t_act = match t.t with | Tapp("reg",[TA_typ t]) | Tabbrev(_,{t=Tapp("reg",[TA_typ t])}) -> t | _ -> t in
+ (match t_act.t with
+ | Tid "bit" | Tabbrev(_,{t=Tid "bit"}) ->
+ parens ((string "get_barray") ^^ space ^^ doc_lexp_ocaml false v) ^^ dot ^^ parens ((string "int_of_big_int") ^^ space ^^ (top_exp false e))
+ | _ -> parens ((string "get_varray") ^^ space ^^ doc_lexp_ocaml false v) ^^ dot ^^ parens ((string "int_of_big_int") ^^ space ^^ (top_exp false e)))
+ | _ ->
+ parens ((string "get_varray") ^^ space ^^ doc_lexp_ocaml false v) ^^ dot ^^ parens ((string "int_of_big_int") ^^ space ^^ (top_exp false e)))
+ | _ -> empty
+
+ and doc_lexp_rwrite ((LEXP_aux(lexp,(l,annot))) as le) e_new_v =
+ let exp = top_exp false in
+ let (is_bit,is_bitv) = match e_new_v with
+ | E_aux(_,(_,Base((_,t),_,_,_,_,_))) ->
+ (match t.t with
+ | Tapp("vector", [_;_;_;(TA_typ ({t=Tid "bit"} | {t=Tabbrev(_,{t=Tid "bit"})}))]) |
+ Tabbrev(_,{t=Tapp("vector",[_;_;_;TA_typ ({t=Tid "bit"} | {t=Tabbrev(_,{t=Tid "bit"})})])}) |
+ Tapp("reg", [TA_typ {t= Tapp("vector", [_;_;_;(TA_typ ({t=Tid "bit"} | {t=Tabbrev(_,{t=Tid "bit"})}))])}])
+ ->
+ (false,true)
+ | Tid "bit" | Tabbrev(_,{t=Tid "bit"}) | Tapp("reg",[TA_typ ({t=Tid "bit"} | {t=Tabbrev(_,{t=Tid "bit"})})])
+ -> (true,false)
+ | _ -> (false,false))
+ | _ -> (false,false) in
+ match lexp with
+ | LEXP_vector(v,e) ->
+ doc_op (string "<-")
+ (group (parens ((string (if is_bit then "get_barray" else "get_varray")) ^^ space ^^ doc_lexp_ocaml false v)) ^^
+ dot ^^ parens ((string "int_of_big_int") ^^ space ^^ (exp e)))
+ (exp e_new_v)
+ | LEXP_vector_range(v,e1,e2) ->
+ parens ((string (if is_bitv then "set_vector_subrange_bit" else "set_vector_subrange_vec")) ^^ space ^^
+ doc_lexp_ocaml false v ^^ space ^^ exp e1 ^^ space ^^ exp e2 ^^ space ^^ exp e_new_v)
+ | LEXP_field(v,id) ->
+ parens ((string (if is_bit then "set_register_field_bit" else "set_register_field_v")) ^^ space ^^
+ doc_lexp_ocaml false v ^^ space ^^string_lit (doc_id id) ^^ space ^^ exp e_new_v)
+ | LEXP_id id | LEXP_cast (_,id) ->
+ (match annot with
+ | Base(_,Alias alias_info,_,_,_,_) ->
+ (match alias_info with
+ | Alias_field(reg,field) ->
+ parens ((if is_bit then string "set_register_field_bit" else string "set_register_field_v") ^^ space ^^
+ string (String.uncapitalize reg) ^^ space ^^string_lit (string field) ^^ space ^^ exp e_new_v)
+ | Alias_extract(reg,start,stop) ->
+ if start = stop
+ then
+ doc_op (string "<-")
+ (group (parens ((string (if is_bit then "get_barray" else "get_varray")) ^^ space ^^ string reg)) ^^
+ dot ^^ parens ((string "int_of_big_int") ^^ space ^^ (doc_int start)))
+ (exp e_new_v)
+ else
+ parens ((string (if is_bitv then "set_vector_subrange_bit" else "set_vector_subrange_vec")) ^^ space ^^
+ string reg ^^ space ^^ doc_int start ^^ space ^^ doc_int stop ^^ space ^^ exp e_new_v)
+ | Alias_pair(reg1,reg2) ->
+ parens ((string "set_two_regs") ^^ space ^^ string reg1 ^^ space ^^ string reg2 ^^ space ^^ exp e_new_v))
+ | _ ->
+ parens (separate space [string "set_register"; doc_id_ocaml id; exp e_new_v]))
+
+ and doc_lexp_fcall ((LEXP_aux(lexp,(l,annot))) as le) e_new_v = match lexp with
+ | LEXP_memory(id,args) -> doc_id_ocaml id ^^ parens (separate_map comma (top_exp false) (args@[e_new_v]))
+
+ (* expose doc_exp and doc_let *)
+ in top_exp false, let_exp
+
+(*TODO Upcase and downcase type and constructors as needed*)
+let doc_type_union_ocaml n (Tu_aux(typ_u,_)) = match typ_u with
+ | Tu_ty_id(typ,id) -> separate space [pipe; doc_id_ocaml_ctor n id; string "of"; doc_typ_ocaml typ;]
+ | Tu_id id -> separate space [pipe; doc_id_ocaml_ctor n id]
+
+let rec doc_range_ocaml (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_ocaml (TD_aux(td,_)) = match td with
+ | TD_abbrev(id,nm,typschm) ->
+ doc_op equals (concat [string "type"; space; doc_id_ocaml_type id;]) (doc_typscm_ocaml typschm)
+ | TD_record(id,nm,typq,fs,_) ->
+ let f_pp (typ,id) = concat [doc_id_ocaml_type id; space; colon; doc_typ_ocaml typ; semi] in
+ let fs_doc = group (separate_map (break 1) f_pp fs) in
+ doc_op equals
+ (concat [string "type"; space; doc_id_ocaml_type id;]) (doc_typquant_ocaml typq (braces fs_doc))
+ | TD_variant(id,nm,typq,ar,_) ->
+ let n = List.length ar in
+ let ar_doc = group (separate_map (break 1) (doc_type_union_ocaml n) ar) in
+ doc_op equals
+ (concat [string "type"; space; doc_id_ocaml_type id;])
+ (if n > 246
+ then brackets (space ^^(doc_typquant_ocaml typq ar_doc))
+ else (doc_typquant_ocaml typq ar_doc))
+ | TD_enum(id,nm,enums,_) ->
+ let n = List.length enums in
+ let enums_doc = group (separate_map (break 1 ^^ pipe) (doc_id_ocaml_ctor n) enums) in
+ doc_op equals
+ (concat [string "type"; space; doc_id_ocaml_type id;])
+ (enums_doc)
+ | TD_register(id,n1,n2,rs) ->
+ let doc_rid (r,id) = parens (separate comma_sp [string_lit (doc_id id); doc_range_ocaml r;]) in
+ let doc_rids = group (separate_map (semi ^^ (break 1)) doc_rid rs) in
+ match n1,n2 with
+ | Nexp_aux(Nexp_constant i1,_),Nexp_aux(Nexp_constant i2,_) ->
+ let dir = i1 < i2 in
+ let size = if dir then i2-i1 +1 else i1-i2+1 in
+ doc_op equals
+ ((string "let") ^^ space ^^ doc_id_ocaml id ^^ space ^^ (string "init_val"))
+ (separate space [string "Vregister";
+ (parens (separate comma_sp
+ [parens (separate space
+ [string "match init_val with";
+ pipe;
+ string "None";
+ arrow;
+ string "ref";
+ string "(Array.make";
+ doc_int size;
+ string "Vzero)";
+ pipe;
+ string "Some init_val";
+ arrow;
+ string "ref init_val";]);
+ doc_nexp n1;
+ string (if dir then "true" else "false");
+ brackets doc_rids]))])
+
+let doc_kdef_ocaml (KD_aux(kd,_)) = match kd with
+ | KD_abbrev(_,id,nm,typschm) ->
+ doc_op equals (concat [string "type"; space; doc_id_ocaml_type id;]) (doc_typscm_ocaml typschm)
+ | KD_record(_,id,nm,typq,fs,_) ->
+ let f_pp (typ,id) = concat [doc_id_ocaml_type id; space; colon; doc_typ_ocaml typ; semi] in
+ let fs_doc = group (separate_map (break 1) f_pp fs) in
+ doc_op equals
+ (concat [string "type"; space; doc_id_ocaml_type id;]) (doc_typquant_ocaml typq (braces fs_doc))
+ | KD_variant(_,id,nm,typq,ar,_) ->
+ let n = List.length ar in
+ let ar_doc = group (separate_map (break 1) (doc_type_union_ocaml n) ar) in
+ doc_op equals
+ (concat [string "type"; space; doc_id_ocaml_type id;])
+ (if n > 246
+ then brackets (space ^^(doc_typquant_ocaml typq ar_doc))
+ else (doc_typquant_ocaml typq ar_doc))
+ | KD_enum(_,id,nm,enums,_) ->
+ let n = List.length enums in
+ let enums_doc = group (separate_map (break 1 ^^ pipe) (doc_id_ocaml_ctor n) enums) in
+ doc_op equals
+ (concat [string "type"; space; doc_id_ocaml_type id;])
+ (enums_doc)
+ | KD_register(_,id,n1,n2,rs) ->
+ let doc_rid (r,id) = parens (separate comma_sp [string_lit (doc_id id); doc_range_ocaml r;]) in
+ let doc_rids = group (separate_map (semi ^^ (break 1)) doc_rid rs) in
+ match n1,n2 with
+ | Nexp_aux(Nexp_constant i1,_),Nexp_aux(Nexp_constant i2,_) ->
+ let dir = i1 < i2 in
+ let size = if dir then i2-i1 +1 else i1-i2 in
+ doc_op equals
+ ((string "let") ^^ space ^^ doc_id_ocaml id ^^ space ^^ (string "init_val"))
+ (separate space [string "Vregister";
+ (parens (separate comma_sp
+ [parens (separate space
+ [string "match init_val with";
+ pipe;
+ string "None";
+ arrow;
+ string "ref";
+ string "(Array.make";
+ doc_int size;
+ string "Vzero)";
+ pipe;
+ string "Some init_val";
+ arrow;
+ string "ref init_val";]);
+ doc_nexp n1;
+ string (if dir then "true" else "false");
+ brackets doc_rids]))])
+
+let doc_rec_ocaml (Rec_aux(r,_)) = match r with
+ | Rec_nonrec -> empty
+ | Rec_rec -> string "rec" ^^ space
+
+let doc_tannot_opt_ocaml (Typ_annot_opt_aux(t,_)) = match t with
+ | Typ_annot_opt_some(tq,typ) -> doc_typquant_ocaml tq (doc_typ_ocaml typ)
+
+let doc_funcl_ocaml (FCL_aux(FCL_Funcl(id,pat,exp),_)) =
+ group (doc_op arrow (doc_pat_ocaml pat) (doc_exp_ocaml exp))
+
+let get_id = function
+ | [] -> failwith "FD_function with empty list"
+ | (FCL_aux (FCL_Funcl (id,_,_),_))::_ -> id
+
+let doc_fundef_ocaml (FD_aux(FD_function(r, typa, efa, fcls),_)) =
+ match fcls with
+ | [] -> failwith "FD_function with empty function list"
+ | [FCL_aux (FCL_Funcl(id,pat,exp),_)] ->
+ (separate space [(string "let"); (doc_rec_ocaml r); (doc_id_ocaml id); (doc_pat_ocaml pat); equals]) ^^ hardline ^^ (doc_exp_ocaml exp)
+ | _ ->
+ let id = get_id fcls in
+ let sep = hardline ^^ pipe ^^ space in
+ let clauses = separate_map sep doc_funcl_ocaml fcls in
+ separate space [string "let";
+ doc_rec_ocaml r;
+ doc_id_ocaml id;
+ equals;
+ (string "function");
+ (hardline^^pipe);
+ clauses]
+
+let doc_dec_ocaml (DEC_aux (reg,(l,annot))) =
+ match reg with
+ | DEC_reg(typ,id) ->
+ (match annot with
+ | Base((_,t),_,_,_,_,_) ->
+ (match t.t with
+ | Tapp("register", [TA_typ {t= Tapp("vector", [TA_nexp start; TA_nexp size; TA_ord order; TA_typ itemt])}])
+ | Tapp("register", [TA_typ {t= Tabbrev(_,{t=Tapp("vector", [TA_nexp start; TA_nexp size; TA_ord order; TA_typ itemt])})}]) ->
+ (match itemt.t,start.nexp,size.nexp with
+ | Tid "bit", Nconst start, Nconst size ->
+ let o = if order.order = Oinc then string "true" else string "false" in
+ separate space [string "let";
+ doc_id_ocaml id;
+ equals;
+ string "Vregister";
+ parens (separate comma [separate space [string "ref";
+ parens (separate space
+ [string "Array.make";
+ doc_int (int_of_big_int size);
+ string "Vzero";])];
+ doc_int (int_of_big_int start);
+ o;
+ brackets empty])]
+ | _ -> empty)
+ | Tapp("register", [TA_typ {t=Tid idt}]) |
+ Tabbrev( {t= Tid idt}, _) ->
+ separate space [string "let";
+ doc_id_ocaml id;
+ equals;
+ doc_id_ocaml (Id_aux (Id idt, Unknown));
+ string "None"]
+ |_-> failwith "type was not handled in register declaration")
+ | _ -> failwith "annot was not Base")
+ | DEC_alias(id,alspec) -> empty (*
+ doc_op equals (string "register alias" ^^ space ^^ doc_id id) (doc_alias alspec) *)
+ | DEC_typ_alias(typ,id,alspec) -> empty (*
+ doc_op equals (string "register alias" ^^ space ^^ doc_atomic_typ typ) (doc_alias alspec) *)
+
+let doc_def_ocaml def = group (match def with
+ | DEF_default df -> empty
+ | DEF_spec v_spec -> empty (*unless we want to have a separate pass to create mli files*)
+ | DEF_type t_def -> doc_typdef_ocaml t_def
+ | DEF_fundef f_def -> doc_fundef_ocaml f_def
+ | DEF_val lbind -> doc_let_ocaml lbind
+ | DEF_reg_dec dec -> doc_dec_ocaml dec
+ | DEF_scattered sdef -> empty (*shoulnd't still be here*)
+ | DEF_kind _ -> failwith "unhandled DEF_kind"
+ | DEF_comm _ -> failwith "unhandled DEF_comm"
+ ) ^^ hardline
+
+let doc_defs_ocaml (Defs(defs)) =
+ separate_map hardline doc_def_ocaml defs
+let pp_defs_ocaml f d top_line opens =
+ print f (string "(*" ^^ (string top_line) ^^ string "*)" ^/^
+ (separate_map hardline (fun lib -> (string "open") ^^ space ^^ (string lib)) opens) ^/^
+ (doc_defs_ocaml d))
+
diff --git a/src/pretty_print_sail.ml b/src/pretty_print_sail.ml
new file mode 100644
index 00000000..22cb707b
--- /dev/null
+++ b/src/pretty_print_sail.ml
@@ -0,0 +1,564 @@
+(**************************************************************************)
+(* Sail *)
+(* *)
+(* Copyright (c) 2013-2017 *)
+(* Kathyrn Gray *)
+(* Shaked Flur *)
+(* Stephen Kell *)
+(* Gabriel Kerneis *)
+(* Robert Norton-Wright *)
+(* Christopher Pulte *)
+(* Peter Sewell *)
+(* *)
+(* 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_internal
+open Ast
+open PPrint
+open Pretty_print_common
+
+(****************************************************************************
+ * PPrint-based source-to-source pretty printer
+****************************************************************************)
+
+
+
+
+let doc_bkind (BK_aux(k,_)) =
+ string (match k with
+ | BK_type -> "Type"
+ | BK_nat -> "Nat"
+ | BK_order -> "Order"
+ | BK_effect -> "Effect")
+
+let doc_kind (K_aux(K_kind(klst),_)) =
+ separate_map (spaces arrow) doc_bkind klst
+
+let doc_nexp_constraint (NC_aux(nc,_)) = match nc with
+ | NC_fixed(n1,n2) -> doc_op equals (doc_nexp n1) (doc_nexp n2)
+ | NC_bounded_ge(n1,n2) -> doc_op (string ">=") (doc_nexp n1) (doc_nexp n2)
+ | NC_bounded_le(n1,n2) -> doc_op (string "<=") (doc_nexp n1) (doc_nexp n2)
+ | NC_nat_set_bounded(v,bounds) ->
+ doc_op (string "IN") (doc_var v)
+ (braces (separate_map comma_sp doc_int bounds))
+
+let doc_qi (QI_aux(qi,_)) = match qi with
+ | QI_const n_const -> doc_nexp_constraint n_const
+ | QI_id(KOpt_aux(ki,_)) ->
+ match ki with
+ | KOpt_none v -> doc_var v
+ | KOpt_kind(k,v) -> separate space [doc_kind k; doc_var v]
+
+(* typ_doc is the doc for the type being quantified *)
+let doc_typquant (TypQ_aux(tq,_)) typ_doc = match tq with
+ | TypQ_no_forall -> typ_doc
+ | TypQ_tq [] -> failwith "TypQ_tq with empty list"
+ | TypQ_tq qlist ->
+ (* include trailing break because the caller doesn't know if tq is empty *)
+ doc_op dot
+ (separate space [string "forall"; separate_map comma_sp doc_qi qlist])
+ typ_doc
+
+let doc_typscm (TypSchm_aux(TypSchm_ts(tq,t),_)) =
+ (doc_typquant tq (doc_typ t))
+
+let doc_typscm_atomic (TypSchm_aux(TypSchm_ts(tq,t),_)) =
+ (doc_typquant tq (doc_atomic_typ t))
+
+let doc_lit (L_aux(l,_)) =
+ utf8string (match l with
+ | L_unit -> "()"
+ | L_zero -> "bitzero"
+ | L_one -> "bitone"
+ | L_true -> "true"
+ | L_false -> "false"
+ | L_num i -> string_of_int i
+ | L_hex n -> "0x" ^ n
+ | L_bin n -> "0b" ^ n
+ | L_undef -> "undefined"
+ | L_string s -> "\"" ^ s ^ "\"")
+
+let doc_pat, doc_atomic_pat =
+ let rec pat pa = pat_colons pa
+ and pat_colons ((P_aux(p,l)) as pa) = match p with
+ (* XXX add leading indentation if not flat - we need to define our own
+ * combinator for that *)
+ | P_vector_concat pats -> separate_map (space ^^ colon ^^ break 1) atomic_pat pats
+ | _ -> app_pat pa
+ and app_pat ((P_aux(p,l)) as pa) = match p with
+ | P_app(id, ((_ :: _) as pats)) -> doc_unop (doc_id id) (parens (separate_map comma_sp atomic_pat pats))
+ | _ -> atomic_pat pa
+ and atomic_pat ((P_aux(p,(l,annot))) as pa) = match p with
+ | P_lit lit -> doc_lit lit
+ | P_wild -> underscore
+ | P_id id -> doc_id id
+ | P_as(p,id) -> parens (separate space [pat p; string "as"; doc_id id])
+ | P_typ(typ,p) -> separate space [parens (doc_typ typ); atomic_pat p]
+ | P_app(id,[]) -> doc_id id
+ | P_record(fpats,_) -> braces (separate_map semi_sp fpat fpats)
+ | P_vector pats -> brackets (separate_map comma_sp atomic_pat pats)
+ | P_vector_indexed ipats -> brackets (separate_map comma_sp npat ipats)
+ | P_tup pats -> parens (separate_map comma_sp atomic_pat pats)
+ | P_list pats -> squarebarbars (separate_map semi_sp atomic_pat pats)
+ | P_app(_, _ :: _) | P_vector_concat _ ->
+ group (parens (pat pa))
+ and fpat (FP_aux(FP_Fpat(id,fpat),_)) = doc_op equals (doc_id id) (pat fpat)
+ and npat (i,p) = doc_op equals (doc_int i) (pat p)
+
+ (* expose doc_pat and doc_atomic_pat *)
+ in pat, atomic_pat
+
+let doc_exp, doc_let =
+ let rec exp e = group (or_exp e)
+ and or_exp ((E_aux(e,_)) as expr) = match e with
+ | E_app_infix(l,(Id_aux(Id ("|" | "||"),_) as op),r) ->
+ doc_op (doc_id op) (and_exp l) (or_exp r)
+ | _ -> and_exp expr
+ and and_exp ((E_aux(e,_)) as expr) = match e with
+ | E_app_infix(l,(Id_aux(Id ("&" | "&&"),_) as op),r) ->
+ doc_op (doc_id op) (eq_exp l) (and_exp r)
+ | _ -> eq_exp expr
+ and eq_exp ((E_aux(e,_)) as expr) = match e with
+ | E_app_infix(l,(Id_aux(Id (
+ (* XXX this is not very consistent - is the parser bogus here? *)
+ "=" | "==" | "!="
+ | ">=" | ">=_s" | ">=_u" | ">" | ">_s" | ">_u"
+ | "<=" | "<=_s" | "<" | "<_s" | "<_si" | "<_u"
+ ),_) as op),r) ->
+ doc_op (doc_id op) (eq_exp l) (at_exp r)
+ (* XXX assignment should not have the same precedence as equal etc. *)
+ | E_assign(le,exp) -> doc_op coloneq (doc_lexp le) (at_exp exp)
+ | _ -> at_exp expr
+ and at_exp ((E_aux(e,_)) as expr) = match e with
+ | E_app_infix(l,(Id_aux(Id ("@" | "^^" | "^" | "~^"),_) as op),r) ->
+ doc_op (doc_id op) (cons_exp l) (at_exp r)
+ | _ -> cons_exp expr
+ and cons_exp ((E_aux(e,_)) as expr) = match e with
+ | E_vector_append(l,r) ->
+ doc_op colon (shift_exp l) (cons_exp r)
+ | E_cons(l,r) ->
+ doc_op colon (shift_exp l) (cons_exp r)
+ | _ -> shift_exp expr
+ and shift_exp ((E_aux(e,_)) as expr) = match e with
+ | E_app_infix(l,(Id_aux(Id (">>" | ">>>" | "<<" | "<<<"),_) as op),r) ->
+ doc_op (doc_id op) (shift_exp l) (plus_exp r)
+ | _ -> plus_exp expr
+ and plus_exp ((E_aux(e,_)) as expr) = match e with
+ | E_app_infix(l,(Id_aux(Id ("+" | "-" | "+_s" | "-_s"),_) as op),r) ->
+ doc_op (doc_id op) (plus_exp l) (star_exp r)
+ | _ -> star_exp expr
+ and star_exp ((E_aux(e,_)) as expr) = match e with
+ | E_app_infix(l,(Id_aux(Id (
+ "*" | "/"
+ | "div" | "quot" | "quot_s" | "rem" | "mod"
+ | "*_s" | "*_si" | "*_u" | "*_ui"),_) as op),r) ->
+ doc_op (doc_id op) (star_exp l) (starstar_exp r)
+ | _ -> starstar_exp expr
+ and starstar_exp ((E_aux(e,_)) as expr) = match e with
+ | E_app_infix(l,(Id_aux(Id "**",_) as op),r) ->
+ doc_op (doc_id op) (starstar_exp l) (app_exp r)
+ | E_if _ | E_for _ | E_let _ -> right_atomic_exp expr
+ | _ -> app_exp expr
+ and right_atomic_exp ((E_aux(e,_)) as expr) = match e with
+ (* Special case: omit "else ()" when the else branch is empty. *)
+ | E_if(c,t,E_aux(E_block [], _)) ->
+ string "if" ^^ space ^^ group (exp c) ^/^
+ string "then" ^^ space ^^ group (exp t)
+ | E_if(c,t,e) ->
+ string "if" ^^ space ^^ group (exp c) ^/^
+ string "then" ^^ space ^^ group (exp t) ^/^
+ string "else" ^^ space ^^ group (exp e)
+ | E_for(id,exp1,exp2,exp3,order,exp4) ->
+ string "foreach" ^^ space ^^
+ group (parens (
+ separate (break 1) [
+ doc_id id;
+ string "from " ^^ atomic_exp exp1;
+ string "to " ^^ atomic_exp exp2;
+ string "by " ^^ atomic_exp exp3;
+ string "in " ^^ doc_ord order
+ ]
+ )) ^/^
+ exp exp4
+ | E_let(leb,e) -> doc_op (string "in") (let_exp leb) (exp e)
+ | _ -> group (parens (exp expr))
+ and app_exp ((E_aux(e,_)) as expr) = match e with
+ | E_app(f,args) ->
+ (doc_id f) ^^ (parens (separate_map comma exp args))
+ | _ -> vaccess_exp expr
+ and vaccess_exp ((E_aux(e,_)) as expr) = match e with
+ | E_vector_access(v,e) ->
+ atomic_exp v ^^ brackets (exp e)
+ | E_vector_subrange(v,e1,e2) ->
+ atomic_exp v ^^ brackets (doc_op dotdot (exp e1) (exp e2))
+ | _ -> field_exp expr
+ and field_exp ((E_aux(e,_)) as expr) = match e with
+ | E_field(fexp,id) -> atomic_exp fexp ^^ dot ^^ doc_id id
+ | _ -> atomic_exp expr
+ and atomic_exp ((E_aux(e,_)) as expr) = match e with
+ (* Special case: an empty block is equivalent to unit, but { } would
+ * be parsed as a struct. *)
+ | E_block [] -> string "()"
+ | E_block exps ->
+ let exps_doc = separate_map (semi ^^ hardline) exp exps in
+ surround 2 1 lbrace exps_doc rbrace
+ | E_nondet exps ->
+ let exps_doc = separate_map (semi ^^ hardline) exp exps in
+ string "nondet" ^^ space ^^ (surround 2 1 lbrace exps_doc rbrace)
+ | E_comment s -> string ("(*" ^ s ^ "*) ()")
+ | E_comment_struc e -> string "(*" ^^ exp e ^^ string "*) ()"
+ | E_id id -> doc_id id
+ | E_lit lit -> doc_lit lit
+ | E_cast(typ,e) -> prefix 2 1 (parens (doc_typ typ)) (group (atomic_exp e))
+ | E_internal_cast((_,NoTyp),e) -> atomic_exp e
+ | E_internal_cast((_,Base((_,t),_,_,_,_,bindings)), (E_aux(_,(_,eannot)) as e)) ->
+ (match t.t,eannot with
+ (* XXX I don't understand why we can hide the internal cast here
+ AAA Because an internal cast between vectors is only generated to reset the base access;
+ the type checker generates far more than are needed and they're pruned off here, after constraint resolution *)
+ | Tapp("vector",[TA_nexp n1;_;_;_]),Base((_,{t=Tapp("vector",[TA_nexp n2;_;_;_])}),_,_,_,_,_)
+ when nexp_eq n1 n2 -> atomic_exp e
+ | _ -> prefix 2 1 (parens (doc_typ (t_to_typ t))) (group (atomic_exp e)))
+ | E_tuple exps ->
+ parens (separate_map comma exp exps)
+ | E_record(FES_aux(FES_Fexps(fexps,_),_)) ->
+ (* XXX E_record is not handled by parser currently
+ AAA The parser can't handle E_record due to ambiguity with blocks; initial_check looks for blocks that are all field assignments and converts *)
+ braces (separate_map semi_sp doc_fexp fexps)
+ | E_record_update(e,(FES_aux(FES_Fexps(fexps,_),_))) ->
+ braces (doc_op (string "with") (exp e) (separate_map semi_sp doc_fexp fexps))
+ | E_vector exps ->
+ let default_print _ = brackets (separate_map comma exp exps) in
+ (match exps with
+ | [] -> default_print ()
+ | E_aux(e,_)::es ->
+ (match e with
+ | E_lit (L_aux(L_one, _)) | E_lit (L_aux(L_zero, _)) ->
+ utf8string
+ ("0b" ^
+ (List.fold_right (fun (E_aux( e,_)) rst ->
+ (match e with
+ | E_lit(L_aux(l, _)) ->
+ ((match l with | L_one -> "1" | L_zero -> "0" | L_undef -> "u" | _ -> assert false) ^ rst)
+ | _ -> assert false)) exps ""))
+ | _ -> default_print ()))
+ | E_vector_indexed (iexps, (Def_val_aux (default,_))) ->
+ let default_string =
+ (match default with
+ | Def_val_empty -> string ""
+ | Def_val_dec e -> concat [semi; space; string "default"; equals; (exp e)]) in
+ let iexp (i,e) = doc_op equals (doc_int i) (exp e) in
+ brackets (concat [(separate_map comma iexp iexps); default_string])
+ | E_vector_update(v,e1,e2) ->
+ brackets (doc_op (string "with") (exp v) (doc_op equals (atomic_exp e1) (exp e2)))
+ | E_vector_update_subrange(v,e1,e2,e3) ->
+ brackets (
+ doc_op (string "with") (exp v)
+ (doc_op equals (atomic_exp e1 ^^ colon ^^ atomic_exp e2) (exp e3)))
+ | E_list exps ->
+ squarebarbars (separate_map comma exp exps)
+ | E_case(e,pexps) ->
+ let opening = separate space [string "switch"; exp e; lbrace] in
+ let cases = separate_map (break 1) doc_case pexps in
+ surround 2 1 opening cases rbrace
+ | E_sizeof n ->
+ separate space [string "sizeof"; doc_nexp n]
+ | E_exit e ->
+ separate space [string "exit"; atomic_exp e;]
+ | E_return e ->
+ separate space [string "return"; atomic_exp e;]
+ | E_assert(c,m) ->
+ separate space [string "assert"; parens (separate comma [exp c; exp m])]
+ (* adding parens and loop for lower precedence *)
+ | E_app (_, _)|E_vector_access (_, _)|E_vector_subrange (_, _, _)
+ | E_cons (_, _)|E_field (_, _)|E_assign (_, _)
+ | E_if _ | E_for _ | E_let _
+ | E_vector_append _
+ | E_app_infix (_,
+ (* for every app_infix operator caught at a higher precedence,
+ * we need to wrap around with parens *)
+ (Id_aux(Id("|" | "||"
+ | "&" | "&&"
+ | "=" | "==" | "!="
+ | ">=" | ">=_s" | ">=_u" | ">" | ">_s" | ">_u"
+ | "<=" | "<=_s" | "<" | "<_s" | "<_si" | "<_u"
+ | "@" | "^^" | "^" | "~^"
+ | ">>" | ">>>" | "<<" | "<<<"
+ | "+" | "-" | "+_s" | "-_s"
+ | "*" | "/"
+ | "div" | "quot" | "quot_s" | "rem" | "mod"
+ | "*_s" | "*_si" | "*_u" | "*_ui"
+ | "**"), _))
+ , _) ->
+ group (parens (exp expr))
+ (* XXX default precedence for app_infix? *)
+ | E_app_infix(l,op,r) ->
+ failwith ("unexpected app_infix operator " ^ (pp_format_id op))
+ (* doc_op (doc_id op) (exp l) (exp r) *)
+ | E_comment s -> comment (string s)
+ | E_comment_struc e -> comment (exp e)
+ | E_internal_exp((l, Base((_,t),_,_,_,_,bindings))) -> (*TODO use bindings, and other params*)
+ (match t.t with
+ | Tapp("register",[TA_typ {t=Tapp("vector",[TA_nexp _;TA_nexp r;_;_])}])
+ | Tapp("vector",[TA_nexp _;TA_nexp r;_;_]) ->
+ (match r.nexp with
+ | Nvar v -> utf8string v
+ | Nconst bi -> utf8string (Big_int.string_of_big_int bi)
+ | _ -> raise (Reporting_basic.err_unreachable l
+ ("Internal exp given vector without known length, instead given " ^ n_to_string r)))
+ | Tapp("implicit",[TA_nexp r]) ->
+ (match r.nexp with
+ | Nconst bi -> utf8string (Big_int.string_of_big_int bi)
+ | Nvar v -> utf8string v
+ | _ -> raise (Reporting_basic.err_unreachable l "Internal exp given implicit without var or const"))
+ | _ -> raise (Reporting_basic.err_unreachable l ("Internal exp given non-vector, non-implicit " ^ t_to_string t)))
+ | E_internal_exp_user _ -> raise (Reporting_basic.err_unreachable Unknown ("internal_exp_user not rewritten away"))
+ | E_internal_cast ((_, Overload (_, _,_ )), _) | E_internal_exp _ -> assert false
+
+ and let_exp (LB_aux(lb,_)) = match lb with
+ | LB_val_explicit(ts,pat,e) ->
+ (match ts with
+ | TypSchm_aux (TypSchm_ts (TypQ_aux (TypQ_no_forall,_),_),_) ->
+ prefix 2 1
+ (separate space [string "let"; parens (doc_typscm_atomic ts); doc_atomic_pat pat; equals])
+ (atomic_exp e)
+ | _ ->
+ prefix 2 1
+ (separate space [string "let"; doc_typscm_atomic ts; doc_atomic_pat pat; equals])
+ (atomic_exp e))
+ | LB_val_implicit(pat,e) ->
+ prefix 2 1
+ (separate space [string "let"; doc_atomic_pat pat; equals])
+ (atomic_exp e)
+
+ and doc_fexp (FE_aux(FE_Fexp(id,e),_)) = doc_op equals (doc_id id) (exp e)
+
+ and doc_case (Pat_aux(Pat_exp(pat,e),_)) =
+ doc_op arrow (separate space [string "case"; doc_atomic_pat pat]) (group (exp e))
+
+ (* lexps are parsed as eq_exp - we need to duplicate the precedence
+ * structure for them *)
+ and doc_lexp le = app_lexp le
+ and app_lexp ((LEXP_aux(lexp,_)) as le) = match lexp with
+ | LEXP_memory(id,args) -> doc_id id ^^ parens (separate_map comma exp args)
+ | _ -> vaccess_lexp le
+ and vaccess_lexp ((LEXP_aux(lexp,_)) as le) = match lexp with
+ | LEXP_vector(v,e) -> atomic_lexp v ^^ brackets (exp e)
+ | LEXP_vector_range(v,e1,e2) ->
+ atomic_lexp v ^^ brackets (exp e1 ^^ dotdot ^^ exp e2)
+ | _ -> field_lexp le
+ and field_lexp ((LEXP_aux(lexp,_)) as le) = match lexp with
+ | LEXP_field(v,id) -> atomic_lexp v ^^ dot ^^ doc_id id
+ | _ -> atomic_lexp le
+ and atomic_lexp ((LEXP_aux(lexp,_)) as le) = match lexp with
+ | LEXP_id id -> doc_id id
+ | LEXP_cast(typ,id) -> prefix 2 1 (parens (doc_typ typ)) (doc_id id)
+ | LEXP_memory _ | LEXP_vector _ | LEXP_vector_range _
+ | LEXP_field _ -> group (parens (doc_lexp le))
+ | LEXP_tup tups -> parens (separate_map comma doc_lexp tups)
+
+ (* expose doc_exp and doc_let *)
+ in exp, let_exp
+
+let doc_default (DT_aux(df,_)) = match df with
+ | DT_kind(bk,v) -> separate space [string "default"; doc_bkind bk; doc_var v]
+ | DT_typ(ts,id) -> separate space [string "default"; doc_typscm ts; doc_id id]
+ | DT_order(ord) -> separate space [string "default"; string "order"; doc_ord ord]
+
+let doc_spec (VS_aux(v,_)) = match v with
+ | VS_val_spec(ts,id) ->
+ separate space [string "val"; doc_typscm ts; doc_id id]
+ | VS_extern_no_rename(ts,id) ->
+ separate space [string "val"; string "extern"; doc_typscm ts; doc_id id]
+ | VS_extern_spec(ts,id,s) ->
+ separate space [string "val"; string "extern"; doc_typscm ts;
+ doc_op equals (doc_id id) (dquotes (string s))]
+
+let doc_namescm (Name_sect_aux(ns,_)) = match ns with
+ | Name_sect_none -> empty
+ (* include leading space because the caller doesn't know if ns is
+ * empty, and trailing break already added by the following equals *)
+ | Name_sect_some s -> space ^^ brackets (doc_op equals (string "name") (dquotes (string s)))
+
+let doc_type_union (Tu_aux(typ_u,_)) = match typ_u with
+ | Tu_ty_id(typ,id) -> separate space [doc_typ typ; doc_id id]
+ | Tu_id id -> doc_id id
+
+let doc_typdef (TD_aux(td,_)) = match td with
+ | TD_abbrev(id,nm,typschm) ->
+ doc_op equals (concat [string "typedef"; space; doc_id id; doc_namescm nm]) (doc_typscm typschm)
+ | TD_record(id,nm,typq,fs,_) ->
+ let f_pp (typ,id) = concat [doc_typ typ; space; doc_id id; semi] in
+ let fs_doc = group (separate_map (break 1) f_pp fs) in
+ doc_op equals
+ (concat [string "typedef"; space; doc_id id; doc_namescm nm])
+ (string "const struct" ^^ space ^^ doc_typquant typq (braces fs_doc))
+ | TD_variant(id,nm,typq,ar,_) ->
+ let ar_doc = group (separate_map (semi ^^ break 1) doc_type_union ar) in
+ doc_op equals
+ (concat [string "typedef"; space; doc_id id; doc_namescm nm])
+ (string "const union" ^^ space ^^ doc_typquant typq (braces ar_doc))
+ | TD_enum(id,nm,enums,_) ->
+ let enums_doc = group (separate_map (semi ^^ break 1) doc_id enums) in
+ doc_op equals
+ (concat [string "typedef"; space; doc_id id; doc_namescm nm])
+ (string "enumerate" ^^ space ^^ braces enums_doc)
+ | TD_register(id,n1,n2,rs) ->
+ let doc_rid (r,id) = separate space [doc_range r; colon; doc_id id] ^^ semi in
+ let doc_rids = group (separate_map (break 1) doc_rid rs) in
+ doc_op equals
+ (string "typedef" ^^ space ^^ doc_id id)
+ (separate space [
+ string "register bits";
+ brackets (doc_nexp n1 ^^ colon ^^ doc_nexp n2);
+ braces doc_rids;
+ ])
+
+let doc_kindef (KD_aux(kd,_)) = match kd with
+ | KD_abbrev(kind,id,nm,typschm) ->
+ doc_op equals (concat [string "def"; space; doc_kind kind; space; doc_id id; doc_namescm nm]) (doc_typscm typschm)
+ | KD_nabbrev(kind,id,nm,n) ->
+ doc_op equals (concat [string "def"; space; doc_kind kind; space; doc_id id; doc_namescm nm]) (doc_nexp n)
+ | KD_record(kind,id,nm,typq,fs,_) ->
+ let f_pp (typ,id) = concat [doc_typ typ; space; doc_id id; semi] in
+ let fs_doc = group (separate_map (break 1) f_pp fs) in
+ doc_op equals
+ (concat [string "def"; space;doc_kind kind; space; doc_id id; doc_namescm nm])
+ (string "const struct" ^^ space ^^ doc_typquant typq (braces fs_doc))
+ | KD_variant(kind,id,nm,typq,ar,_) ->
+ let ar_doc = group (separate_map (semi ^^ break 1) doc_type_union ar) in
+ doc_op equals
+ (concat [string "def"; space; doc_kind kind; space; doc_id id; doc_namescm nm])
+ (string "const union" ^^ space ^^ doc_typquant typq (braces ar_doc))
+ | KD_enum(kind,id,nm,enums,_) ->
+ let enums_doc = group (separate_map (semi ^^ break 1) doc_id enums) in
+ doc_op equals
+ (concat [string "def"; space; doc_kind kind; space; doc_id id; doc_namescm nm])
+ (string "enumerate" ^^ space ^^ braces enums_doc)
+ | KD_register(kind,id,n1,n2,rs) ->
+ let doc_rid (r,id) = separate space [doc_range r; colon; doc_id id] ^^ semi in
+ let doc_rids = group (separate_map (break 1) doc_rid rs) in
+ doc_op equals
+ (string "def" ^^ space ^^ doc_kind kind ^^ space ^^ doc_id id)
+ (separate space [
+ string "register bits";
+ brackets (doc_nexp n1 ^^ colon ^^ doc_nexp n2);
+ braces doc_rids;
+ ])
+
+
+let doc_rec (Rec_aux(r,_)) = match r with
+ | Rec_nonrec -> empty
+ (* include trailing space because caller doesn't know if we return
+ * empty *)
+ | Rec_rec -> string "rec" ^^ space
+
+let doc_tannot_opt (Typ_annot_opt_aux(t,_)) = match t with
+ | Typ_annot_opt_some(tq,typ) -> doc_typquant tq (doc_typ typ)
+
+let doc_effects_opt (Effect_opt_aux(e,_)) = match e with
+ | Effect_opt_pure -> string "pure"
+ | Effect_opt_effect e -> doc_effects e
+
+let doc_funcl (FCL_aux(FCL_Funcl(id,pat,exp),_)) =
+ group (doc_op equals (separate space [doc_id id; doc_atomic_pat pat]) (doc_exp exp))
+
+let doc_fundef (FD_aux(FD_function(r, typa, efa, fcls),_)) =
+ match fcls with
+ | [] -> failwith "FD_function with empty function list"
+ | _ ->
+ let sep = hardline ^^ string "and" ^^ space in
+ let clauses = separate_map sep doc_funcl fcls in
+ separate space ([string "function";
+ doc_rec r ^^ doc_tannot_opt typa;]@
+ (match efa with
+ | Effect_opt_aux (Effect_opt_pure,_) -> []
+ | _ -> [string "effect";
+ doc_effects_opt efa;])
+ @[clauses])
+
+let doc_alias (AL_aux (alspec,_)) =
+ match alspec with
+ | AL_subreg((RI_aux (RI_id id,_)),subid) -> doc_id id ^^ dot ^^ doc_id subid
+ | AL_bit((RI_aux (RI_id id,_)),ac) -> doc_id id ^^ brackets (doc_exp ac)
+ | AL_slice((RI_aux (RI_id id,_)),b,e) -> doc_id id ^^ brackets (doc_op dotdot (doc_exp b) (doc_exp e))
+ | AL_concat((RI_aux (RI_id f,_)),(RI_aux (RI_id s,_))) -> doc_op colon (doc_id f) (doc_id s)
+
+let doc_dec (DEC_aux (reg,_)) =
+ match reg with
+ | DEC_reg(typ,id) -> separate space [string "register"; doc_typ typ; doc_id id]
+ | DEC_alias(id,alspec) ->
+ doc_op equals (string "register alias" ^^ space ^^ doc_id id) (doc_alias alspec)
+ | DEC_typ_alias(typ,id,alspec) ->
+ doc_op equals (string "register alias" ^^ space ^^ doc_typ typ) (doc_alias alspec)
+
+let doc_scattered (SD_aux (sdef, _)) = match sdef with
+ | SD_scattered_function (r, typa, efa, id) ->
+ separate space ([
+ string "scattered function";
+ doc_rec r ^^ doc_tannot_opt typa;]@
+ (match efa with
+ | Effect_opt_aux (Effect_opt_pure,_) -> []
+ | _ -> [string "effect"; doc_effects_opt efa;])
+ @[doc_id id])
+ | SD_scattered_variant (id, ns, tq) ->
+ doc_op equals
+ (string "scattered typedef" ^^ space ^^ doc_id id ^^ doc_namescm ns)
+ (string "const union" ^^ space ^^ (doc_typquant tq empty))
+ | SD_scattered_funcl funcl ->
+ string "function clause" ^^ space ^^ doc_funcl funcl
+ | SD_scattered_unioncl (id, tu) ->
+ separate space [string "union"; doc_id id;
+ string "member"; doc_type_union tu]
+ | SD_scattered_end id -> string "end" ^^ space ^^ doc_id id
+
+let rec doc_def def = group (match def with
+ | DEF_default df -> doc_default df
+ | DEF_spec v_spec -> doc_spec v_spec
+ | DEF_type t_def -> doc_typdef t_def
+ | DEF_kind k_def -> doc_kindef k_def
+ | DEF_fundef f_def -> doc_fundef f_def
+ | DEF_val lbind -> doc_let lbind
+ | DEF_reg_dec dec -> doc_dec dec
+ | DEF_scattered sdef -> doc_scattered sdef
+ | DEF_comm (DC_comm s) -> comment (string s)
+ | DEF_comm (DC_comm_struct d) -> comment (doc_def d)
+ ) ^^ hardline
+
+let doc_defs (Defs(defs)) =
+ separate_map hardline doc_def defs
+
+let pp_defs f d = print f (doc_defs d)
+let pp_exp b e = to_buf b (doc_exp e)
+let pat_to_string p =
+ let b = Buffer.create 20 in
+ to_buf b (doc_pat p);
+ Buffer.contents b
diff --git a/src/pretty_print_t_ascii.ml b/src/pretty_print_t_ascii.ml
new file mode 100644
index 00000000..79897f4b
--- /dev/null
+++ b/src/pretty_print_t_ascii.ml
@@ -0,0 +1,149 @@
+(**************************************************************************)
+(* Sail *)
+(* *)
+(* Copyright (c) 2013-2017 *)
+(* Kathyrn Gray *)
+(* Shaked Flur *)
+(* Stephen Kell *)
+(* Gabriel Kerneis *)
+(* Robert Norton-Wright *)
+(* Christopher Pulte *)
+(* Peter Sewell *)
+(* *)
+(* 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_internal
+open Ast
+open Pretty_print_common
+open Big_int
+
+(* **************************************************************************
+ * pp from tannot to ASCII source, for pp of built-in type environment
+ *)
+
+let rec pp_format_t_ascii t =
+ match t.t with
+ | Tid i -> i
+ | Tvar i -> "'" ^ i
+ | Tfn(t1,t2,_,e) -> (pp_format_t_ascii t1) ^ " -> " ^ (pp_format_t_ascii t2) ^ (match e.effect with Eset [] -> "" | _ -> " effect " ^ pp_format_e_ascii e)
+ | Ttup(tups) -> "(" ^ (list_format ", " pp_format_t_ascii tups) ^ ")"
+ | Tapp(i,args) -> i ^ "<" ^ list_format ", " pp_format_targ_ascii args ^ ">"
+ | Tabbrev(ti,ta) -> (pp_format_t_ascii ti) (* (pp_format_t_ascii ta) *)
+ | Tuvar(_) -> failwith "Tuvar in pp_format_t_ascii"
+ | Toptions _ -> failwith "Toptions in pp_format_t_ascii"
+and pp_format_targ_ascii = function
+ | TA_typ t -> pp_format_t_ascii t
+ | TA_nexp n -> pp_format_n_ascii n
+ | TA_eft e -> pp_format_e_ascii e
+ | TA_ord o -> pp_format_o_ascii o
+and pp_format_n_ascii n =
+ match n.nexp with
+ | Nid (i, n) -> i (* from an abbreviation *)
+ | Nvar i -> "'" ^ i
+ | Nconst i -> (string_of_int (int_of_big_int i))
+ | Npos_inf -> "infinity"
+ | Nadd(n1,n2) -> (pp_format_n_ascii n1) ^ "+" ^ (pp_format_n_ascii n2)
+ | Nsub(n1,n2) -> (pp_format_n_ascii n1) ^ "-" ^ (pp_format_n_ascii n2)
+ | Nmult(n1,n2) -> (pp_format_n_ascii n1) ^ "*" ^ (pp_format_n_ascii n2)
+ | N2n(n,_) -> "2**"^(pp_format_n_ascii n) (* string_of_big_int i ^ *)
+ | Nneg n -> "-" ^ (pp_format_n_ascii n)
+ | Nuvar _ -> failwith "Nuvar in pp_format_n_ascii"
+ | Nneg_inf -> "-infinity"
+ | Npow _ -> failwith "Npow in pp_format_n_ascii"
+ | Ninexact -> failwith "Ninexact in pp_format_n_ascii"
+and pp_format_e_ascii e =
+ match e.effect with
+ | Evar i -> "'" ^ i
+ | Eset es -> "{" ^
+ (list_format ", " pp_format_base_effect_ascii es) ^ "}"
+ | Euvar(_) -> failwith "Euvar in pp_format_e_ascii"
+and pp_format_o_ascii o =
+ match o.order with
+ | Ovar i -> "'" ^ i
+ | Oinc -> "inc"
+ | Odec -> "dec"
+ | Ouvar(_) -> failwith "Ouvar in pp_format_o_ascii"
+and pp_format_base_effect_ascii (BE_aux(e,l)) =
+ match e with
+ | BE_rreg -> "rreg"
+ | BE_wreg -> "wreg"
+ | BE_rmem -> "rmem"
+ | BE_wmem -> "wmem"
+ | BE_wmv -> "wmv"
+ | BE_eamem -> "eamem"
+ | BE_barr -> "barr"
+ | BE_depend -> "depend"
+ | BE_undef -> "undef"
+ | BE_unspec -> "unspec"
+ | BE_nondet -> "nondet"
+ | BE_lset -> "lset"
+ | BE_lret -> "lret"
+ | BE_escape -> "escape"
+
+and pp_format_nes_ascii nes =
+ list_format ", " pp_format_ne_ascii nes
+
+and pp_format_ne_ascii ne =
+ match ne with
+ | Lt(_,_,n1,n2) -> pp_format_n_ascii n1 ^ " < " ^ pp_format_n_ascii n2
+ | LtEq(_,_,n1,n2) -> pp_format_n_ascii n1 ^ " <= " ^ pp_format_n_ascii n2
+ | NtEq(_,n1,n2) -> pp_format_n_ascii n1 ^ " != " ^ pp_format_n_ascii n2
+ | Eq(_,n1,n2) -> pp_format_n_ascii n1 ^ " = " ^ pp_format_n_ascii n2
+ | GtEq(_,_,n1,n2) -> pp_format_n_ascii n1 ^ " >= " ^ pp_format_n_ascii n2
+ | Gt(_,_,n1,n2) -> pp_format_n_ascii n1 ^ " > " ^ pp_format_n_ascii n2
+ | In(_,i,ns) | InS(_,{nexp=Nvar i},ns) ->
+ i ^ " IN {" ^ (list_format ", " string_of_int ns)^ "}"
+ | InS(_,_,ns) -> (* when the variable has been replaced by a unification variable, we use this *)
+ failwith "InS in pp_format_nes_ascii" (*"(Nec_in \"fresh\" [" ^ (list_format "; " string_of_int ns)^ "])"*)
+ | Predicate(_,n1,n2) -> "flow_constraints(" ^ pp_format_ne_ascii n1 ^", "^ pp_format_ne_ascii n2 ^")"
+ | CondCons(_,_,_,nes_c,nes_t) ->
+ failwith "CondCons in pp_format_nes_ascii" (*"(Nec_cond " ^ (pp_format_nes nes_c) ^ " " ^ (pp_format_nes nes_t) ^ ")"*)
+ | BranchCons(_,_,nes_b) ->
+ failwith "BranchCons in pp_format_nes_ascii" (*"(Nec_branch " ^ (pp_format_nes nes_b) ^ ")"*)
+
+let rec pp_format_annot_ascii = function
+ | NoTyp -> "Nothing"
+ | Base((targs,t),tag,nes,efct,efctsum,_) ->
+ (*TODO print out bindings for use in pattern match in interpreter*)
+ (match tag with External (Some s) -> "("^s^") " | _ -> "") ^
+ (match (targs,nes) with ([],[]) -> "\n" | _ ->
+ "forall " ^ list_format ", " (function (i,k) -> kind_to_string k ^" '"^ i) targs ^
+ (match nes with [] -> "" | _ -> ", " ^ pp_format_nes_ascii nes)
+ ^ ".\n") ^ " "
+ ^ pp_format_t_ascii t
+ ^ "\n"
+(*
+^ " ********** " ^ pp_format_tag tag ^ ", " ^ pp_format_nes nes ^ ", " ^
+ pp_format_e_lem efct ^ ", " ^ pp_format_e_lem efctsum ^ "))"
+*)
+ | Overload (tannot, return_type_overloading_allowed, tannots) ->
+ (*pp_format_annot_ascii tannot*) "\n" ^ String.concat "" (List.map (function tannot' -> " " ^ pp_format_annot_ascii tannot' ) tannots)
+