From 04805e391c77dc05580332203a6ddbb8d3dcf5a3 Mon Sep 17 00:00:00 2001 From: Joe Hellerstein Date: Tue, 28 Apr 2026 17:56:25 -0700 Subject: [PATCH 1/2] feat(hydro_lang): add --graph ir CLI option for IR JSON export - Gate ir_json() on viz feature (serde_json available there) - Add GraphType::Ir variant for CLI: --graph ir -o output.json - BuiltFlow::generate_graph intercepts Ir before delegating to viz --- hydro_lang/src/compile/built.rs | 8 +++++++- hydro_lang/src/viz/api.rs | 1 + hydro_lang/src/viz/config.rs | 3 +++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/hydro_lang/src/compile/built.rs b/hydro_lang/src/compile/built.rs index 6935c2abcc70..3d7036509297 100644 --- a/hydro_lang/src/compile/built.rs +++ b/hydro_lang/src/compile/built.rs @@ -50,7 +50,7 @@ impl<'a> BuiltFlow<'a> { } /// Serialize the IR as JSON. - #[cfg(feature = "runtime_support")] + #[cfg(feature = "viz")] pub fn ir_json(&self) -> Result { super::ir::serialize_dedup_shared(|| serde_json::to_string_pretty(&self.ir)) } @@ -98,6 +98,12 @@ impl<'a> BuiltFlow<'a> { &self, config: &crate::viz::config::GraphConfig, ) -> Result, Box> { + if let Some(crate::viz::config::GraphType::Ir) = config.graph { + let filename = config.output.clone().unwrap_or_else(|| "hydro_ir.json".to_string()); + let json = self.ir_json()?; + std::fs::write(&filename, &json)?; + return Ok(Some(filename)); + } self.graph_api().generate_graph(config) } diff --git a/hydro_lang/src/viz/api.rs b/hydro_lang/src/viz/api.rs index d9cdb3b41c52..8824b8807dad 100644 --- a/hydro_lang/src/viz/api.rs +++ b/hydro_lang/src/viz/api.rs @@ -40,6 +40,7 @@ impl<'a> GraphApi<'a> { crate::viz::config::GraphType::Mermaid => render_hydro_ir_mermaid(self.ir, config), crate::viz::config::GraphType::Dot => render_hydro_ir_dot(self.ir, config), crate::viz::config::GraphType::Json => render_hydro_ir_json(self.ir, config), + crate::viz::config::GraphType::Ir => panic!("Ir format handled by BuiltFlow::generate_graph"), } } diff --git a/hydro_lang/src/viz/config.rs b/hydro_lang/src/viz/config.rs index cab480942b75..45516dcb62a6 100644 --- a/hydro_lang/src/viz/config.rs +++ b/hydro_lang/src/viz/config.rs @@ -9,6 +9,8 @@ pub enum GraphType { Dot, /// JSON format for Hydroscope interactive viewer. Json, + /// Serialized IR JSON for standalone coordination analysis. + Ir, } impl GraphType { @@ -18,6 +20,7 @@ impl GraphType { GraphType::Mermaid => "mmd", GraphType::Dot => "dot", GraphType::Json => "json", + GraphType::Ir => "json", } } } From 879a685f1111083c9ea0070cdb3d454e7f9c067e Mon Sep 17 00:00:00 2001 From: Joe Hellerstein Date: Thu, 30 Apr 2026 17:59:14 -0700 Subject: [PATCH 2/2] fix(viz): handle Ir format in GraphApi instead of panicking - Move IR serialization into GraphApi::render so all code paths work - Remove special-case in BuiltFlow::generate_graph (now just delegates) - Use .ir.json extension to distinguish from Hydroscope .json format --- hydro_lang/src/compile/built.rs | 6 ------ hydro_lang/src/viz/api.rs | 6 +++++- hydro_lang/src/viz/config.rs | 2 +- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/hydro_lang/src/compile/built.rs b/hydro_lang/src/compile/built.rs index 3d7036509297..8f4dc09b22cb 100644 --- a/hydro_lang/src/compile/built.rs +++ b/hydro_lang/src/compile/built.rs @@ -98,12 +98,6 @@ impl<'a> BuiltFlow<'a> { &self, config: &crate::viz::config::GraphConfig, ) -> Result, Box> { - if let Some(crate::viz::config::GraphType::Ir) = config.graph { - let filename = config.output.clone().unwrap_or_else(|| "hydro_ir.json".to_string()); - let json = self.ir_json()?; - std::fs::write(&filename, &json)?; - return Ok(Some(filename)); - } self.graph_api().generate_graph(config) } diff --git a/hydro_lang/src/viz/api.rs b/hydro_lang/src/viz/api.rs index 8824b8807dad..39a9533109ed 100644 --- a/hydro_lang/src/viz/api.rs +++ b/hydro_lang/src/viz/api.rs @@ -40,7 +40,11 @@ impl<'a> GraphApi<'a> { crate::viz::config::GraphType::Mermaid => render_hydro_ir_mermaid(self.ir, config), crate::viz::config::GraphType::Dot => render_hydro_ir_dot(self.ir, config), crate::viz::config::GraphType::Json => render_hydro_ir_json(self.ir, config), - crate::viz::config::GraphType::Ir => panic!("Ir format handled by BuiltFlow::generate_graph"), + crate::viz::config::GraphType::Ir => { + crate::compile::ir::serialize_dedup_shared(|| { + serde_json::to_string_pretty(self.ir).expect("failed to serialize IR") + }) + } } } diff --git a/hydro_lang/src/viz/config.rs b/hydro_lang/src/viz/config.rs index 45516dcb62a6..da5e8ae5e518 100644 --- a/hydro_lang/src/viz/config.rs +++ b/hydro_lang/src/viz/config.rs @@ -20,7 +20,7 @@ impl GraphType { GraphType::Mermaid => "mmd", GraphType::Dot => "dot", GraphType::Json => "json", - GraphType::Ir => "json", + GraphType::Ir => "ir.json", } } }