summaryrefslogtreecommitdiff
path: root/src/pretty_print.ml
diff options
context:
space:
mode:
Diffstat (limited to 'src/pretty_print.ml')
-rw-r--r--src/pretty_print.ml353
1 files changed, 351 insertions, 2 deletions
diff --git a/src/pretty_print.ml b/src/pretty_print.ml
index 6f3422d6..7ec83696 100644
--- a/src/pretty_print.ml
+++ b/src/pretty_print.ml
@@ -1769,6 +1769,355 @@ let pp_defs_ocaml f d top_line opens =
* PPrint-based sail-to-lem pretty printer
****************************************************************************)
+let doc_id_ocaml (Id_aux(i,_)) =
+ match i with
+ | Id("bit") -> string "vbit"
+ | Id i -> string (if i.[0] = '\'' || is_number(i.[0]) then "_" ^ i else 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_exp_lem, doc_let_lem =
+ 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_lem le) (exp e)
+ | LEXP_vector _ ->
+ doc_op (string "<-") (doc_lexp_array_lem le) (exp e)
+ | LEXP_vector_range _ ->
+ parens ((string "set_vector_range") ^^ space ^^ (doc_lexp_lem le) ^^ space ^^ (exp 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 [], _)) ->
+ 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_lem 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 Lem 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 = match annot with
+ | Base(_,External (Some n),_,_,_,_) -> string n
+ | Base(_,Constructor,_,_,_,_) -> doc_id_ocaml_ctor f
+ | _ -> doc_id_lem f in
+ parens (doc_unop call (parens (separate_map comma exp args)))
+ | 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_lem id
+ | Base((_, ({t = Tapp("register",_)} | {t=Tabbrev(_,{t=Tapp("register",_)})})),_,_,_,_,_) ->
+ if read_registers
+ then string "(read_register " ^^ doc_id_lem id ^^ string ")"
+ else doc_id_lem id
+ | Base(_,(Constructor|Enum _),_,_,_,_) -> doc_id_ocaml_ctor 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 reg; string_lit (string field)])
+ | Alias_extract(reg,start,stop) ->
+ if start = stop
+ then parens (separate space [string "bit_vector_access";string reg;doc_int start])
+ else parens
+ (separate space [string "vector_subrange"; string reg; doc_int start; doc_int stop])
+ | Alias_pair(reg1,reg2) ->
+ parens (separate space [string "vector_concat"; string reg1; string reg2]))
+ | _ -> doc_id_lem 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
+ | _ -> (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; _])}) ->
+ 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 true 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_lem 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_lem 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_lem 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_lem ((LEXP_aux(lexp,(l,annot))) as le) =
+ let exp = top_exp false in
+ match lexp with
+ | LEXP_vector(v,e) -> parens ((string "vector_access") ^^ space ^^ doc_lexp_lem v) ^^ dot ^^ parens (exp e)
+ | LEXP_vector_range(v,e1,e2) ->
+ parens ((string "vector_subrange") ^^ space ^^ doc_lexp_lem v ^^ space ^^ (exp e1) ^^ space ^^ (exp e2))
+ | LEXP_field(v,id) -> doc_lexp_lem v ^^ dot ^^ doc_id_lem id
+ | LEXP_id id -> doc_id_lem id
+ | LEXP_cast(typ,id) -> (doc_id_lem id)
+
+ and doc_lexp_array_lem ((LEXP_aux(lexp,(l,annot))) as le) = match lexp with
+ | LEXP_vector(v,e) -> parens ((string "get_varray") ^^ space ^^ doc_lexp_lem v) ^^ dot ^^ parens (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 = 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"})})])}) ->
+ true
+ | _ -> 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_lem v)) ^^
+ dot ^^ parens (exp e))
+ (exp e_new_v)
+ | LEXP_vector_range(v,e1,e2) ->
+ parens ((string (if is_bit then "set_vector_subrange_bit" else "set_vector_subrange_v")) ^^ space ^^
+ doc_lexp_lem v ^^ space ^^ exp e1 ^^ space ^^ exp e2 ^^ space ^^ exp e_new_v)
+ | LEXP_field(v,id) ->
+ parens ((string "set_register_field") ^^ space ^^
+ doc_lexp_lem 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 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 (doc_int start))
+ (exp e_new_v)
+ else
+ parens ((string (if is_bit then "set_vector_subrange_bit" else "set_vector_subrange_v")) ^^ 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_lem 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_lem id ^^ parens (separate_map comma (top_exp false) (args@[e_new_v]))
+
+ (* expose doc_exp and doc_let *)
+ in top_exp false, let_exp
+
+let doc_funcl_lem (FCL_aux(FCL_Funcl(id,pat,exp),_)) =
+ group (doc_op arrow (doc_pat_ocaml pat) (doc_exp_lem exp))
+
+let get_id = function
+ | [] -> failwith "FD_function with empty list"
+ | (FCL_aux (FCL_Funcl (id,_,_),_))::_ -> id
+
+let doc_fundef_lem (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_lem id); (doc_pat_ocaml pat); equals]) ^^ hardline ^^ (doc_exp_lem exp)
+ | _ ->
+ let id = get_id fcls in
+ let sep = hardline ^^ pipe ^^ space in
+ let clauses = separate_map sep doc_funcl_lem fcls in
+ separate space [string "let";
+ doc_rec_ocaml r;
+ doc_id_lem id;
+ equals;
+ (string "function");
+ (hardline^^pipe);
+ clauses]
+
+
+let doc_def_lem 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_lem f_def
+ | DEF_val lbind -> doc_let_lem lbind
+ | DEF_reg_dec dec -> doc_dec_ocaml dec
+ | DEF_scattered sdef -> empty (*shoulnd't still be here*)
+ ) ^^ hardline
+
+let doc_defs_lem (Defs(defs)) =
+ separate_map hardline doc_def_lem defs
+let pp_defs_lem 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_lem d))
+
+
(*
| E_for(id,exp1,exp2,exp3,(Ord_aux(order,_)),exp4) ->
@@ -1782,7 +2131,7 @@ let pp_defs_ocaml f d top_line opens =
let start = group (exp exp1) in
let stop = group (exp exp2) in
let by = group (exp exp3) in
- let var = doc_id_ocaml id in
+ let var = doc_id_lem id in
let body = exp exp4 in
let forL = if order = Ord_inc then string "foreach_inc" else string "foreach_dec" in
@@ -1793,7 +2142,7 @@ let pp_defs_ocaml f d top_line opens =
(string "return") ^^ space ^^ updated_vars
)
- (* this way requires the following OCaml declarations first
+ (* this way requires the following Lem declarations first
let rec foreach_inc i stop by body =
if i <= stop then (body i; foreach_inc (i + by) stop by body) else ()