summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/PrintPure.ml29
-rw-r--r--src/Pure.ml20
-rw-r--r--src/SymbolicToPure.ml82
3 files changed, 99 insertions, 32 deletions
diff --git a/src/PrintPure.ml b/src/PrintPure.ml
index b631f940..e5b58b9f 100644
--- a/src/PrintPure.ml
+++ b/src/PrintPure.ml
@@ -34,6 +34,9 @@ let value_to_type_formatter (fmt : value_formatter) : type_formatter =
type_def_id_to_string = fmt.type_def_id_to_string;
}
+(* TODO: we need to store which variables we have encountered so far, and
+ remove [var_id_to_string].
+*)
type ast_formatter = {
type_var_id_to_string : TypeVarId.id -> string;
type_def_id_to_string : TypeDefId.id -> string;
@@ -101,8 +104,8 @@ let mk_ast_formatter (type_defs : T.type_def TypeDefId.Map.t)
Print.Contexts.type_ctx_to_adt_variant_to_string_fun type_defs
in
let var_id_to_string vid =
- (* TODO: lookup in the context *)
- VarId.to_string vid
+ (* TODO: somehow lookup in the context *)
+ "@" ^ VarId.to_string vid
in
let adt_field_names =
Print.Contexts.type_ctx_to_adt_field_names_fun type_defs
@@ -183,7 +186,12 @@ let type_def_to_string (fmt : type_formatter) (def : type_def) : string =
"enum " ^ name ^ params ^ " =\n" ^ variants
let var_to_string (fmt : type_formatter) (v : var) : string =
- "(@" ^ VarId.to_string v.id ^ " : " ^ ty_to_string fmt v.ty ^ ")"
+ let varname =
+ match v.basename with
+ | Some name -> name ^ "^" ^ VarId.to_string v.id
+ | None -> "@" ^ VarId.to_string v.id
+ in
+ "(" ^ varname ^ " : " ^ ty_to_string fmt v.ty ^ ")"
let var_or_dummy_to_string (fmt : value_formatter) (v : var_or_dummy) : string =
match v with
@@ -218,6 +226,7 @@ let rec projection_to_string (fmt : ast_formatter) (inside : string)
"(" ^ s ^ " as " ^ variant_name ^ ")." ^ field_name))
let place_to_string (fmt : ast_formatter) (p : place) : string =
+ (* TODO: improve that *)
let var = "@" ^ fmt.var_id_to_string p.var in
projection_to_string fmt var p.projection
@@ -330,7 +339,7 @@ let rec expression_to_string (fmt : ast_formatter) (indent : string)
| Return v -> indent ^ "return " ^ typed_rvalue_to_string fmt v
| Fail -> indent ^ "fail"
| Let (lb, e) -> let_to_string fmt indent indent_incr lb e
- | Switch (scrutinee, body) ->
+ | Switch (scrutinee, _, body) ->
switch_to_string fmt indent indent_incr scrutinee body
and let_to_string (fmt : ast_formatter) (indent : string) (indent_incr : string)
@@ -339,7 +348,9 @@ and let_to_string (fmt : ast_formatter) (indent : string) (indent_incr : string)
let val_fmt = ast_to_value_formatter fmt in
match lb with
| Call (lvs, call) ->
- let lvs = List.map (typed_lvalue_to_string val_fmt) lvs in
+ let lvs =
+ List.map (fun (lv, _) -> typed_lvalue_to_string val_fmt lv) lvs
+ in
let lvs =
match lvs with
| [] ->
@@ -359,13 +370,15 @@ and let_to_string (fmt : ast_formatter) (indent : string) (indent_incr : string)
else fun_id ^ " " ^ String.concat " " all_args
in
indent ^ "let " ^ lvs ^ " = " ^ call ^ " in\n" ^ e
- | Assign (lv, rv) ->
+ | Assign (lv, _, rv, _) ->
let lv = typed_lvalue_to_string val_fmt lv in
let rv = typed_rvalue_to_string fmt rv in
indent ^ "let " ^ lv ^ " = " ^ rv ^ " in\n" ^ e
- | Deconstruct (lvs, opt_adt_id, rv) ->
+ | Deconstruct (lvs, opt_adt_id, rv, _) ->
let rv = typed_rvalue_to_string fmt rv in
- let lvs = List.map (var_or_dummy_to_string val_fmt) lvs in
+ let lvs =
+ List.map (fun (lv, _) -> var_or_dummy_to_string val_fmt lv) lvs
+ in
let lvs =
match opt_adt_id with
| None -> "(" ^ String.concat ", " lvs ^ ")"
diff --git a/src/Pure.ml b/src/Pure.ml
index 02f6b1ba..ba0c9837 100644
--- a/src/Pure.ml
+++ b/src/Pure.ml
@@ -111,6 +111,14 @@ type projection = projection_elem list
type place = { var : VarId.id; projection : projection }
+type mplace = { name : string option; projection : projection }
+(** "Meta" place.
+
+ Meta-data retrieved from the symbolic execution, which gives provenance
+ information about the values. We use this to generate names for the variables
+ we introduce.
+ *)
+
type rvalue =
| RvConcrete of constant_value
| RvPlace of place
@@ -148,15 +156,19 @@ type call = {
In the extracted code, we add a unit argument. This is unit argument is
added later, when going from the "pure" AST to the "extracted" AST.
*)
+ args_mplaces : mplace option list; (** Meta data *)
}
type let_bindings =
- | Call of typed_lvalue list * call
+ | Call of (typed_lvalue * mplace option) list * call
(** The called function and the tuple of returned values. *)
- | Assign of typed_lvalue * typed_rvalue
+ | Assign of typed_lvalue * mplace option * typed_rvalue * mplace option
(** Variable assignment: the introduced pattern and the place we read *)
| Deconstruct of
- var_or_dummy list * (TypeDefId.id * VariantId.id) option * typed_rvalue
+ (var_or_dummy * mplace option) list
+ * (TypeDefId.id * VariantId.id) option
+ * typed_rvalue
+ * mplace option
(** This is used in two cases.
1. When deconstructing a tuple:
@@ -202,7 +214,7 @@ type expression =
| Fail
| Let of let_bindings * expression
(** Let bindings include the let-bindings introduced because of function calls *)
- | Switch of typed_rvalue * switch_body
+ | Switch of typed_rvalue * mplace option * switch_body
and switch_body =
| If of expression * expression
diff --git a/src/SymbolicToPure.ml b/src/SymbolicToPure.ml
index 716b4e94..fb1bb029 100644
--- a/src/SymbolicToPure.ml
+++ b/src/SymbolicToPure.ml
@@ -768,6 +768,24 @@ let abs_to_consumed (ctx : bs_ctx) (abs : V.abs) : typed_rvalue list =
log#ldebug (lazy ("abs_to_consumed:\n" ^ abs_to_string ctx abs));
List.filter_map (typed_avalue_to_consumed ctx) abs.avalues
+let translate_mprojection_elem (pe : E.projection_elem) : projection_elem option
+ =
+ match pe with
+ | Deref | DerefBox -> None
+ | Field (pkind, field_id) -> Some { pkind; field_id }
+
+let translate_mprojection (p : E.projection) : projection =
+ List.filter_map translate_mprojection_elem p
+
+(** Translate a "meta"-place *)
+let translate_mplace (p : S.place) : mplace =
+ let name = p.bv.name in
+ let projection = translate_mprojection p.projection in
+ { name; projection }
+
+let translate_opt_mplace (p : S.place option) : mplace option =
+ match p with None -> None | Some p -> Some (translate_mplace p)
+
(** Explore an abstraction value and convert it to a given back value
by collecting all the meta-values from the ended *borrows*.
@@ -895,7 +913,7 @@ let rec translate_expression (e : S.expression) (ctx : bs_ctx) : expression =
| Panic -> Fail
| FunCall (call, e) -> translate_function_call call e ctx
| EndAbstraction (abs, e) -> translate_end_abstraction abs e ctx
- | Expansion (sv, exp) -> translate_expansion sv exp ctx
+ | Expansion (p, sv, exp) -> translate_expansion p sv exp ctx
| Meta (_, e) ->
(* We ignore the meta information *)
translate_expression e ctx
@@ -935,6 +953,8 @@ and translate_function_call (call : S.call) (e : S.expression) (ctx : bs_ctx) :
(* Translate the function call *)
let type_params = List.map (ctx_translate_fwd_ty ctx) call.type_params in
let args = List.map (typed_value_to_rvalue ctx) call.args in
+ let args_mplaces = List.map translate_opt_mplace call.args_places in
+ let dest_mplace = translate_opt_mplace call.dest_place in
let ctx, dest = fresh_var_for_symbolic_value call.dest ctx in
(* Retrieve the function id, and register the function call in the context
* if necessary. *)
@@ -960,11 +980,11 @@ and translate_function_call (call : S.call) (e : S.expression) (ctx : bs_ctx) :
(ctx, Binop (binop, int_ty0))
| _ -> failwith "Unreachable")
in
- let call = { func; type_params; args } in
+ let call = { func; type_params; args; args_mplaces } in
(* Translate the next expression *)
let e = translate_expression e ctx in
(* Put together *)
- Let (Call ([ mk_typed_lvalue_from_var dest ], call), e)
+ Let (Call ([ (mk_typed_lvalue_from_var dest, dest_mplace) ], call), e)
and translate_end_abstraction (abs : V.abs) (e : S.expression) (ctx : bs_ctx) :
expression =
@@ -1019,7 +1039,7 @@ and translate_end_abstraction (abs : V.abs) (e : S.expression) (ctx : bs_ctx) :
(* Generate the assignemnts *)
List.fold_right
(fun (var, value) e ->
- Let (Assign (mk_typed_lvalue_from_var var, value), e))
+ Let (Assign (mk_typed_lvalue_from_var var, None, value, None), e))
variables_values e
| V.FunCall ->
let call_info = V.FunCallId.Map.find abs.call_id ctx.calls in
@@ -1072,7 +1092,9 @@ and translate_end_abstraction (abs : V.abs) (e : S.expression) (ctx : bs_ctx) :
(* Translate the next expression *)
let e = translate_expression e ctx in
(* Put everything together *)
- let call = { func; type_params; args = inputs } in
+ let args_mplaces = List.map (fun _ -> None) inputs in
+ let call = { func; type_params; args = inputs; args_mplaces } in
+ let outputs = List.map (fun x -> (x, None)) outputs in
Let (Call (outputs, call), e)
| V.SynthRet ->
(* If we end the abstraction which consumed the return value of the function
@@ -1126,14 +1148,17 @@ and translate_end_abstraction (abs : V.abs) (e : S.expression) (ctx : bs_ctx) :
(* Generate the assignments *)
List.fold_right
(fun (given_back, input_var) e ->
- Let (Assign (given_back, mk_typed_rvalue_from_var input_var), e))
+ Let
+ ( Assign (given_back, None, mk_typed_rvalue_from_var input_var, None),
+ e ))
given_back_inputs e
-and translate_expansion (sv : V.symbolic_value) (exp : S.expansion)
- (ctx : bs_ctx) : expression =
+and translate_expansion (p : S.place option) (sv : V.symbolic_value)
+ (exp : S.expansion) (ctx : bs_ctx) : expression =
(* Translate the scrutinee *)
let scrutinee_var = lookup_var_for_symbolic_value sv ctx in
let scrutinee = mk_typed_rvalue_from_var scrutinee_var in
+ let scrutinee_mplace = translate_opt_mplace p in
(* Translate the branches *)
match exp with
| ExpandNoBranch (sexp, e) -> (
@@ -1142,12 +1167,15 @@ and translate_expansion (sv : V.symbolic_value) (exp : S.expansion)
(* Actually, we don't *register* symbolic expansions to constant
* values in the symbolic ADT *)
failwith "Unreachable"
- | SeMutRef (_, sv) | SeSharedRef (_, sv) ->
+ | SeMutRef (_, nsv) | SeSharedRef (_, nsv) ->
(* The (mut/shared) borrow type is extracted to identity: we thus simply
* introduce an reassignment *)
- let ctx, var = fresh_var_for_symbolic_value sv ctx in
+ let ctx, var = fresh_var_for_symbolic_value nsv ctx in
let e = translate_expression e ctx in
- Let (Assign (mk_typed_lvalue_from_var var, scrutinee), e)
+ Let
+ ( Assign
+ (mk_typed_lvalue_from_var var, None, scrutinee, scrutinee_mplace),
+ e )
| SeAdt _ ->
(* Should be in the [ExpandAdt] case *)
failwith "Unreachable")
@@ -1167,9 +1195,13 @@ and translate_expansion (sv : V.symbolic_value) (exp : S.expansion)
if is_enum then
(* This is an enumeration: introduce an [ExpandEnum] let-binding *)
let variant_id = Option.get variant_id in
- let vars = List.map (fun x -> Var x) vars in
+ let vars = List.map (fun x -> (Var x, None)) vars in
Let
- ( Deconstruct (vars, Some (adt_id, variant_id), scrutinee),
+ ( Deconstruct
+ ( vars,
+ Some (adt_id, variant_id),
+ scrutinee,
+ scrutinee_mplace ),
branch )
else
(* This is not an enumeration: introduce let-bindings for every
@@ -1190,11 +1222,14 @@ and translate_expansion (sv : V.symbolic_value) (exp : S.expansion)
List.fold_right
(fun (fid, var) e ->
let field_proj = gen_field_proj fid var in
- Let (Assign (mk_typed_lvalue_from_var var, field_proj), e))
+ Let
+ ( Assign
+ (mk_typed_lvalue_from_var var, None, field_proj, None),
+ e ))
id_var_pairs branch
| T.Tuple ->
- let vars = List.map (fun x -> Var x) vars in
- Let (Deconstruct (vars, None, scrutinee), branch)
+ let vars = List.map (fun x -> (Var x, None)) vars in
+ Let (Deconstruct (vars, None, scrutinee, scrutinee_mplace), branch)
| T.Assumed T.Box ->
(* There should be exactly one variable *)
let var =
@@ -1202,7 +1237,13 @@ and translate_expansion (sv : V.symbolic_value) (exp : S.expansion)
in
(* We simply introduce an assignment - the box type is the
* identity when extracted (`box a == a`) *)
- Let (Assign (mk_typed_lvalue_from_var var, scrutinee), branch))
+ Let
+ ( Assign
+ ( mk_typed_lvalue_from_var var,
+ None,
+ scrutinee,
+ scrutinee_mplace ),
+ branch ))
| branches ->
let translate_branch (variant_id : T.VariantId.id option)
(svl : V.symbolic_value list) (branch : S.expression) :
@@ -1217,13 +1258,13 @@ and translate_expansion (sv : V.symbolic_value) (exp : S.expansion)
let branches =
List.map (fun (vid, svl, e) -> translate_branch vid svl e) branches
in
- Switch (scrutinee, Match branches))
+ Switch (scrutinee, scrutinee_mplace, Match branches))
| ExpandBool (true_e, false_e) ->
(* We don't need to update the context: we don't introduce any
* new values/variables *)
let true_e = translate_expression true_e ctx in
let false_e = translate_expression false_e ctx in
- Switch (scrutinee, If (true_e, false_e))
+ Switch (scrutinee, scrutinee_mplace, If (true_e, false_e))
| ExpandInt (int_ty, branches, otherwise) ->
let translate_branch ((v, branch_e) : V.scalar_value * S.expression) :
scalar_value * expression =
@@ -1234,7 +1275,8 @@ and translate_expansion (sv : V.symbolic_value) (exp : S.expansion)
in
let branches = List.map translate_branch branches in
let otherwise = translate_expression otherwise ctx in
- Switch (scrutinee, SwitchInt (int_ty, branches, otherwise))
+ Switch
+ (scrutinee, scrutinee_mplace, SwitchInt (int_ty, branches, otherwise))
let translate_fun_def (ctx : bs_ctx) (body : S.expression) : fun_def =
let def = ctx.fun_def in