summaryrefslogtreecommitdiff
path: root/compiler/SynthesizeSymbolic.ml
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/SynthesizeSymbolic.ml')
-rw-r--r--compiler/SynthesizeSymbolic.ml156
1 files changed, 156 insertions, 0 deletions
diff --git a/compiler/SynthesizeSymbolic.ml b/compiler/SynthesizeSymbolic.ml
new file mode 100644
index 00000000..a2256bdd
--- /dev/null
+++ b/compiler/SynthesizeSymbolic.ml
@@ -0,0 +1,156 @@
+module C = Collections
+module T = Types
+module V = Values
+module E = Expressions
+module A = LlbcAst
+open SymbolicAst
+
+let mk_mplace (p : E.place) (ctx : Contexts.eval_ctx) : mplace =
+ let bv = Contexts.ctx_lookup_binder ctx p.var_id in
+ { bv; projection = p.projection }
+
+let mk_opt_mplace (p : E.place option) (ctx : Contexts.eval_ctx) : mplace option
+ =
+ match p with None -> None | Some p -> Some (mk_mplace p ctx)
+
+let mk_opt_place_from_op (op : E.operand) (ctx : Contexts.eval_ctx) :
+ mplace option =
+ match op with
+ | E.Copy p | E.Move p -> Some (mk_mplace p ctx)
+ | E.Constant _ -> None
+
+let synthesize_symbolic_expansion (sv : V.symbolic_value)
+ (place : mplace option) (seel : V.symbolic_expansion option list)
+ (exprl : expression list option) : expression option =
+ match exprl with
+ | None -> None
+ | Some exprl ->
+ let ls = List.combine seel exprl in
+ (* Match on the symbolic value type to know which can of expansion happened *)
+ let expansion =
+ match sv.V.sv_ty with
+ | T.Bool -> (
+ (* Boolean expansion: there should be two branches *)
+ match ls with
+ | [
+ (Some (V.SeConcrete (V.Bool true)), true_exp);
+ (Some (V.SeConcrete (V.Bool false)), false_exp);
+ ] ->
+ ExpandBool (true_exp, false_exp)
+ | _ -> failwith "Ill-formed boolean expansion")
+ | T.Integer int_ty ->
+ (* Switch over an integer: split between the "regular" branches
+ and the "otherwise" branch (which should be the last branch) *)
+ let branches, otherwise = C.List.pop_last ls in
+ (* For all the regular branches, the symbolic value should have
+ * been expanded to a constant *)
+ let get_scalar (see : V.symbolic_expansion option) : V.scalar_value
+ =
+ match see with
+ | Some (V.SeConcrete (V.Scalar cv)) ->
+ assert (cv.V.int_ty = int_ty);
+ cv
+ | _ -> failwith "Unreachable"
+ in
+ let branches =
+ List.map (fun (see, exp) -> (get_scalar see, exp)) branches
+ in
+ (* For the otherwise branch, the symbolic value should have been left
+ * unchanged *)
+ let otherwise_see, otherwise = otherwise in
+ assert (otherwise_see = None);
+ (* Return *)
+ ExpandInt (int_ty, branches, otherwise)
+ | T.Adt (_, _, _) ->
+ (* Branching: it is necessarily an enumeration expansion *)
+ let get_variant (see : V.symbolic_expansion option) :
+ T.VariantId.id option * V.symbolic_value list =
+ match see with
+ | Some (V.SeAdt (vid, fields)) -> (vid, fields)
+ | _ -> failwith "Ill-formed branching ADT expansion"
+ in
+ let exp =
+ List.map
+ (fun (see, exp) ->
+ let vid, fields = get_variant see in
+ (vid, fields, exp))
+ ls
+ in
+ ExpandAdt exp
+ | T.Ref (_, _, _) -> (
+ (* Reference expansion: there should be one branch *)
+ match ls with
+ | [ (Some see, exp) ] -> ExpandNoBranch (see, exp)
+ | _ -> failwith "Ill-formed borrow expansion")
+ | T.TypeVar _ | Char | Never | Str | Array _ | Slice _ ->
+ failwith "Ill-formed symbolic expansion"
+ in
+ Some (Expansion (place, sv, expansion))
+
+let synthesize_symbolic_expansion_no_branching (sv : V.symbolic_value)
+ (place : mplace option) (see : V.symbolic_expansion)
+ (expr : expression option) : expression option =
+ let exprl = match expr with None -> None | Some expr -> Some [ expr ] in
+ synthesize_symbolic_expansion sv place [ Some see ] exprl
+
+let synthesize_function_call (call_id : call_id)
+ (abstractions : V.AbstractionId.id list) (type_params : T.ety list)
+ (args : V.typed_value list) (args_places : mplace option list)
+ (dest : V.symbolic_value) (dest_place : mplace option)
+ (expr : expression option) : expression option =
+ match expr with
+ | None -> None
+ | Some expr ->
+ let call =
+ {
+ call_id;
+ abstractions;
+ type_params;
+ args;
+ dest;
+ args_places;
+ dest_place;
+ }
+ in
+ Some (FunCall (call, expr))
+
+let synthesize_global_eval (gid : A.GlobalDeclId.id) (dest : V.symbolic_value)
+ (expr : expression option) : expression option =
+ match expr with None -> None | Some e -> Some (EvalGlobal (gid, dest, e))
+
+let synthesize_regular_function_call (fun_id : A.fun_id)
+ (call_id : V.FunCallId.id) (abstractions : V.AbstractionId.id list)
+ (type_params : T.ety list) (args : V.typed_value list)
+ (args_places : mplace option list) (dest : V.symbolic_value)
+ (dest_place : mplace option) (expr : expression option) : expression option
+ =
+ synthesize_function_call
+ (Fun (fun_id, call_id))
+ abstractions type_params args args_places dest dest_place expr
+
+let synthesize_unary_op (unop : E.unop) (arg : V.typed_value)
+ (arg_place : mplace option) (dest : V.symbolic_value)
+ (dest_place : mplace option) (expr : expression option) : expression option
+ =
+ synthesize_function_call (Unop unop) [] [] [ arg ] [ arg_place ] dest
+ dest_place expr
+
+let synthesize_binary_op (binop : E.binop) (arg0 : V.typed_value)
+ (arg0_place : mplace option) (arg1 : V.typed_value)
+ (arg1_place : mplace option) (dest : V.symbolic_value)
+ (dest_place : mplace option) (expr : expression option) : expression option
+ =
+ synthesize_function_call (Binop binop) [] [] [ arg0; arg1 ]
+ [ arg0_place; arg1_place ] dest dest_place expr
+
+let synthesize_end_abstraction (abs : V.abs) (expr : expression option) :
+ expression option =
+ match expr with
+ | None -> None
+ | Some expr -> Some (EndAbstraction (abs, expr))
+
+let synthesize_assignment (lplace : mplace) (rvalue : V.typed_value)
+ (rplace : mplace option) (expr : expression option) : expression option =
+ match expr with
+ | None -> None
+ | Some expr -> Some (Meta (Assignment (lplace, rvalue, rplace), expr))