Skip to content

Commit e8cb72f

Browse files
authored
Merge pull request #1508 from cryspen/rengine-conform-engine-interface
Rust Engine: turn it into a hax-frontend compatible engine
2 parents c3d7911 + cfb2c6c commit e8cb72f

File tree

22 files changed

+578
-38
lines changed

22 files changed

+578
-38
lines changed

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jobs:
2828
- uses: Swatinem/rust-cache@v2
2929

3030
- name: Test
31-
run: cargo test --workspace --exclude hax-engine-names-extract --verbose
31+
run: cargo test --workspace --exclude hax-engine-names-extract --exclude hax-rust-engine --verbose
3232

3333
- name: Test `hax-frontend-exporter` with feature `rustc` off
3434
run: cargo check -p hax-frontend-exporter --no-default-features --verbose

.utils/rebuild.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ cd_rootwise () {
3131

3232
rust () {
3333
cd_rootwise "cli"
34-
for i in driver subcommands ../engine/names/extract; do
34+
for i in driver subcommands ../engine/names/extract ../rust-engine; do
3535
CURRENT="rust/$i"
3636
cargo install --locked --quiet $OFFLINE_FLAG --debug --path $i
3737
done

Cargo.lock

Lines changed: 60 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cli/subcommands/build.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ fn json_schema_static_asset() {
2424
hax_types::engine_api::protocol::FromEngine,
2525
hax_types::engine_api::protocol::ToEngine,
2626
hax_lib_macros_types::AttrPayload,
27-
hax_rust_engine::ast::Item,
27+
hax_rust_engine::ocaml_engine::Query,
28+
hax_rust_engine::ocaml_engine::Response,
2829
));
2930
schema.schema.metadata.get_or_insert_default().id = Some(hax_types::HAX_VERSION.into());
3031
serde_json::to_writer(

cli/subcommands/src/cargo_hax.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,25 @@ fn find_hax_engine(message_format: MessageFormat) -> process::Command {
125125
})
126126
}
127127

128+
const RUST_ENGINE_BINARY_NAME: &str = "hax-rust-engine";
129+
const RUST_ENGINE_BINARY_NOT_FOUND: &str =
130+
"The binary [hax-rust-engine] was not found in your [PATH].";
131+
132+
#[allow(unused_variables, unreachable_code)]
133+
fn find_rust_hax_engine(message_format: MessageFormat) -> process::Command {
134+
use which::which;
135+
136+
std::env::var("HAX_RUST_BINARY")
137+
.ok()
138+
.map(process::Command::new)
139+
.or_else(|| {
140+
which(RUST_ENGINE_BINARY_NAME)
141+
.ok()
142+
.map(process::Command::new)
143+
})
144+
.expect(RUST_ENGINE_BINARY_NOT_FOUND)
145+
}
146+
128147
use hax_types::diagnostics::message::HaxMessage;
129148
use hax_types::diagnostics::report::ReportCtx;
130149

@@ -245,7 +264,12 @@ fn run_engine(
245264
input: haxmeta.items,
246265
impl_infos: haxmeta.impl_infos,
247266
};
248-
let mut engine_subprocess = find_hax_engine(message_format)
267+
let mut hax_engine_command = if let Backend::Lean { .. } = &engine_options.backend.backend {
268+
find_rust_hax_engine(message_format)
269+
} else {
270+
find_hax_engine(message_format)
271+
};
272+
let mut engine_subprocess = hax_engine_command
249273
.stdin(std::process::Stdio::piped())
250274
.stdout(std::process::Stdio::piped())
251275
.spawn()

engine/bin/lib.ml

Lines changed: 60 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,12 @@ let run (options : Types.engine_options) : Types.output =
140140
| Fstar opts -> run (module Fstar_backend) opts
141141
| Coq -> run (module Coq_backend) ()
142142
| Ssprove -> run (module Ssprove_backend) ()
143-
| Easycrypt -> run (module Easycrypt_backend) ())
143+
| Easycrypt -> run (module Easycrypt_backend) ()
144+
| Lean ->
145+
failwith
146+
"The OCaml hax engine should never be called for lean. The Lean \
147+
backend uses the newer rust engine. Please report this issue on \
148+
our GitHub repository: https://github.com/cryspen/hax.")
144149
in
145150
{
146151
diagnostics = List.map ~f:Diagnostics.to_thir_diagnostic diagnostics;
@@ -181,34 +186,39 @@ let parse_id_table_node (json : Yojson.Safe.t) :
181186
in
182187
(table, value)
183188

184-
let parse_options () =
189+
let load_table ?(check_version = true) : Yojson.Safe.t =
185190
let table, json =
186191
Hax_io.read_json () |> Option.value_exn |> parse_id_table_node
187192
in
188-
let version =
189-
try Yojson.Safe.Util.(member "hax_version" json |> to_string)
190-
with _ -> "unknown"
191-
in
192-
if String.equal version Types.hax_version |> not then (
193-
prerr_endline
194-
[%string
195-
{|
193+
(if check_version then
194+
let version =
195+
try Yojson.Safe.Util.(member "hax_version" json |> to_string)
196+
with _ -> "unknown"
197+
in
198+
if String.equal version Types.hax_version |> not then (
199+
prerr_endline
200+
[%string
201+
{|
196202
The versions of `hax-engine` and of `cargo-hax` are different:
197203
- `hax-engine` version: %{Types.hax_version}
198204
- `cargo-hax` version: %{version}
199205

200206
Please reinstall hax.
201207
|}];
202-
Stdlib.exit 1);
208+
Stdlib.exit 1));
203209
table
204210
|> List.iter ~f:(fun (id, json) ->
205211
Hashtbl.add_exn Types.cache_map ~key:id ~data:(`JSON json));
212+
json
213+
214+
let parse_options () =
215+
let json = load_table ~check_version:true in
206216
let options = [%of_yojson: Types.engine_options] json in
207217
Profiling.enabled := options.backend.profile;
208218
options
209219
210220
(** Entrypoint of the engine. Assumes `Hax_io.init` was called. *)
211-
let main () =
221+
let engine () =
212222
let options = Profiling.profile (Other "parse_options") 1 parse_options in
213223
Printexc.record_backtrace true;
214224
let result =
@@ -240,3 +250,41 @@ let main () =
240250
| Error (exn, bt) ->
241251
Logs.info (fun m -> m "Exiting Hax engine (with an unexpected failure)");
242252
Printexc.raise_with_backtrace exn bt
253+
254+
module ExportRustAst = Export_ast.Make (Features.Rust)
255+
module ExportFStarAst = Export_ast.Make (Fstar_backend.InputLanguage)
256+
257+
(** Entry point for interacting with the Rust hax engine *)
258+
let driver_for_rust_engine () : unit =
259+
let query : Rust_engine_types.query =
260+
(* TODO: support for table *)
261+
(* let json = load_table ~check_version:false in *)
262+
let json = Hax_io.read_json () |> Option.value_exn in
263+
[%of_yojson: Rust_engine_types.query] json
264+
in
265+
Concrete_ident.ImplInfoStore.init
266+
(Concrete_ident_generated.impl_infos @ query.impl_infos);
267+
match query.kind with
268+
| Types.ImportThir { input } ->
269+
let imported_items = import_thir_items [] input in
270+
let imported_items =
271+
(* TODO: this let binding is applying the phases from the F* backend *)
272+
Fstar_backend.apply_phases
273+
{
274+
cli_extension = EmptyStructempty_args_extension;
275+
fuel = Int64.zero;
276+
ifuel = Int64.zero;
277+
interfaces = [];
278+
line_width = 80;
279+
z3rlimit = Int64.zero;
280+
}
281+
imported_items
282+
in
283+
let rust_ast_items =
284+
List.concat_map
285+
~f:(fun item -> ExportFStarAst.ditem item)
286+
imported_items
287+
in
288+
let response = Rust_engine_types.ImportThir { output = rust_ast_items } in
289+
Hax_io.write_json ([%yojson_of: Rust_engine_types.response] response);
290+
Hax_io.write_json ([%yojson_of: Types.from_engine] Exit)

engine/bin/lib.mli

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
val main : unit -> unit
1+
val engine : unit -> unit
2+
val driver_for_rust_engine : unit -> unit

engine/bin/native_driver.ml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,6 @@ let _ =
2020
output_char stdout '\n';
2121
flush stdout
2222
end);
23-
Lib.main ()
23+
match Sys.get_argv () with
24+
| [| _; "driver_rust_engine" |] -> Lib.driver_for_rust_engine ()
25+
| _ -> Lib.engine ()

engine/lib/export_ast.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ module Make (FA : Features.T) = struct
347347
| String s -> B.String (Newtypesymbol s)
348348
| Char c -> B.Char c
349349
| Int { value; negative; kind } ->
350-
B.Int { value; negative; kind = dint_kind kind }
350+
B.Int { value = Newtypesymbol value; negative; kind = dint_kind kind }
351351
| Float { value; negative; kind } ->
352352
B.Float
353353
{ value = Newtypesymbol value; negative; kind = dfloat_kind kind }

hax-types/src/cli_options/mod.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -182,16 +182,20 @@ pub enum Backend<E: Extension> {
182182
Easycrypt,
183183
/// Use the ProVerif backend (warning: work in progress!)
184184
ProVerif(ProVerifOptions),
185+
/// Use the Lean backend (warning: work in progress!)
186+
#[clap(hide = true)]
187+
Lean,
185188
}
186189

187190
impl fmt::Display for Backend<()> {
188191
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
189192
match self {
190-
Backend::Fstar(..) => write!(f, "fstar"),
191-
Backend::Coq => write!(f, "coq"),
192-
Backend::Ssprove => write!(f, "ssprove"),
193-
Backend::Easycrypt => write!(f, "easycrypt"),
194-
Backend::ProVerif(..) => write!(f, "proverif"),
193+
Backend::Fstar { .. } => write!(f, "fstar"),
194+
Backend::Coq { .. } => write!(f, "coq"),
195+
Backend::Ssprove { .. } => write!(f, "ssprove"),
196+
Backend::Easycrypt { .. } => write!(f, "easycrypt"),
197+
Backend::ProVerif { .. } => write!(f, "proverif"),
198+
Backend::Lean { .. } => write!(f, "lean"),
195199
}
196200
}
197201
}

0 commit comments

Comments
 (0)