summaryrefslogtreecommitdiff
path: root/src/ExtractToFStar.ml
diff options
context:
space:
mode:
Diffstat (limited to 'src/ExtractToFStar.ml')
-rw-r--r--src/ExtractToFStar.ml235
1 files changed, 139 insertions, 96 deletions
diff --git a/src/ExtractToFStar.ml b/src/ExtractToFStar.ml
index e9b91c6e..8134144a 100644
--- a/src/ExtractToFStar.ml
+++ b/src/ExtractToFStar.ml
@@ -760,6 +760,8 @@ let extract_fun_decl_register_names (ctx : extraction_ctx) (keep_fwd : bool)
Note that lvalues can introduce new variables: we thus return an extraction
context updated with new bindings.
+
+ TODO: we don't need something very generic anymore
*)
let extract_adt_g_value
(extract_value : extraction_ctx -> bool -> 'v -> extraction_ctx)
@@ -830,57 +832,6 @@ let rec extract_typed_lvalue (ctx : extraction_ctx) (fmt : F.formatter)
extract_adt_g_value extract_value fmt ctx inside av.variant_id
av.field_values v.ty
-let extract_place (ctx : extraction_ctx) (fmt : F.formatter) (p : place) : unit
- =
- let rec extract_projection (pl : projection) : unit =
- match pl with
- | [] ->
- (* No projection element left: print the variable *)
- let var_name = ctx_get_var p.var ctx in
- F.pp_print_string fmt var_name
- | pe :: pl ->
- (* Extract the interior of the projection *)
- extract_projection pl;
- (* Match on the projection element *)
- let def_id =
- match pe.pkind with
- | E.ProjAdt (def_id, None) -> def_id
- | E.ProjAdt (_, Some _) | E.ProjOption _ | E.ProjTuple _ ->
- (* We can't have field accesses on enumerations (variables for
- * the fields are introduced upon the moment we match over the
- * enumeration). We also forbid field access on tuples, because
- * we don't have the syntax to translate that... We thus
- * deconstruct the tuples whenever we need to have access:
- * `let (x, y) = p in ...` *)
- raise (Failure "Unreachable")
- in
- let field_name = ctx_get_field (AdtId def_id) pe.field_id ctx in
- (* We allow to break where the "." appears *)
- F.pp_print_break fmt 0 0;
- F.pp_print_string fmt ".";
- F.pp_print_string fmt field_name
- in
- (* We allow to break where "." appears, but we try to prevent that by
- * wrapping in a box *)
- F.pp_open_hovbox fmt ctx.indent_incr;
- extract_projection p.projection;
- F.pp_close_box fmt ()
-
-(** [inside]: see [extract_ty] *)
-let rec extract_typed_rvalue (ctx : extraction_ctx) (fmt : F.formatter)
- (inside : bool) (v : typed_rvalue) : extraction_ctx =
- match v.value with
- | RvConcrete cv ->
- ctx.fmt.extract_constant_value fmt inside cv;
- ctx
- | RvPlace p ->
- extract_place ctx fmt p;
- ctx
- | RvAdt av ->
- let extract_value ctx inside v = extract_typed_rvalue ctx fmt inside v in
- extract_adt_g_value extract_value fmt ctx inside av.variant_id
- av.field_values v.ty
-
(** [inside]: controls the introduction of parentheses. See [extract_ty]
TODO: replace the formatting boolean [inside] with something more general?
@@ -889,16 +840,17 @@ let rec extract_typed_rvalue (ctx : extraction_ctx) (fmt : F.formatter)
let rec extract_texpression (ctx : extraction_ctx) (fmt : F.formatter)
(inside : bool) (e : texpression) : unit =
match e.e with
- | Value (rv, _) ->
- let _ = extract_typed_rvalue ctx fmt inside rv in
- ()
+ | Local var_id ->
+ let var_name = ctx_get_var var_id ctx in
+ F.pp_print_string fmt var_name
+ | Const cv -> ctx.fmt.extract_constant_value fmt inside cv
| App _ ->
let app, args = destruct_apps e in
extract_App ctx fmt inside app args
| Abs _ ->
let xl, e = destruct_abs_list e in
extract_Abs ctx fmt inside xl e
- | Func _ ->
+ | Qualif _ ->
(* We use the app case *)
extract_App ctx fmt inside e []
| Let (monadic, lv, re, next_e) ->
@@ -908,48 +860,19 @@ let rec extract_texpression (ctx : extraction_ctx) (fmt : F.formatter)
and extract_App (ctx : extraction_ctx) (fmt : F.formatter) (inside : bool)
(app : texpression) (args : texpression list) : unit =
- (* We don't do the same thing if the app is a function identifier or a "regular" expression *)
+ (* We don't do the same thing if the app is a top-level identifier (function,
+ * ADT constructor...) or a "regular" expression *)
match app.e with
- | Func func -> (
- (* Function identifier *)
- match (func.func, args) with
- | Unop unop, [ arg ] ->
- ctx.fmt.extract_unop (extract_texpression ctx fmt) fmt inside unop arg
- | Binop (binop, int_ty), [ arg0; arg1 ] ->
- ctx.fmt.extract_binop
- (extract_texpression ctx fmt)
- fmt inside binop int_ty arg0 arg1
- | Regular (fun_id, rg_id), _ ->
- if inside then F.pp_print_string fmt "(";
- (* Open a box for the function call *)
- F.pp_open_hovbox fmt ctx.indent_incr;
- (* Print the function name *)
- let fun_name = ctx_get_function fun_id rg_id ctx in
- F.pp_print_string fmt fun_name;
- (* Print the type parameters *)
- List.iter
- (fun ty ->
- F.pp_print_space fmt ();
- extract_ty ctx fmt true ty)
- func.type_params;
- (* Print the arguments *)
- List.iter
- (fun ve ->
- F.pp_print_space fmt ();
- extract_texpression ctx fmt true ve)
- args;
- (* Close the box for the function call *)
- F.pp_close_box fmt ();
- (* Return *)
- if inside then F.pp_print_string fmt ")"
- | _ ->
- raise
- (Failure
- ("Unreachable:\n" ^ "Function: " ^ show_fun_id func.func
- ^ ",\nNumber of arguments: "
- ^ string_of_int (List.length args)
- ^ ",\nArguments: "
- ^ String.concat " " (List.map show_texpression args))))
+ | Qualif qualif -> (
+ (* Top-level qualifier *)
+ match qualif.id with
+ | Func fun_id ->
+ extract_function_call ctx fmt inside fun_id qualif.type_params args
+ | AdtCons adt_cons_id ->
+ extract_adt_cons ctx fmt inside adt_cons_id qualif.type_params args
+ | Proj proj ->
+ extract_field_projector ctx fmt inside app proj qualif.type_params
+ args)
| _ ->
(* "Regular" expression *)
(* Open parentheses *)
@@ -970,6 +893,126 @@ and extract_App (ctx : extraction_ctx) (fmt : F.formatter) (inside : bool)
(* Close parentheses *)
if inside then F.pp_print_string fmt ")"
+(** Subcase of the app case: function call *)
+and extract_function_call (ctx : extraction_ctx) (fmt : F.formatter)
+ (inside : bool) (fid : fun_id) (type_args : ty list)
+ (args : texpression list) : unit =
+ match (fid, args) with
+ | Unop unop, [ arg ] ->
+ (* A unop can have *at most* one argument (the result can't be a function!).
+ * Note that the way we generate the translation, we shouldn't get the
+ * case where we have no argument (all functions are fully instantiated,
+ * and no AST transformation introduces partial calls). *)
+ ctx.fmt.extract_unop (extract_texpression ctx fmt) fmt inside unop arg
+ | Binop (binop, int_ty), [ arg0; arg1 ] ->
+ (* Number of arguments: similar to unop *)
+ ctx.fmt.extract_binop
+ (extract_texpression ctx fmt)
+ fmt inside binop int_ty arg0 arg1
+ | Regular (fun_id, rg_id), _ ->
+ if inside then F.pp_print_string fmt "(";
+ (* Open a box for the function call *)
+ F.pp_open_hovbox fmt ctx.indent_incr;
+ (* Print the function name *)
+ let fun_name = ctx_get_function fun_id rg_id ctx in
+ F.pp_print_string fmt fun_name;
+ (* Print the type parameters *)
+ List.iter
+ (fun ty ->
+ F.pp_print_space fmt ();
+ extract_ty ctx fmt true ty)
+ type_args;
+ (* Print the arguments *)
+ List.iter
+ (fun ve ->
+ F.pp_print_space fmt ();
+ extract_texpression ctx fmt true ve)
+ args;
+ (* Close the box for the function call *)
+ F.pp_close_box fmt ();
+ (* Return *)
+ if inside then F.pp_print_string fmt ")"
+ | _ ->
+ raise
+ (Failure
+ ("Unreachable:\n" ^ "Function: " ^ show_fun_id fid
+ ^ ",\nNumber of arguments: "
+ ^ string_of_int (List.length args)
+ ^ ",\nArguments: "
+ ^ String.concat " " (List.map show_texpression args)))
+
+(** Subcase of the app case: ADT constructor *)
+and extract_adt_cons (ctx : extraction_ctx) (fmt : F.formatter) (inside : bool)
+ (adt_cons : adt_cons_id) (type_args : ty list) (args : texpression list) :
+ unit =
+ match adt_cons.adt_id with
+ | Tuple ->
+ (* Tuple *)
+ (* For now, we only support fully applied tuple constructors *)
+ assert (List.length type_args = List.length args);
+ F.pp_print_string fmt "(";
+ Collections.List.iter_link
+ (fun () ->
+ F.pp_print_string fmt ",";
+ F.pp_print_space fmt ())
+ (fun v -> extract_texpression ctx fmt false v)
+ args;
+ F.pp_print_string fmt ")"
+ | _ ->
+ (* "Regular" ADT *)
+ (* We print something of the form: `Cons field0 ... fieldn`.
+ * We could update the code to print something of the form:
+ * `{ field0=...; ...; fieldn=...; }` in case of fully
+ * applied structure constructors.
+ *)
+ let cons =
+ match adt_cons.variant_id with
+ | Some vid -> ctx_get_variant adt_cons.adt_id vid ctx
+ | None -> ctx_get_struct adt_cons.adt_id ctx
+ in
+ let use_parentheses = inside && args <> [] in
+ if use_parentheses then F.pp_print_string fmt "(";
+ F.pp_print_string fmt cons;
+ Collections.List.iter
+ (fun v ->
+ F.pp_print_space fmt ();
+ extract_texpression ctx fmt false v)
+ args;
+ if use_parentheses then F.pp_print_string fmt ")"
+
+(** Subcase of the app case: ADT field projector. *)
+and extract_field_projector (ctx : extraction_ctx) (fmt : F.formatter)
+ (inside : bool) (original_app : texpression) (proj : proj_kind)
+ (_proj_type_params : ty list) (args : texpression list) : unit =
+ (* We isolate the first argument (if there is), in order to pretty print the
+ * projection (`x.field` instead of `MkAdt?.field x` *)
+ match args with
+ | [ arg ] ->
+ (* Exactly one argument: pretty-print *)
+ let field_name = ctx_get_field proj.adt_id proj.field_id ctx in
+ (* Open a box *)
+ F.pp_open_hovbox fmt ctx.indent_incr;
+ (* TODO: parentheses: we do something very crude *)
+ let use_parentheses = not (is_var arg) in
+ if use_parentheses then F.pp_print_string fmt "(";
+ (* Extract the expression *)
+ extract_texpression ctx fmt false arg;
+ (* We allow to break where the "." appears *)
+ F.pp_print_break fmt 0 0;
+ F.pp_print_string fmt ".";
+ F.pp_print_string fmt field_name;
+ (* Close the parentheses *)
+ if use_parentheses then F.pp_print_string fmt ")";
+ (* Close the box *)
+ F.pp_close_box fmt ()
+ | arg :: args ->
+ (* Call extract_App again, but in such a way that the first argument is
+ * isolated *)
+ extract_App ctx fmt inside (mk_app original_app arg) args
+ | [] ->
+ (* No argument: shouldn't happen *)
+ raise (Failure "Unreachable")
+
and extract_Abs (ctx : extraction_ctx) (fmt : F.formatter) (inside : bool)
(xl : typed_lvalue list) (e : texpression) : unit =
(* Open a box for the abs expression *)