hax_rust_engine/
ocaml_engine.rs1use std::{io::BufRead, sync::OnceLock};
6
7use hax_frontend_exporter::{
8 ThirBody,
9 id_table::{Table, WithTable},
10};
11use hax_types::engine_api::protocol::{FromEngine, ToEngine};
12use serde::Deserialize;
13
14#[derive(Debug, Clone, ::schemars::JsonSchema, ::serde::Deserialize, ::serde::Serialize)]
16pub struct Query {
17 #[serde(flatten)]
18 meta: Meta,
19 kind: QueryKind,
21}
22
23#[derive(Debug, Clone, ::schemars::JsonSchema, ::serde::Deserialize, ::serde::Serialize)]
25pub struct Meta {
26 pub hax_version: String,
28 pub impl_infos: Vec<(
30 hax_frontend_exporter::DefId,
31 hax_frontend_exporter::ImplInfos,
32 )>,
33 pub debug_bind_phase: bool,
35 pub profiling: bool,
37}
38
39static STATE: OnceLock<Meta> = OnceLock::new();
40
41pub fn initialize(meta: Meta) {
43 STATE
44 .set(meta)
45 .expect("`ocaml_engine::initialize` was called more than once")
46}
47
48#[derive(Debug, Clone, ::schemars::JsonSchema, ::serde::Deserialize, ::serde::Serialize)]
51pub enum QueryKind {
52 ImportThir {
54 input: Vec<hax_frontend_exporter::Item<ThirBody>>,
56 translation_options: hax_types::cli_options::TranslationOptions,
58 },
59
60 ApplyPhases {
62 phases: Vec<String>,
64 input: Vec<crate::ast::Item>,
66 },
67
68 Print {
70 printer: hax_types::cli_options::Backend<()>,
72 input: Vec<crate::ast::Item>,
74 },
75}
76#[derive(Debug, Clone, ::schemars::JsonSchema, ::serde::Deserialize, ::serde::Serialize)]
78pub enum Response {
79 ImportThir {
81 output: Vec<crate::ast::Item>,
83 },
84 ApplyPhases {
86 output: Vec<crate::ast::Item>,
88 },
89 PrintOk,
91}
92
93#[derive(Debug, Clone, ::schemars::JsonSchema, ::serde::Deserialize, ::serde::Serialize)]
95#[serde(untagged)]
96pub enum ExtendedFromEngine {
97 FromEngine(FromEngine),
99 Response(Response),
101}
102
103impl QueryKind {
104 pub fn execute(self, table: Option<Table>) -> Option<Response> {
106 let query = Query {
107 meta: STATE
108 .get()
109 .expect("`ocaml_engine::initialize` should be called first")
110 .clone(),
111 kind: self,
112 };
113 use std::io::Write;
114 use std::process::Command;
115
116 macro_rules! send {
117 ($where: expr, $value:expr) => {
118 serde_json::to_writer(&mut $where, $value).unwrap();
119 $where.write_all(b"\n").unwrap();
120 $where.flush().unwrap();
121 };
122 }
123
124 let mut engine_subprocess =
125 Command::new(std::env::var("HAX_ENGINE_BINARY").unwrap_or("hax-engine".into()))
126 .arg("driver_rust_engine")
127 .stdin(std::process::Stdio::piped())
128 .stdout(std::process::Stdio::piped())
129 .spawn()
130 .unwrap();
131
132 let mut stdin = std::io::BufWriter::new(
133 engine_subprocess
134 .stdin
135 .as_mut()
136 .expect("Could not write on stdin"),
137 );
138
139 if let Some(table) = table {
140 WithTable::run(table, query, |with_table| {
141 send!(stdin, with_table);
142 });
143 } else {
144 send!(stdin, &(vec![] as Vec<()>, query));
145 }
146
147 let mut response = None;
148 let stdout = std::io::BufReader::new(engine_subprocess.stdout.take().unwrap());
149 for slice in stdout.split(b'\n') {
152 let msg = (|| {
153 let slice = slice.ok()?;
154 let mut de = serde_json::Deserializer::from_slice(&slice);
155 de.disable_recursion_limit();
156 let de = serde_stacker::Deserializer::new(&mut de);
157 let msg = ExtendedFromEngine::deserialize(de);
158 msg.ok()
159 })()
160 .expect(
161 "Hax engine sent an invalid json value. \
162 This might be caused by debug messages on stdout, \
163 which is reserved for JSON communication with cargo-hax",
164 );
165
166 match msg {
167 ExtendedFromEngine::Response(res) => response = Some(res),
168 ExtendedFromEngine::FromEngine(FromEngine::Exit) => break,
169 ExtendedFromEngine::FromEngine(from_engine) => {
171 crate::hax_io::write(&from_engine);
172 if from_engine.requires_response() {
173 let response: ToEngine = crate::hax_io::read_to_engine_message();
174 send!(stdin, &response);
175 }
176 }
177 }
178 }
179 drop(stdin);
180
181 let exit_status = engine_subprocess.wait().unwrap();
182 if !exit_status.success() {
183 panic!("ocaml engine crashed");
184 }
185
186 response
187 }
188}