Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Opaque extensions #1134

Merged
merged 17 commits into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions engine/backends/fstar/fstar_ast.ml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module Ident = FStar_Ident

let dummyRange = Range.dummyRange
let id ident = Ident.mk_ident (ident, dummyRange)
let id_prime (ident : Ident.ident) = id (ident.idText ^ "'")

let lid path =
let init, last = List.(drop_last_exn path, last_exn path) in
Expand Down Expand Up @@ -87,6 +88,7 @@ let mk_refined (x : string) (typ : AST.term) (phi : x:AST.term -> AST.term) =
term @@ AST.Refine (x_bd, phi (term @@ AST.Var (lid_of_id x)))

let type0_term = AST.Name (lid [ "Type0" ]) |> term
let eqtype_term = AST.Name (lid [ "eqtype" ]) |> term

let parse_string f s =
let open FStar_Parser_ParseIt in
Expand Down
132 changes: 71 additions & 61 deletions engine/backends/fstar/fstar_backend.ml
Original file line number Diff line number Diff line change
Expand Up @@ -875,6 +875,34 @@ struct
| `VerbatimIntf of string * [ `NoNewline | `Newline ]
| `Comment of string ]
list =
let is_erased =
Attrs.find_unique_attr e.attrs
~f:([%eq: Types.ha_payload] Erased >> Fn.flip Option.some_if ())
|> Option.is_some
in
let erased_impl name ty attrs binders =
let name' = F.id_prime name in
let pat = F.AST.PatVar (name, None, []) in
let term = F.term @@ F.AST.Var (F.lid_of_id @@ name') in
let pat, term =
match binders with
| [] -> (pat, term)
| _ ->
( F.AST.PatApp
(F.pat pat, List.map ~f:FStarBinder.to_pattern binders),
List.fold_left binders ~init:term ~f:(fun term binder ->
let binder_term, binder_imp =
FStarBinder.to_qualified_term binder
in
F.term @@ F.AST.App (term, binder_term, binder_imp)) )
in
[
F.decl ~quals:[ Assumption ] ~fsti:false ~attrs
@@ F.AST.Assume (name', ty);
F.decl ~fsti:false
@@ F.AST.TopLevelLet (NoLetQualifier, [ (F.pat @@ pat, term) ]);
]
in
match e.v with
| Alias { name; item } ->
(* These should come from bundled items (in the case of cyclic module dependencies).
Expand Down Expand Up @@ -939,7 +967,12 @@ struct
in

let intf = F.decl ~fsti:true (F.AST.Val (name, arrow_typ)) in
if interface_mode then [ impl; intf ] else [ full ]

let erased = erased_impl name arrow_typ [] generics in
let impl, full =
if is_erased then (erased, erased) else ([ impl ], [ full ])
in
if interface_mode then intf :: impl else full
| TyAlias { name; generics; ty } ->
let pat =
F.pat
Expand Down Expand Up @@ -972,31 +1005,20 @@ struct
|> List.map ~f:to_pattern) ),
ty );
] )
| Type { name; generics; _ }
when Attrs.find_unique_attr e.attrs
~f:([%eq: Types.ha_payload] OpaqueType >> Fn.flip Option.some_if ())
|> Option.is_some ->
if not ctx.interface_mode then
Error.raise
@@ {
kind =
AttributeRejected
{
reason =
"a type cannot be opaque if its module is not extracted \
as an interface";
};
span = e.span;
}
else
let generics = FStarBinder.of_generics e.span generics in
let ty = F.type0_term in
let arrow_typ =
F.term
@@ F.AST.Product (List.map ~f:FStarBinder.to_binder generics, ty)
in
let name = F.id @@ U.Concrete_ident_view.to_definition_name name in
[ F.decl ~fsti:true (F.AST.Val (name, arrow_typ)) ]
| Type { name; generics; _ } when is_erased ->
let generics =
FStarBinder.of_generics e.span generics
|> List.map ~f:FStarBinder.implicit_to_explicit
in
let ty = F.eqtype_term in
let arrow_typ =
F.term
@@ F.AST.Product (List.map ~f:FStarBinder.to_binder generics, ty)
in
let name = F.id @@ U.Concrete_ident_view.to_definition_name name in
let erased = erased_impl name arrow_typ [] generics in
let intf = F.decl ~fsti:true (F.AST.Val (name, arrow_typ)) in
if ctx.interface_mode then intf :: erased else erased
| Type
{
name;
Expand Down Expand Up @@ -1476,15 +1498,20 @@ struct
List.exists items ~f:(fun { ii_v; _ } ->
match ii_v with IIType _ -> true | _ -> false)
in
let impl_val = ctx.interface_mode && not has_type in
let let_impl = F.AST.TopLevelLet (NoLetQualifier, [ (pat, body) ]) in
if impl_val then
let generics_binders = List.map ~f:FStarBinder.to_binder generics in
let val_type = F.term @@ F.AST.Product (generics_binders, typ) in
let v = F.AST.Val (name, val_type) in
(F.decls ~fsti:true ~attrs:[ tcinst ] @@ v)
@ F.decls ~fsti:false ~attrs:[ tcinst ] let_impl
else F.decls ~fsti:ctx.interface_mode ~attrs:[ tcinst ] let_impl
let generics_binders = List.map ~f:FStarBinder.to_binder generics in
let val_type = F.term @@ F.AST.Product (generics_binders, typ) in
let v = F.AST.Val (name, val_type) in
let intf = F.decls ~fsti:true ~attrs:[ tcinst ] v in
let impl =
if is_erased then erased_impl name val_type [ tcinst ] generics
else
F.decls
~fsti:(ctx.interface_mode && has_type)
~attrs:[ tcinst ] let_impl
in
let intf = if has_type && not is_erased then [] else intf in
if ctx.interface_mode then intf @ impl else impl
| Quote { quote; _ } ->
let fstar_opts =
Attrs.find_unique_attr e.attrs ~f:(function
Expand Down Expand Up @@ -1530,8 +1557,7 @@ let make (module M : Attrs.WITH_ITEMS) ctx =
let ctx = ctx
end) : S)

let strings_of_item ~signature_only (bo : BackendOptions.t) m items
(item : item) :
let strings_of_item (bo : BackendOptions.t) m items (item : item) :
([> `Impl of string | `Intf of string ] * [ `NoNewline | `Newline ]) list =
let interface_mode' : Types.inclusion_kind =
List.rev bo.interfaces
Expand All @@ -1549,8 +1575,7 @@ let strings_of_item ~signature_only (bo : BackendOptions.t) m items
|> Option.value ~default:(Types.Excluded : Types.inclusion_kind)
in
let interface_mode =
signature_only
|| not ([%matches? (Types.Excluded : Types.inclusion_kind)] interface_mode')
not ([%matches? (Types.Excluded : Types.inclusion_kind)] interface_mode')
in
let (module Print) =
make m
Expand All @@ -1561,30 +1586,27 @@ let strings_of_item ~signature_only (bo : BackendOptions.t) m items
line_width = bo.line_width;
}
in
let mk_impl = if interface_mode then fun i -> `Impl i else fun i -> `Impl i in
let mk_impl i = `Impl i in
let mk_intf = if interface_mode then fun i -> `Intf i else fun i -> `Impl i in
let no_impl =
signature_only
|| [%matches? (Types.Included None' : Types.inclusion_kind)] interface_mode'
[%matches? (Types.Included None' : Types.inclusion_kind)] interface_mode'
in
Print.pitem item
|> List.filter ~f:(function `Impl _ when no_impl -> false | _ -> true)
|> List.concat_map ~f:(function
| `Impl i -> [ (mk_impl (Print.decl_to_string i), `Newline) ]
| `Intf i -> [ (mk_intf (Print.decl_to_string i), `Newline) ]
| `VerbatimIntf (s, nl) ->
[ ((if interface_mode then `Intf s else `Impl s), nl) ]
| `VerbatimImpl (s, nl) ->
[ ((if interface_mode then `Impl s else `Impl s), nl) ]
| `VerbatimIntf (s, nl) -> [ (mk_intf s, nl) ]
| `VerbatimImpl (s, nl) -> [ (`Impl s, nl) ]
| `Comment s ->
let s = "(* " ^ s ^ " *)" in
if interface_mode then [ (`Impl s, `Newline); (`Intf s, `Newline) ]
else [ (`Impl s, `Newline) ])

type rec_prefix = NonRec | FirstMutRec | MutRec

let string_of_items ~signature_only ~mod_name ~bundles (bo : BackendOptions.t) m
items : string * string =
let string_of_items ~mod_name ~bundles (bo : BackendOptions.t) m items :
string * string =
let collect_trait_goal_idents =
object
inherit [_] Visitors.reduce as super
Expand Down Expand Up @@ -1657,7 +1679,7 @@ let string_of_items ~signature_only ~mod_name ~bundles (bo : BackendOptions.t) m
List.concat_map
~f:(fun item ->
let recursivity_prefix = get_recursivity_prefix item in
let strs = strings_of_item ~signature_only bo m items item in
let strs = strings_of_item bo m items item in
match (recursivity_prefix, item.v) with
| FirstMutRec, Fn _ ->
replace_in_strs ~pattern:"let" ~with_:"let rec" strs
Expand Down Expand Up @@ -1710,20 +1732,8 @@ let translate_as_fstar m (bo : BackendOptions.t) ~(bundles : AST.item list list)
U.group_items_by_namespace items
|> Map.to_alist
|> List.concat_map ~f:(fun (ns, items) ->
let signature_only =
let is_dropped_body =
Concrete_ident.eq_name Rust_primitives__hax__dropped_body
in
let contains_dropped_body =
U.Reducers.collect_concrete_idents#visit_item ()
>> Set.exists ~f:is_dropped_body
in
List.exists ~f:contains_dropped_body items
in
let mod_name = module_name ns in
let impl, intf =
string_of_items ~signature_only ~mod_name ~bundles bo m items
in
let impl, intf = string_of_items ~mod_name ~bundles bo m items in
let make ~ext body =
if String.is_empty body then None
else
Expand Down
3 changes: 1 addition & 2 deletions engine/backends/proverif/proverif_backend.ml
Original file line number Diff line number Diff line change
Expand Up @@ -630,8 +630,7 @@ module Make (Options : OPTS) : MAKE = struct
if
Attrs.find_unique_attr item.attrs
~f:
([%eq: Types.ha_payload] OpaqueType
>> Fn.flip Option.some_if ())
([%eq: Types.ha_payload] Erased >> Fn.flip Option.some_if ())
|> Option.is_some
then default_lines
else default_lines ^^ destructor_lines
Expand Down
4 changes: 2 additions & 2 deletions engine/bin/lib.ml
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,14 @@ let import_thir_items (include_clauses : Types.inclusion_clause list)
include_clauses
|> List.last
in
let drop_body =
let type_only =
(* Shall we drop the body? *)
Option.map
~f:(fun clause -> [%matches? Types.SignatureOnly] clause.kind)
most_precise_clause
|> Option.value ~default:false
in
Import_thir.import_item ~drop_body item)
Import_thir.import_item ~type_only item)
items
|> List.map ~f:snd
in
Expand Down
Loading
Loading