diff --git a/hydro_deploy/hydroflow_plus_cli_integration/src/deploy.rs b/hydro_deploy/hydroflow_plus_cli_integration/src/deploy.rs index 2f0d863ac20a..c165cbf3c24a 100644 --- a/hydro_deploy/hydroflow_plus_cli_integration/src/deploy.rs +++ b/hydro_deploy/hydroflow_plus_cli_integration/src/deploy.rs @@ -10,7 +10,7 @@ use hydro_deploy::hydroflow_crate::ports::{ }; use hydro_deploy::hydroflow_crate::HydroflowCrateService; use hydro_deploy::{Deployment, Host}; -use hydroflow_plus::builder::Builders; +use hydroflow_plus::ir::HfPlusLeaf; use hydroflow_plus::location::{ Cluster, ClusterSpec, Deploy, HfSendManyToMany, HfSendManyToOne, HfSendOneToMany, HfSendOneToOne, Location, ProcessSpec, @@ -70,6 +70,7 @@ pub trait DeployCrateWrapper { pub struct DeployNode<'a> { id: usize, builder: &'a FlowBuilder<'a, HydroDeploy>, + cycle_counter: Rc>, next_port: Rc>, underlying: Arc>, } @@ -118,8 +119,12 @@ impl<'a> Location<'a> for DeployNode<'a> { self.id } - fn flow_builder(&self) -> (&'a RefCell, &'a Builders) { - self.builder.builder_components() + fn ir_leaves(&self) -> &'a RefCell> { + self.builder.ir_leaves() + } + + fn cycle_counter(&self) -> &RefCell { + self.cycle_counter.as_ref() } fn next_port(&self) -> DeployPort { @@ -156,6 +161,7 @@ impl DeployCrateWrapper for DeployClusterNode { pub struct DeployCluster<'a> { id: usize, builder: &'a FlowBuilder<'a, HydroDeploy>, + cycle_counter: Rc>, next_port: Rc>, pub members: Vec, } @@ -168,8 +174,12 @@ impl<'a> Location<'a> for DeployCluster<'a> { self.id } - fn flow_builder(&self) -> (&'a RefCell, &'a Builders) { - self.builder.builder_components() + fn ir_leaves(&self) -> &'a RefCell> { + self.builder.ir_leaves() + } + + fn cycle_counter(&self) -> &RefCell { + self.cycle_counter.as_ref() } fn next_port(&self) -> DeployPort { @@ -223,15 +233,12 @@ impl<'a> HfSendOneToOne<'a, DeployNode<'a>> for DeployNode<'a> { source_port.send_to(&mut recipient_port); } - fn gen_sink_statement(&self, _port: &Self::Port) -> hydroflow_plus::lang::parse::Pipeline { - parse_quote!(null()) + fn gen_sink_statement(&self, _port: &Self::Port) -> syn::Expr { + parse_quote!(null) } - fn gen_source_statement( - _other: &DeployNode<'a>, - _port: &Self::Port, - ) -> hydroflow_plus::lang::parse::Pipeline { - parse_quote!(null()) + fn gen_source_statement(_other: &DeployNode<'a>, _port: &Self::Port) -> syn::Expr { + parse_quote!(null) } } @@ -264,15 +271,15 @@ impl<'a> HfSendManyToOne<'a, DeployNode<'a>> for DeployCluster<'a> { } } - fn gen_sink_statement(&self, _port: &Self::Port) -> hydroflow_plus::lang::parse::Pipeline { - parse_quote!(null()) + fn gen_sink_statement(&self, _port: &Self::Port) -> syn::Expr { + parse_quote!(null) } fn gen_source_statement( _other: &DeployNode<'a>, _port: &DeployPort>, - ) -> hydroflow_plus::lang::parse::Pipeline { - parse_quote!(null()) + ) -> syn::Expr { + parse_quote!(null) } } @@ -309,15 +316,15 @@ impl<'a> HfSendOneToMany<'a, DeployCluster<'a>> for DeployNode<'a> { source_port.send_to(&mut recipient_port); } - fn gen_sink_statement(&self, _port: &Self::Port) -> hydroflow_plus::lang::parse::Pipeline { - parse_quote!(null()) + fn gen_sink_statement(&self, _port: &Self::Port) -> syn::Expr { + parse_quote!(null) } fn gen_source_statement( _other: &DeployCluster<'a>, _port: &DeployPort>, - ) -> hydroflow_plus::lang::parse::Pipeline { - parse_quote!(null()) + ) -> syn::Expr { + parse_quote!(null) } } @@ -362,15 +369,15 @@ impl<'a> HfSendManyToMany<'a, DeployCluster<'a>> for DeployCluster<'a> { } } - fn gen_sink_statement(&self, _port: &Self::Port) -> hydroflow_plus::lang::parse::Pipeline { - parse_quote!(null()) + fn gen_sink_statement(&self, _port: &Self::Port) -> syn::Expr { + parse_quote!(null) } fn gen_source_statement( _other: &DeployCluster<'a>, _port: &DeployPort>, - ) -> hydroflow_plus::lang::parse::Pipeline { - parse_quote!(null()) + ) -> syn::Expr { + parse_quote!(null) } } @@ -394,6 +401,7 @@ impl<'a: 'b, 'b> ProcessSpec<'a, HydroDeploy> for DeployProcessSpec<'b> { DeployNode { id, builder, + cycle_counter: Rc::new(RefCell::new(0)), next_port: Rc::new(RefCell::new(0)), underlying: (self.0.borrow_mut())(), } @@ -423,6 +431,7 @@ impl<'a: 'b, 'b> ClusterSpec<'a, HydroDeploy> for DeployClusterSpec<'b> { DeployCluster { id, builder, + cycle_counter: Rc::new(RefCell::new(0)), next_port: Rc::new(RefCell::new(0)), members: cluster_nodes .into_iter() diff --git a/hydro_deploy/hydroflow_plus_cli_integration/src/runtime.rs b/hydro_deploy/hydroflow_plus_cli_integration/src/runtime.rs index 6f2b00a3b170..9a9b554375ce 100644 --- a/hydro_deploy/hydroflow_plus_cli_integration/src/runtime.rs +++ b/hydro_deploy/hydroflow_plus_cli_integration/src/runtime.rs @@ -1,7 +1,7 @@ use std::cell::RefCell; use std::rc::Rc; -use hydroflow_plus::lang::parse::Pipeline; +use hydroflow_plus::ir::HfPlusLeaf; use hydroflow_plus::location::{ Cluster, ClusterSpec, Deploy, HfSendManyToMany, HfSendManyToOne, HfSendOneToMany, HfSendOneToOne, Location, ProcessSpec, @@ -11,7 +11,6 @@ use hydroflow_plus::util::cli::{ }; use hydroflow_plus::FlowBuilder; use stageleft::{q, Quoted, RuntimeData}; -use syn::parse_quote; use super::HydroflowPlusMeta; @@ -30,6 +29,7 @@ impl<'a> Deploy<'a> for CLIRuntime { pub struct CLIRuntimeNode<'a> { id: usize, builder: &'a FlowBuilder<'a, CLIRuntime>, + cycle_counter: Rc>, next_port: Rc>, cli: RuntimeData<&'a HydroCLI>, } @@ -42,8 +42,12 @@ impl<'a> Location<'a> for CLIRuntimeNode<'a> { self.id } - fn flow_builder(&self) -> (&'a RefCell, &'a hydroflow_plus::builder::Builders) { - self.builder.builder_components() + fn ir_leaves(&self) -> &'a RefCell> { + self.builder.ir_leaves() + } + + fn cycle_counter(&self) -> &RefCell { + self.cycle_counter.as_ref() } fn next_port(&self) -> String { @@ -59,6 +63,7 @@ impl<'a> Location<'a> for CLIRuntimeNode<'a> { pub struct CLIRuntimeCluster<'a> { id: usize, builder: &'a FlowBuilder<'a, CLIRuntime>, + cycle_counter: Rc>, next_port: Rc>, cli: RuntimeData<&'a HydroCLI>, } @@ -71,8 +76,12 @@ impl<'a> Location<'a> for CLIRuntimeCluster<'a> { self.id } - fn flow_builder(&self) -> (&'a RefCell, &'a hydroflow_plus::builder::Builders) { - self.builder.builder_components() + fn ir_leaves(&self) -> &'a RefCell> { + self.builder.ir_leaves() + } + + fn cycle_counter(&self) -> &RefCell { + self.cycle_counter.as_ref() } fn next_port(&self) -> String { @@ -95,64 +104,56 @@ impl<'a> Cluster<'a> for CLIRuntimeCluster<'a> { impl<'a> HfSendOneToOne<'a, CLIRuntimeNode<'a>> for CLIRuntimeNode<'a> { fn connect(&self, _other: &CLIRuntimeNode, _source_port: &String, _recipient_port: &String) {} - fn gen_sink_statement(&self, port: &String) -> Pipeline { + fn gen_sink_statement(&self, port: &String) -> syn::Expr { let self_cli = self.cli; let port = port.as_str(); - let sink_quote = q!({ + q!({ self_cli .port(port) .connect_local_blocking::() .into_sink() }) - .splice(); - - parse_quote!(dest_sink(#sink_quote)) + .splice() } - fn gen_source_statement(other: &CLIRuntimeNode<'a>, port: &String) -> Pipeline { + fn gen_source_statement(other: &CLIRuntimeNode<'a>, port: &String) -> syn::Expr { let self_cli = other.cli; let port = port.as_str(); - let source_quote = q!({ + q!({ self_cli .port(port) .connect_local_blocking::() .into_source() }) - .splice(); - - parse_quote!(source_stream(#source_quote)) + .splice() } } impl<'a> HfSendManyToOne<'a, CLIRuntimeNode<'a>> for CLIRuntimeCluster<'a> { fn connect(&self, _other: &CLIRuntimeNode, _source_port: &String, _recipient_port: &String) {} - fn gen_sink_statement(&self, port: &String) -> Pipeline { + fn gen_sink_statement(&self, port: &String) -> syn::Expr { let self_cli = self.cli; let port = port.as_str(); - let sink_quote = q!({ + q!({ self_cli .port(port) .connect_local_blocking::() .into_sink() }) - .splice(); - - parse_quote!(dest_sink(#sink_quote)) + .splice() } - fn gen_source_statement(other: &CLIRuntimeNode<'a>, port: &String) -> Pipeline { + fn gen_source_statement(other: &CLIRuntimeNode<'a>, port: &String) -> syn::Expr { let self_cli = other.cli; let port = port.as_str(); - let source_quote = q!({ + q!({ self_cli .port(port) .connect_local_blocking::>() .into_source() }) - .splice(); - - parse_quote!(source_stream(#source_quote)) + .splice() } } @@ -160,34 +161,30 @@ impl<'a> HfSendOneToMany<'a, CLIRuntimeCluster<'a>> for CLIRuntimeNode<'a> { fn connect(&self, _other: &CLIRuntimeCluster, _source_port: &String, _recipient_port: &String) { } - fn gen_sink_statement(&self, port: &String) -> Pipeline { + fn gen_sink_statement(&self, port: &String) -> syn::Expr { let self_cli = self.cli; let port = port.as_str(); - let sink_quote = q!({ + q!({ self_cli .port(port) .connect_local_blocking::>() .into_sink() }) - .splice(); - - parse_quote!(dest_sink(#sink_quote)) + .splice() } - fn gen_source_statement(other: &CLIRuntimeCluster<'a>, port: &String) -> Pipeline { + fn gen_source_statement(other: &CLIRuntimeCluster<'a>, port: &String) -> syn::Expr { let self_cli = other.cli; let port = port.as_str(); - let source_quote = q!({ + q!({ self_cli .port(port) .connect_local_blocking::() .into_source() }) - .splice(); - - parse_quote!(source_stream(#source_quote)) + .splice() } } @@ -195,34 +192,30 @@ impl<'a> HfSendManyToMany<'a, CLIRuntimeCluster<'a>> for CLIRuntimeCluster<'a> { fn connect(&self, _other: &CLIRuntimeCluster, _source_port: &String, _recipient_port: &String) { } - fn gen_sink_statement(&self, port: &String) -> Pipeline { + fn gen_sink_statement(&self, port: &String) -> syn::Expr { let self_cli = self.cli; let port = port.as_str(); - let sink_quote = q!({ + q!({ self_cli .port(port) .connect_local_blocking::>() .into_sink() }) - .splice(); - - parse_quote!(dest_sink(#sink_quote)) + .splice() } - fn gen_source_statement(other: &CLIRuntimeCluster<'a>, port: &String) -> Pipeline { + fn gen_source_statement(other: &CLIRuntimeCluster<'a>, port: &String) -> syn::Expr { let self_cli = other.cli; let port = port.as_str(); - let source_quote = q!({ + q!({ self_cli .port(port) .connect_local_blocking::>() .into_source() }) - .splice(); - - parse_quote!(source_stream(#source_quote)) + .splice() } } @@ -236,6 +229,7 @@ impl<'cli> ProcessSpec<'cli, CLIRuntime> for RuntimeData<&'cli HydroCLI ClusterSpec<'cli, CLIRuntime> for RuntimeData<&'cli HydroCLI), Name(Ported), @@ -204,7 +205,7 @@ impl ToTokens for Pipeline { } } -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct Import { pub import: Ident, pub bang: Token![!], @@ -236,7 +237,7 @@ impl ToTokens for Import { } } -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct Ported { pub inn: Option, pub inner: Inner, @@ -274,7 +275,7 @@ where } } -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct PipelineParen { pub paren_token: Paren, pub pipeline: Box, @@ -298,7 +299,7 @@ impl ToTokens for PipelineParen { } } -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct PipelineLink { pub lhs: Box, pub arrow: Token![->], @@ -321,7 +322,7 @@ impl ToTokens for PipelineLink { } } -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct Indexing { pub bracket_token: Bracket, pub index: PortIndex, @@ -375,12 +376,13 @@ impl ToTokens for PortIndex { } } -#[derive(Clone, Debug)] +#[derive(Clone)] pub struct Operator { pub path: Path, pub paren_token: Paren, pub args: Punctuated, } + impl Operator { pub fn name(&self) -> Path { Path { @@ -462,6 +464,7 @@ impl Parse for Operator { }) } } + impl ToTokens for Operator { fn to_tokens(&self, tokens: &mut TokenStream) { self.path.to_tokens(tokens); @@ -471,6 +474,22 @@ impl ToTokens for Operator { } } +impl Debug for Operator { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Operator") + .field("path", &self.path.to_token_stream().to_string()) + .field( + "args", + &self + .args + .iter() + .map(|a| a.to_token_stream().to_string()) + .collect::>(), + ) + .finish() + } +} + #[derive(Clone, Copy, Debug)] pub struct IndexInt { pub value: isize, diff --git a/hydroflow_plus/src/builder.rs b/hydroflow_plus/src/builder.rs index 50323179827b..ffbe732bd647 100644 --- a/hydroflow_plus/src/builder.rs +++ b/hydroflow_plus/src/builder.rs @@ -1,23 +1,21 @@ -use std::cell::RefCell; -use std::collections::BTreeMap; +use std::cell::{Ref, RefCell}; +use std::collections::{BTreeMap, HashMap}; use std::marker::PhantomData; use hydroflow_lang::graph::{ - eliminate_extra_unions_tees, partition_graph, propagate_flow_props, FlatGraphBuilder, + eliminate_extra_unions_tees, partition_graph, propagate_flow_props, HydroflowGraph, }; use proc_macro2::{Span, TokenStream}; use quote::quote; use stageleft::{Quoted, QuotedContext}; use syn::parse_quote; +use crate::ir::HfPlusLeaf; use crate::location::{ClusterSpec, LocalDeploy, Location, ProcessSpec}; use crate::{HfBuilt, RuntimeContext}; -pub type Builders = RefCell>>; - pub struct FlowBuilder<'a, D: LocalDeploy<'a> + ?Sized> { - pub(crate) next_id: RefCell, - pub(crate) builders: Builders, + ir_leaves: RefCell>, nodes: RefCell>, clusters: RefCell>, @@ -31,6 +29,12 @@ pub struct FlowBuilder<'a, D: LocalDeploy<'a> + ?Sized> { _phantom: PhantomData<&'a mut &'a ()>, } +impl<'a, D: LocalDeploy<'a> + ?Sized> FlowBuilder<'a, D> { + pub fn ir(&self) -> Ref<'_, Vec> { + self.ir_leaves.borrow() + } +} + impl<'a, D: LocalDeploy<'a>> QuotedContext for FlowBuilder<'a, D> { fn create() -> Self { FlowBuilder::new() @@ -41,8 +45,7 @@ impl<'a, D: LocalDeploy<'a>> FlowBuilder<'a, D> { #[allow(clippy::new_without_default)] pub fn new() -> FlowBuilder<'a, D> { FlowBuilder { - next_id: RefCell::new(0), - builders: RefCell::new(Some(Default::default())), + ir_leaves: RefCell::new(Vec::new()), nodes: RefCell::new(Vec::new()), clusters: RefCell::new(Vec::new()), meta: RefCell::new(Default::default()), @@ -51,8 +54,8 @@ impl<'a, D: LocalDeploy<'a>> FlowBuilder<'a, D> { } } - pub fn builder_components(&self) -> (&RefCell, &Builders) { - (&self.next_id, &self.builders) + pub fn ir_leaves(&self) -> &RefCell> { + &self.ir_leaves } pub fn process(&'a self, spec: &impl ProcessSpec<'a, D>) -> D::Process { @@ -99,8 +102,21 @@ impl<'a, D: LocalDeploy<'a>> FlowBuilder<'a, D> { } } -fn build_inner<'a, D: LocalDeploy<'a>>(me: &FlowBuilder<'a, D>, id: TokenStream) -> HfBuilt<'a> { - let builders = me.builders.borrow_mut().take().unwrap(); +fn build_inner<'a, D: LocalDeploy<'a>>( + me: &FlowBuilder<'a, D>, + id: syn::Expr, + is_single: bool, +) -> HfBuilt<'a> { + let mut builders = BTreeMap::new(); + let mut built_tees = HashMap::new(); + let mut next_stmt_id = 0; + for leaf in me.ir_leaves().replace(Default::default()) { + leaf.emit(&mut builders, &mut built_tees, &mut next_stmt_id); + } + + if is_single && builders.len() != 1 { + panic!("Expected exactly one node in the graph."); + } let mut conditioned_tokens = None; for (subgraph_id, builder) in builders { @@ -145,28 +161,64 @@ fn build_inner<'a, D: LocalDeploy<'a>>(me: &FlowBuilder<'a, D>, id: TokenStream) let conditioned_tokens: TokenStream = conditioned_tokens.unwrap(); HfBuilt { - tokens: parse_quote! { + tokens: parse_quote!({ let __given_id = #id; #conditioned_tokens else { panic!("Invalid node id: {}", __given_id); } - }, + }), _phantom: PhantomData, } } impl<'a, D: LocalDeploy<'a, RuntimeID = usize>> FlowBuilder<'a, D> { pub fn build(&self, id: impl Quoted<'a, usize>) -> HfBuilt<'a> { - build_inner(self, id.splice()) + build_inner(self, id.splice(), false) + } + + pub fn hydroflow_ir(&self) -> BTreeMap { + let mut builders = BTreeMap::new(); + let mut built_tees = HashMap::new(); + let mut next_stmt_id = 0; + let borrowed_leaves = self.ir_leaves.borrow(); + for leaf in borrowed_leaves.iter() { + leaf.clone() + .emit(&mut builders, &mut built_tees, &mut next_stmt_id); + } + + let mut result = BTreeMap::new(); + for (subgraph_id, builder) in builders { + let (flat_graph, _, _) = builder.build(); + result.insert(subgraph_id, flat_graph); + } + + result } } impl<'a, D: LocalDeploy<'a, RuntimeID = ()>> FlowBuilder<'a, D> { pub fn build_single(&self) -> HfBuilt<'a> { - if self.builders.borrow().as_ref().unwrap().len() != 1 { + build_inner(self, parse_quote!(0), true) + } + + pub fn single_hydroflow_ir(&self) -> HydroflowGraph { + let mut builders = BTreeMap::new(); + let mut built_tees = HashMap::new(); + let mut next_stmt_id = 0; + let borrowed_leaves = self.ir_leaves.borrow(); + for leaf in borrowed_leaves.iter() { + leaf.clone() + .emit(&mut builders, &mut built_tees, &mut next_stmt_id); + } + + if builders.len() != 1 { panic!("Expected exactly one node in the graph."); } - build_inner(self, quote!(0)) + builders + .remove(&0) + .expect("expected a single graph") + .build() + .0 } } diff --git a/hydroflow_plus/src/cycle.rs b/hydroflow_plus/src/cycle.rs index bfaeecfac84f..8e00d5086c55 100644 --- a/hydroflow_plus/src/cycle.rs +++ b/hydroflow_plus/src/cycle.rs @@ -1,8 +1,7 @@ +use std::cell::RefCell; use std::marker::PhantomData; -use syn::parse_quote; - -use crate::builder::Builders; +use crate::ir::HfPlusLeaf; use crate::location::Location; use crate::Stream; @@ -13,24 +12,18 @@ use crate::Stream; pub struct HfCycle<'a, T, W, N: Location<'a>> { pub(crate) ident: syn::Ident, pub(crate) node: N, - pub(crate) builders: &'a Builders, + pub(crate) ir_leaves: &'a RefCell>, pub(crate) _phantom: PhantomData<(T, W)>, } impl<'a, T, W, N: Location<'a>> HfCycle<'a, T, W, N> { - pub fn complete(self, stream: &Stream<'a, T, W, N>) { + pub fn complete(self, stream: Stream<'a, T, W, N>) { let ident = self.ident; - // TODO(shadaj): avoid having to concretize within cycles - let stream_ident = stream.ensure_concrete().ident.clone(); - self.builders - .borrow_mut() - .as_mut() - .unwrap() - .entry(self.node.id()) - .or_default() - .add_statement(parse_quote! { - #stream_ident -> #ident; - }); + self.ir_leaves.borrow_mut().push(HfPlusLeaf::CycleSink { + ident, + location_id: self.node.id(), + input: Box::new(stream.ir_node.into_inner()), + }); } } diff --git a/hydroflow_plus/src/ir.rs b/hydroflow_plus/src/ir.rs new file mode 100644 index 000000000000..3a56f29be527 --- /dev/null +++ b/hydroflow_plus/src/ir.rs @@ -0,0 +1,597 @@ +use std::cell::RefCell; +use std::collections::{BTreeMap, HashMap}; +use std::ops::Deref; +use std::rc::Rc; + +use hydroflow_lang::graph::FlatGraphBuilder; +use hydroflow_lang::parse::Pipeline; +use proc_macro2::{Span, TokenStream}; +use quote::ToTokens; +use syn::parse_quote; + +#[derive(Clone)] +pub struct DebugExpr(pub syn::Expr); + +impl From for DebugExpr { + fn from(expr: syn::Expr) -> DebugExpr { + DebugExpr(expr) + } +} + +impl Deref for DebugExpr { + type Target = syn::Expr; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl ToTokens for DebugExpr { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.0.to_tokens(tokens); + } +} + +impl std::fmt::Debug for DebugExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0.to_token_stream()) + } +} + +#[derive(Clone)] +pub struct DebugPipelineFn(pub Rc Option<(Pipeline, bool)> + 'static>); + +impl std::fmt::Debug for DebugPipelineFn { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "") + } +} + +/// A source in a Hydroflow+ graph, where data enters the graph. +#[derive(Clone, Debug)] +pub enum HfPlusSource { + Stream(DebugExpr), + Iter(DebugExpr), + Interval(DebugExpr), + Spin(), +} + +/// An leaf in a Hydroflow+ graph, which is an pipeline that doesn't emit +/// any downstream values. Traversals over the dataflow graph and +/// generating Hydroflow IR start from leaves. +#[derive(Clone, Debug)] +pub enum HfPlusLeaf { + ForEach { + f: DebugExpr, + input: Box, + }, + DestSink { + sink: DebugExpr, + input: Box, + }, + CycleSink { + ident: syn::Ident, + location_id: usize, + input: Box, + }, +} + +impl HfPlusLeaf { + pub fn emit( + self, + graph_builders: &mut BTreeMap, + built_tees: &mut HashMap<*const RefCell, (syn::Ident, usize, bool)>, + next_stmt_id: &mut usize, + ) { + match self { + HfPlusLeaf::ForEach { f, input } => { + let (input_ident, input_location_id, input_delta) = + input.emit(graph_builders, built_tees, next_stmt_id); + + assert!(!input_delta, "for_each on a delta stream"); + + graph_builders + .entry(input_location_id) + .or_default() + .add_statement(parse_quote! { + #input_ident -> for_each(#f); + }); + } + + HfPlusLeaf::DestSink { sink, input } => { + let (input_ident, input_location_id, input_delta) = + input.emit(graph_builders, built_tees, next_stmt_id); + + assert!(!input_delta, "sending delta in dest_sink"); + + graph_builders + .entry(input_location_id) + .or_default() + .add_statement(parse_quote! { + #input_ident -> dest_sink(#sink); + }); + } + + HfPlusLeaf::CycleSink { + ident, + location_id, + input, + } => { + let (input_ident, input_location_id, input_delta) = + input.emit(graph_builders, built_tees, next_stmt_id); + + assert!(!input_delta, "sending deltas into a cycle"); + assert_eq!( + input_location_id, location_id, + "cycle_sink location mismatch" + ); + + graph_builders + .entry(location_id) + .or_default() + .add_statement(parse_quote! { + #ident = #input_ident; + }); + } + } + } +} + +/// An intermediate node in a Hydroflow+ graph, which consumes data +/// from upstream nodes and emits data to downstream nodes. +#[derive(Clone, Debug)] +pub enum HfPlusNode { + Placeholder, + Persist(Box), + Delta(Box), + Source { + source: HfPlusSource, + produces_delta: bool, + location_id: usize, + }, + CycleSource { + ident: syn::Ident, + location_id: usize, + }, + Tee { + inner: Rc>, + }, + Union(Box, Box), + CrossProduct(Box, Box), + Join(Box, Box), + Difference(Box, Box), + AntiJoin(Box, Box), + + Map { + f: DebugExpr, + input: Box, + }, + + /// A temporary IR node for a custom pipeline, which eventually will be replaced by a proper node. + PipelineOp { + kind: &'static str, + gen_pipeline: DebugPipelineFn, + input: Box, + }, + + Network { + to_location: usize, + serialize_pipeline: Option, + sink_expr: DebugExpr, + source_expr: DebugExpr, + deserialize_pipeline: Option, + input: Box, + }, +} + +impl HfPlusNode { + pub fn emit( + self, + graph_builders: &mut BTreeMap, + built_tees: &mut HashMap<*const RefCell, (syn::Ident, usize, bool)>, + next_stmt_id: &mut usize, + ) -> (syn::Ident, usize, bool) { + match self { + HfPlusNode::Placeholder => { + panic!() + } + + HfPlusNode::Persist(inner) => { + let (ident, location, inner_delta) = + inner.emit(graph_builders, built_tees, next_stmt_id); + assert!(!inner_delta, "double persist"); + (ident, location, true) + } + + HfPlusNode::Delta(inner) => { + let (inner_ident, location, inner_delta) = + inner.emit(graph_builders, built_tees, next_stmt_id); + + if inner_delta { + (inner_ident, location, false) + } else { + let delta_id = *next_stmt_id; + *next_stmt_id += 1; + + let delta_ident = + syn::Ident::new(&format!("stream_{}", delta_id), Span::call_site()); + + let builder = graph_builders.entry(location).or_default(); + builder.add_statement(parse_quote! { + #delta_ident = #inner_ident -> multiset_delta(); + }); + + (delta_ident, location, false) + } + } + + HfPlusNode::Source { + source, + produces_delta, + location_id, + } => { + let source_id = *next_stmt_id; + *next_stmt_id += 1; + + let source_ident = + syn::Ident::new(&format!("stream_{}", source_id), Span::call_site()); + + let source_stmt = match source { + HfPlusSource::Stream(expr) => { + parse_quote! { + #source_ident = source_stream(#expr); + } + } + + HfPlusSource::Iter(expr) => { + parse_quote! { + #source_ident = source_iter(#expr); + } + } + + HfPlusSource::Interval(expr) => { + parse_quote! { + #source_ident = source_interval(#expr); + } + } + + HfPlusSource::Spin() => { + parse_quote! { + #source_ident = spin(); + } + } + }; + + graph_builders + .entry(location_id) + .or_default() + .add_statement(source_stmt); + + (source_ident, location_id, produces_delta) + } + + HfPlusNode::CycleSource { ident, location_id } => (ident.clone(), location_id, false), + + HfPlusNode::Tee { inner } => { + if let Some(ret) = built_tees.get(&(inner.as_ref() as *const RefCell)) { + ret.clone() + } else { + let (inner_ident, inner_location_id, inner_produces_delta) = inner + .replace(HfPlusNode::Placeholder) + .emit(graph_builders, built_tees, next_stmt_id); + + let tee_id = *next_stmt_id; + *next_stmt_id += 1; + + let tee_ident = + syn::Ident::new(&format!("stream_{}", tee_id), Span::call_site()); + + let builder = graph_builders.entry(inner_location_id).or_default(); + builder.add_statement(parse_quote! { + #tee_ident = #inner_ident -> tee(); + }); + + built_tees.insert( + inner.as_ref() as *const RefCell, + (tee_ident.clone(), inner_location_id, inner_produces_delta), + ); + + (tee_ident, inner_location_id, inner_produces_delta) + } + } + + HfPlusNode::Union(left, right) => { + let (left_ident, left_location_id, left_delta) = + left.emit(graph_builders, built_tees, next_stmt_id); + let (right_ident, right_location_id, right_delta) = + right.emit(graph_builders, built_tees, next_stmt_id); + + assert_eq!( + left_location_id, right_location_id, + "union inputs must be in the same location" + ); + + assert!(!left_delta, "union on a delta stream"); + assert!(!right_delta, "union on a delta stream"); + + let union_id = *next_stmt_id; + *next_stmt_id += 1; + + let union_ident = + syn::Ident::new(&format!("stream_{}", union_id), Span::call_site()); + + let builder = graph_builders.entry(left_location_id).or_default(); + builder.add_statement(parse_quote! { + #union_ident = union(); + }); + + builder.add_statement(parse_quote! { + #left_ident -> [0]#union_ident; + }); + + builder.add_statement(parse_quote! { + #right_ident -> [1]#union_ident; + }); + + (union_ident, left_location_id, false) + } + + HfPlusNode::CrossProduct(..) | HfPlusNode::Join(..) => { + let operator: syn::Ident = if matches!(self, HfPlusNode::CrossProduct(..)) { + parse_quote!(cross_join) + } else { + parse_quote!(join) + }; + + if let HfPlusNode::CrossProduct(left, right) | HfPlusNode::Join(left, right) = self + { + let (left_ident, left_location_id, left_delta) = + left.emit(graph_builders, built_tees, next_stmt_id); + let (right_ident, right_location_id, right_delta) = + right.emit(graph_builders, built_tees, next_stmt_id); + + assert_eq!( + left_location_id, right_location_id, + "join / cross product inputs must be in the same location" + ); + + let stream_id = *next_stmt_id; + *next_stmt_id += 1; + + let stream_ident = + syn::Ident::new(&format!("stream_{}", stream_id), Span::call_site()); + + let builder = graph_builders.entry(left_location_id).or_default(); + + let output_delta = match (left_delta, right_delta) { + (true, true) => { + builder.add_statement(parse_quote! { + #stream_ident = #operator::<'static, 'static>(); + }); + + false // TODO(shadaj): join/cross_join already replays? + } + (true, false) => { + builder.add_statement(parse_quote! { + #stream_ident = #operator::<'static, 'tick>(); + }); + + false + } + (false, true) => { + builder.add_statement(parse_quote! { + #stream_ident = #operator::<'tick, 'static>(); + }); + + false + } + (false, false) => { + builder.add_statement(parse_quote! { + #stream_ident = #operator::<'tick, 'tick>(); + }); + + false + } + }; + + builder.add_statement(parse_quote! { + #left_ident -> [0]#stream_ident; + }); + + builder.add_statement(parse_quote! { + #right_ident -> [1]#stream_ident; + }); + + (stream_ident, left_location_id, output_delta) + } else { + unreachable!() + } + } + + HfPlusNode::Difference(..) | HfPlusNode::AntiJoin(..) => { + let operator: syn::Ident = if matches!(self, HfPlusNode::Difference(..)) { + parse_quote!(difference) + } else { + parse_quote!(anti_join) + }; + + if let HfPlusNode::Difference(left, right) | HfPlusNode::AntiJoin(left, right) = + self + { + let (left_ident, left_location_id, left_delta) = + left.emit(graph_builders, built_tees, next_stmt_id); + let (right_ident, right_location_id, right_delta) = + right.emit(graph_builders, built_tees, next_stmt_id); + + assert_eq!( + left_location_id, right_location_id, + "difference / anti join inputs must be in the same location" + ); + + let stream_id = *next_stmt_id; + *next_stmt_id += 1; + + let stream_ident = + syn::Ident::new(&format!("stream_{}", stream_id), Span::call_site()); + + let builder = graph_builders.entry(left_location_id).or_default(); + let output_delta = match (left_delta, right_delta) { + (true, true) => { + // difference/anti_join<'static, _> does not replay + // but we need to re-filter every tick + builder.add_statement(parse_quote! { + #stream_ident = #operator::<'tick, 'static>(); + }); + + false + } + (true, false) => { + // difference/anti_join<'static, _> does not replay + // but we need to re-filter every tick + builder.add_statement(parse_quote! { + #stream_ident = #operator::<'tick, 'tick>(); + }); + + false + } + (false, true) => { + builder.add_statement(parse_quote! { + #stream_ident = #operator::<'tick, 'static>(); + }); + + false + } + (false, false) => { + builder.add_statement(parse_quote! { + #stream_ident = #operator::<'tick, 'tick>(); + }); + + false + } + }; + + if left_delta { + builder.add_statement(parse_quote! { + #left_ident -> persist() -> [pos]#stream_ident; + }); + } else { + builder.add_statement(parse_quote! { + #left_ident -> [pos]#stream_ident; + }); + } + + builder.add_statement(parse_quote! { + #right_ident -> [neg]#stream_ident; + }); + + (stream_ident, left_location_id, output_delta) + } else { + unreachable!() + } + } + + HfPlusNode::Map { f, input } => { + let (input_ident, input_location_id, input_delta) = + input.emit(graph_builders, built_tees, next_stmt_id); + + let map_id = *next_stmt_id; + *next_stmt_id += 1; + + let map_ident = syn::Ident::new(&format!("stream_{}", map_id), Span::call_site()); + + let builder = graph_builders.entry(input_location_id).or_default(); + builder.add_statement(parse_quote! { + #map_ident = map(#f); + }); + + builder.add_statement(parse_quote! { + #input_ident -> #map_ident; + }); + + (map_ident, input_location_id, input_delta) + } + + HfPlusNode::Network { + to_location, + serialize_pipeline, + sink_expr, + source_expr, + deserialize_pipeline, + input, + } => { + let (input_ident, input_location_id, input_delta) = + input.emit(graph_builders, built_tees, next_stmt_id); + + let sender_builder = graph_builders.entry(input_location_id).or_default(); + + if let Some(serialize_pipeline) = serialize_pipeline { + sender_builder.add_statement(parse_quote! { + #input_ident -> #serialize_pipeline -> dest_sink(#sink_expr); + }); + } else { + sender_builder.add_statement(parse_quote! { + #input_ident -> dest_sink(#sink_expr); + }); + } + + let receiver_builder = graph_builders.entry(to_location).or_default(); + let receiver_stream_id = *next_stmt_id; + *next_stmt_id += 1; + + let receiver_stream_ident = + syn::Ident::new(&format!("stream_{}", receiver_stream_id), Span::call_site()); + + if let Some(deserialize_pipeline) = deserialize_pipeline { + receiver_builder.add_statement(parse_quote! { + #receiver_stream_ident = source_stream(#source_expr) -> #deserialize_pipeline; + }); + } else { + receiver_builder.add_statement(parse_quote! { + #receiver_stream_ident = source_stream(#source_expr); + }); + } + + (receiver_stream_ident, to_location, input_delta) + } + + HfPlusNode::PipelineOp { + kind: _, + gen_pipeline, + input, + } => { + let (input_ident, input_location_id, input_delta) = + input.emit(graph_builders, built_tees, next_stmt_id); + + let pipeline_id = *next_stmt_id; + *next_stmt_id += 1; + + let pipeline_ident = + syn::Ident::new(&format!("stream_{}", pipeline_id), Span::call_site()); + + if let Some((pipeline, is_delta)) = gen_pipeline.0(input_delta) { + graph_builders + .entry(input_location_id) + .or_default() + .add_statement(parse_quote! { + #pipeline_ident = #input_ident -> #pipeline; + }); + + (pipeline_ident, input_location_id, is_delta) + } else if input_delta { + let (pipeline, is_delta) = gen_pipeline.0(false) + .expect("pipeline op refused to generate on a non-delta stream"); + graph_builders + .entry(input_location_id) + .or_default() + .add_statement(parse_quote! { + #pipeline_ident = #input_ident -> persist() -> #pipeline; + }); + + (pipeline_ident, input_location_id, is_delta) + } else { + panic!("pipeline op refused to generate on a non-delta stream"); + } + } + } + } +} diff --git a/hydroflow_plus/src/lib.rs b/hydroflow_plus/src/lib.rs index d50401e427d6..bc57aa2318af 100644 --- a/hydroflow_plus/src/lib.rs +++ b/hydroflow_plus/src/lib.rs @@ -29,6 +29,8 @@ pub use cycle::HfCycle; pub mod builder; pub use builder::FlowBuilder; +pub mod ir; + #[derive(Clone)] pub struct RuntimeContext<'a> { _phantom: PhantomData<&'a mut &'a ()>, diff --git a/hydroflow_plus/src/location/graphs.rs b/hydroflow_plus/src/location/graphs.rs index 784f556c77bc..377bef6bae2f 100644 --- a/hydroflow_plus/src/location/graphs.rs +++ b/hydroflow_plus/src/location/graphs.rs @@ -1,9 +1,10 @@ use std::cell::RefCell; +use std::rc::Rc; use stageleft::{Quoted, RuntimeData}; use super::{Cluster, LocalDeploy, Location, ProcessSpec}; -use crate::builder::Builders; +use crate::ir::HfPlusLeaf; use crate::FlowBuilder; pub struct SingleProcessGraph {} @@ -22,13 +23,17 @@ impl<'a> ProcessSpec<'a, SingleProcessGraph> for () { builder: &'a FlowBuilder<'a, SingleProcessGraph>, _meta: &mut (), ) -> SingleNode<'a> { - SingleNode { builder } + SingleNode { + builder, + cycle_counter: Rc::new(RefCell::new(0)), + } } } #[derive(Clone)] pub struct SingleNode<'a> { builder: &'a FlowBuilder<'a, SingleProcessGraph>, + cycle_counter: Rc>, } impl<'a> Location<'a> for SingleNode<'a> { @@ -39,8 +44,12 @@ impl<'a> Location<'a> for SingleNode<'a> { 0 } - fn flow_builder(&self) -> (&'a RefCell, &'a Builders) { - (&self.builder.next_id, &self.builder.builders) + fn ir_leaves(&self) -> &'a RefCell> { + self.builder.ir_leaves() + } + + fn cycle_counter(&self) -> &RefCell { + self.cycle_counter.as_ref() } fn next_port(&self) { @@ -74,7 +83,11 @@ impl<'a> ProcessSpec<'a, MultiGraph> for () { builder: &'a FlowBuilder<'a, MultiGraph>, _meta: &mut (), ) -> MultiNode<'a> { - MultiNode { builder, id } + MultiNode { + builder, + id, + cycle_counter: Rc::new(RefCell::new(0)), + } } } @@ -82,6 +95,7 @@ impl<'a> ProcessSpec<'a, MultiGraph> for () { pub struct MultiNode<'a> { builder: &'a FlowBuilder<'a, MultiGraph>, id: usize, + cycle_counter: Rc>, } impl<'a> Location<'a> for MultiNode<'a> { @@ -92,8 +106,12 @@ impl<'a> Location<'a> for MultiNode<'a> { self.id } - fn flow_builder(&self) -> (&'a RefCell, &'a Builders) { - (&self.builder.next_id, &self.builder.builders) + fn ir_leaves(&self) -> &'a RefCell> { + self.builder.ir_leaves() + } + + fn cycle_counter(&self) -> &RefCell { + self.cycle_counter.as_ref() } fn next_port(&self) { diff --git a/hydroflow_plus/src/location/mod.rs b/hydroflow_plus/src/location/mod.rs index d3f7fc7a904e..f55e926e2b2b 100644 --- a/hydroflow_plus/src/location/mod.rs +++ b/hydroflow_plus/src/location/mod.rs @@ -7,9 +7,8 @@ use hydroflow::bytes::BytesMut; use hydroflow::futures::stream::Stream as FuturesStream; use proc_macro2::Span; use stageleft::{q, Quoted}; -use syn::parse_quote; -use crate::builder::Builders; +use crate::ir::{HfPlusLeaf, HfPlusNode, HfPlusSource}; use crate::stream::{Async, Windowed}; use crate::{FlowBuilder, HfCycle, Stream}; @@ -68,41 +67,27 @@ pub trait Location<'a>: Clone { type Meta; fn id(&self) -> usize; - fn flow_builder(&self) -> (&'a RefCell, &'a Builders); + + /// A handle to the global list of IR leaves, which are the outputs of the program. + fn ir_leaves(&self) -> &'a RefCell>; + + /// A handle to a counter of cycles within this location. + fn cycle_counter(&self) -> &RefCell; + fn next_port(&self) -> Self::Port; fn update_meta(&mut self, meta: &Self::Meta); fn spin(&self) -> Stream<'a, (), Async, Self> { - let (next_id_cell, builders) = self.flow_builder(); - - let next_id = { - let mut next_id = next_id_cell.borrow_mut(); - let id = *next_id; - *next_id += 1; - id - }; - - let ident = syn::Ident::new(&format!("stream_{}", next_id), Span::call_site()); - - builders - .borrow_mut() - .as_mut() - .unwrap() - .entry(self.id()) - .or_default() - .add_statement(parse_quote! { - #ident = spin() -> tee(); - }); - - Stream { - ident, - node: self.clone(), - next_id: next_id_cell, - builders, - is_delta: false, - _phantom: PhantomData, - } + Stream::new( + self.clone(), + self.ir_leaves(), + HfPlusNode::Source { + source: HfPlusSource::Spin(), + produces_delta: false, + location_id: self.id(), + }, + ) } fn spin_batch( @@ -119,36 +104,17 @@ pub trait Location<'a>: Clone { &self, e: impl Quoted<'a, E>, ) -> Stream<'a, T, Async, Self> { - let (next_id_cell, builders) = self.flow_builder(); - - let next_id = { - let mut next_id = next_id_cell.borrow_mut(); - let id = *next_id; - *next_id += 1; - id - }; - - let ident = syn::Ident::new(&format!("stream_{}", next_id), Span::call_site()); let e = e.splice(); - builders - .borrow_mut() - .as_mut() - .unwrap() - .entry(self.id()) - .or_default() - .add_statement(parse_quote! { - #ident = source_stream(#e) -> tee(); - }); - - Stream { - ident, - node: self.clone(), - next_id: next_id_cell, - builders, - is_delta: false, - _phantom: PhantomData, - } + Stream::new( + self.clone(), + self.ir_leaves(), + HfPlusNode::Source { + source: HfPlusSource::Stream(e.into()), + location_id: self.id(), + produces_delta: false, + }, + ) } fn source_external( @@ -160,39 +126,20 @@ pub trait Location<'a>: Clone { where Self: HfSendOneToOne<'a, Self>, { - let (next_id_cell, builders) = self.flow_builder(); - - let next_id = { - let mut next_id = next_id_cell.borrow_mut(); - let id = *next_id; - *next_id += 1; - id - }; - - let ident = syn::Ident::new(&format!("stream_{}", next_id), Span::call_site()); let port = self.next_port(); let source_pipeline = Self::gen_source_statement(self, &port); - builders - .borrow_mut() - .as_mut() - .unwrap() - .entry(self.id()) - .or_default() - .add_statement(parse_quote! { - #ident = #source_pipeline -> tee(); - }); - ( port, - Stream { - ident, - node: self.clone(), - next_id: next_id_cell, - builders, - is_delta: false, - _phantom: PhantomData, - }, + Stream::new( + self.clone(), + self.ir_leaves(), + HfPlusNode::Source { + source: HfPlusSource::Stream(source_pipeline.into()), + location_id: self.id(), + produces_delta: false, + }, + ), ) } @@ -205,39 +152,20 @@ pub trait Location<'a>: Clone { where S: HfSendOneToMany<'a, Self>, { - let (next_id_cell, builders) = self.flow_builder(); - - let next_id = { - let mut next_id = next_id_cell.borrow_mut(); - let id = *next_id; - *next_id += 1; - id - }; - - let ident = syn::Ident::new(&format!("stream_{}", next_id), Span::call_site()); let port = self.next_port(); let source_pipeline = S::gen_source_statement(self, &port); - builders - .borrow_mut() - .as_mut() - .unwrap() - .entry(self.id()) - .or_default() - .add_statement(parse_quote! { - #ident = #source_pipeline -> tee(); - }); - ( port, - Stream { - ident, - node: self.clone(), - next_id: next_id_cell, - builders, - is_delta: false, - _phantom: PhantomData, - }, + Stream::new( + self.clone(), + self.ir_leaves(), + HfPlusNode::Source { + source: HfPlusSource::Stream(source_pipeline.into()), + location_id: self.id(), + produces_delta: false, + }, + ), ) } @@ -245,76 +173,38 @@ pub trait Location<'a>: Clone { &self, e: impl Quoted<'a, E>, ) -> Stream<'a, T, Windowed, Self> { - let (next_id_cell, builders) = self.flow_builder(); - - let next_id = { - let mut next_id = next_id_cell.borrow_mut(); - let id = *next_id; - *next_id += 1; - id - }; - - let ident = syn::Ident::new(&format!("stream_{}", next_id), Span::call_site()); let e = e.splice(); - builders - .borrow_mut() - .as_mut() - .unwrap() - .entry(self.id()) - .or_default() - .add_statement(parse_quote! { - #ident = source_iter(#e) -> tee(); - }); - - Stream { - ident, - node: self.clone(), - next_id: next_id_cell, - builders, - is_delta: false, - _phantom: PhantomData, - } + Stream::new( + self.clone(), + self.ir_leaves(), + HfPlusNode::Source { + source: HfPlusSource::Iter(e.into()), + location_id: self.id(), + produces_delta: false, + }, + ) } fn source_interval( &self, interval: impl Quoted<'a, Duration> + Copy + 'a, ) -> Stream<'a, hydroflow::tokio::time::Instant, Async, Self> { - let (next_id_cell, builders) = self.flow_builder(); - - let next_id = { - let mut next_id = next_id_cell.borrow_mut(); - let id = *next_id; - *next_id += 1; - id - }; - - let ident = syn::Ident::new(&format!("stream_{}", next_id), Span::call_site()); let interval = interval.splice(); - builders - .borrow_mut() - .as_mut() - .unwrap() - .entry(self.id()) - .or_default() - .add_statement(parse_quote! { - #ident = source_interval(#interval) -> tee(); - }); - - Stream { - ident, - node: self.clone(), - next_id: next_id_cell, - builders, - is_delta: false, - _phantom: PhantomData, - } + Stream::new( + self.clone(), + self.ir_leaves(), + HfPlusNode::Source { + source: HfPlusSource::Interval(interval.into()), + location_id: self.id(), + produces_delta: false, + }, + ) } fn cycle(&self) -> (HfCycle<'a, T, W, Self>, Stream<'a, T, W, Self>) { - let (next_id_cell, builders) = self.flow_builder(); + let next_id_cell = self.cycle_counter(); let next_id = { let mut next_id = next_id_cell.borrow_mut(); @@ -323,33 +213,23 @@ pub trait Location<'a>: Clone { id }; - let ident = syn::Ident::new(&format!("stream_{}", next_id), Span::call_site()); - - builders - .borrow_mut() - .as_mut() - .unwrap() - .entry(self.id()) - .or_default() - .add_statement(parse_quote! { - #ident = tee(); - }); + let ident = syn::Ident::new(&format!("cycle_{}", next_id), Span::call_site()); ( HfCycle { ident: ident.clone(), node: self.clone(), - builders, - _phantom: PhantomData, - }, - Stream { - ident, - node: self.clone(), - next_id: next_id_cell, - builders, - is_delta: false, + ir_leaves: self.ir_leaves(), _phantom: PhantomData, }, + Stream::new( + self.clone(), + self.ir_leaves(), + HfPlusNode::CycleSource { + ident, + location_id: self.id(), + }, + ), ) } } diff --git a/hydroflow_plus/src/location/network.rs b/hydroflow_plus/src/location/network.rs index a4f2e2682312..f368ca926353 100644 --- a/hydroflow_plus/src/location/network.rs +++ b/hydroflow_plus/src/location/network.rs @@ -1,31 +1,29 @@ -use hydroflow_lang::parse::Pipeline; - use super::Location; pub trait HfSendOneToOne<'a, O: Location<'a>>: Location<'a> { fn connect(&self, other: &O, source_port: &Self::Port, recipient_port: &O::Port); - fn gen_sink_statement(&self, port: &Self::Port) -> Pipeline; - fn gen_source_statement(other: &O, port: &O::Port) -> Pipeline; + fn gen_sink_statement(&self, port: &Self::Port) -> syn::Expr; + fn gen_source_statement(other: &O, port: &O::Port) -> syn::Expr; } pub trait HfSendManyToOne<'a, O: Location<'a>>: Location<'a> { fn connect(&self, other: &O, source_port: &Self::Port, recipient_port: &O::Port); - fn gen_sink_statement(&self, port: &Self::Port) -> Pipeline; - fn gen_source_statement(other: &O, port: &O::Port) -> Pipeline; + fn gen_sink_statement(&self, port: &Self::Port) -> syn::Expr; + fn gen_source_statement(other: &O, port: &O::Port) -> syn::Expr; } pub trait HfSendOneToMany<'a, O: Location<'a>>: Location<'a> { fn connect(&self, other: &O, source_port: &Self::Port, recipient_port: &O::Port); - fn gen_sink_statement(&self, port: &Self::Port) -> Pipeline; - fn gen_source_statement(other: &O, port: &O::Port) -> Pipeline; + fn gen_sink_statement(&self, port: &Self::Port) -> syn::Expr; + fn gen_source_statement(other: &O, port: &O::Port) -> syn::Expr; } pub trait HfSendManyToMany<'a, O: Location<'a>>: Location<'a> { fn connect(&self, other: &O, source_port: &Self::Port, recipient_port: &O::Port); - fn gen_sink_statement(&self, port: &Self::Port) -> Pipeline; - fn gen_source_statement(other: &O, port: &O::Port) -> Pipeline; + fn gen_sink_statement(&self, port: &Self::Port) -> syn::Expr; + fn gen_source_statement(other: &O, port: &O::Port) -> syn::Expr; } diff --git a/hydroflow_plus/src/stream.rs b/hydroflow_plus/src/stream.rs index 33bd7e1447f1..746196baf1ce 100644 --- a/hydroflow_plus/src/stream.rs +++ b/hydroflow_plus/src/stream.rs @@ -2,6 +2,8 @@ use std::cell::RefCell; use std::hash::Hash; use std::io; use std::marker::PhantomData; +use std::ops::Deref; +use std::rc::Rc; use hydroflow::bytes::{Bytes, BytesMut}; use hydroflow::futures::Sink; @@ -14,7 +16,7 @@ use stageleft::{q, IntoQuotedMut, Quoted}; use syn::parse_quote; use syn::visit_mut::VisitMut; -use crate::builder::Builders; +use crate::ir::{DebugPipelineFn, HfPlusLeaf, HfPlusNode}; use crate::location::{ Cluster, HfSendManyToMany, HfSendManyToOne, HfSendOneToMany, HfSendOneToOne, Location, }; @@ -42,343 +44,244 @@ pub struct Windowed {} /// or [`Windowed`] /// - `N`: the type of the node that the stream is materialized on pub struct Stream<'a, T, W, N: Location<'a>> { - pub(crate) ident: syn::Ident, - pub(crate) node: N, - pub(crate) next_id: &'a RefCell, - pub(crate) builders: &'a Builders, - - /// Does this stream represent a delta of the underlying data? - /// i.e. is the true stream supposed to have a `persist()` at the end - pub(crate) is_delta: bool, + node: N, + + pub(crate) ir_leaves: &'a RefCell>, + pub(crate) ir_node: RefCell, + pub(crate) _phantom: PhantomData<(&'a mut &'a (), T, W)>, } impl<'a, T, W, N: Location<'a>> Stream<'a, T, W, N> { - fn pipeline_op(&self, pipeline: Pipeline, produces_delta: bool) -> Stream<'a, U, W2, N> { - let next_id = { - let mut next_id = self.next_id.borrow_mut(); - let id = *next_id; - *next_id += 1; - id - }; - - let self_ident = &self.ident; - let ident = syn::Ident::new(&format!("stream_{}", next_id), Span::call_site()); - - self.builders - .borrow_mut() - .as_mut() - .unwrap() - .entry(self.node.id()) - .or_default() - .add_statement(parse_quote! { - #ident = #self_ident -> #pipeline -> tee(); - }); - + pub(crate) fn new( + node: N, + ir_leaves: &'a RefCell>, + ir_node: HfPlusNode, + ) -> Self { Stream { - ident, - node: self.node.clone(), - next_id: self.next_id, - builders: self.builders, - is_delta: produces_delta, + node, + ir_leaves, + ir_node: RefCell::new(ir_node), _phantom: PhantomData, } } +} - /// Reifies the stream to ensure that it is not producing deltas. - pub(crate) fn ensure_concrete(&self) -> Stream<'a, T, Windowed, N> { - if self.is_delta { - self.pipeline_op(parse_quote!(persist()), false) - } else { - self.assume_windowed() +impl<'a, T: Clone, W, N: Location<'a>> Clone for Stream<'a, T, W, N> { + fn clone(&self) -> Self { + if !matches!(self.ir_node.borrow().deref(), HfPlusNode::Tee { .. }) { + let orig_ir_node = self.ir_node.replace(HfPlusNode::Placeholder); + *self.ir_node.borrow_mut() = HfPlusNode::Tee { + inner: Rc::new(RefCell::new(orig_ir_node)), + }; } + + Stream::new( + self.node.clone(), + self.ir_leaves, + self.ir_node.borrow().clone(), + ) } +} - pub fn map U + 'a>(&self, f: impl IntoQuotedMut<'a, F>) -> Stream<'a, U, W, N> { - let f = f.splice(); - self.pipeline_op(parse_quote!(map(#f)), self.is_delta) +impl<'a, T, W, N: Location<'a>> Stream<'a, T, W, N> { + fn pipeline_op( + self, + kind: &'static str, + gen_pipeline: impl Fn(bool) -> Option<(Pipeline, bool)> + 'static, + ) -> Stream<'a, U, W2, N> { + Stream::new( + self.node, + self.ir_leaves, + HfPlusNode::PipelineOp { + kind, + gen_pipeline: DebugPipelineFn(Rc::new(gen_pipeline)), + input: Box::new(self.ir_node.into_inner()), + }, + ) + } + + pub fn map U + 'a>(self, f: impl IntoQuotedMut<'a, F>) -> Stream<'a, U, W, N> { + Stream::new( + self.node, + self.ir_leaves, + HfPlusNode::Map { + f: f.splice().into(), + input: Box::new(self.ir_node.into_inner()), + }, + ) } pub fn flat_map, F: Fn(T) -> I + 'a>( - &self, + self, f: impl IntoQuotedMut<'a, F>, ) -> Stream<'a, U, W, N> { let f = f.splice(); - self.pipeline_op(parse_quote!(flat_map(#f)), self.is_delta) + self.pipeline_op("flat_map", move |d| Some((parse_quote!(flat_map(#f)), d))) } - pub fn enumerate(&self) -> Stream<'a, (usize, T), W, N> { - self.ensure_concrete() - .pipeline_op(parse_quote!(enumerate()), self.is_delta) + pub fn enumerate(self) -> Stream<'a, (usize, T), W, N> { + self.pipeline_op("enumerate", |d| { + if d { + None + } else { + Some((parse_quote!(enumerate()), false)) + } + }) } - pub fn inspect(&self, f: impl IntoQuotedMut<'a, F>) -> Stream<'a, T, W, N> { + pub fn inspect(self, f: impl IntoQuotedMut<'a, F>) -> Stream<'a, T, W, N> { let f = f.splice(); - self.ensure_concrete() - .pipeline_op(parse_quote!(inspect(#f)), self.is_delta) + self.pipeline_op("inspect", move |d| { + if d { + None + } else { + Some((parse_quote!(inspect(#f)), false)) + } + }) } pub fn filter bool + 'a>( - &self, + self, f: impl IntoQuotedMut<'a, F>, ) -> Stream<'a, T, W, N> { let f = f.splice(); - self.pipeline_op(parse_quote!(filter(#f)), self.is_delta) + self.pipeline_op("filter", move |d| Some((parse_quote!(filter(#f)), d))) } pub fn filter_map Option + 'a>( - &self, + self, f: impl IntoQuotedMut<'a, F>, ) -> Stream<'a, U, W, N> { let f = f.splice(); - self.pipeline_op(parse_quote!(filter_map(#f)), self.is_delta) + self.pipeline_op("filter_map", move |d| { + Some((parse_quote!(filter_map(#f)), d)) + }) } // TODO(shadaj): should allow for differing windows, using strongest one - pub fn cross_product(&self, other: &Stream<'a, O, W, N>) -> Stream<'a, (T, O), W, N> { + pub fn cross_product(self, other: Stream<'a, O, W, N>) -> Stream<'a, (T, O), W, N> { if self.node.id() != other.node.id() { panic!("cross_product must be called on streams on the same node"); } - let next_id = { - let mut next_id = self.next_id.borrow_mut(); - let id = *next_id; - *next_id += 1; - id - }; - - let self_ident = &self.ident; - let other_ident = &other.ident; - let ident = syn::Ident::new(&format!("stream_{}", next_id), Span::call_site()); - - let mut builders = self.builders.borrow_mut(); - let builder = builders - .as_mut() - .unwrap() - .entry(self.node.id()) - .or_default(); - - let output_delta = match (self.is_delta, other.is_delta) { - (true, true) => { - builder.add_statement(parse_quote! { - #ident = cross_join::<'static, 'static>() -> tee(); - }); - - false // TODO(shadaj): cross_join already replays? - } - (true, false) => { - builder.add_statement(parse_quote! { - #ident = cross_join::<'static, 'tick>() -> tee(); - }); - - false - } - (false, true) => { - builder.add_statement(parse_quote! { - #ident = cross_join::<'tick, 'static>() -> tee(); - }); - - false - } - (false, false) => { - builder.add_statement(parse_quote! { - #ident = cross_join::<'tick, 'tick>() -> tee(); - }); - - false - } - }; - - builder.add_statement(parse_quote! { - #self_ident -> [0]#ident; - }); - - builder.add_statement(parse_quote! { - #other_ident -> [1]#ident; - }); - - Stream { - ident, - node: self.node.clone(), - next_id: self.next_id, - builders: self.builders, - is_delta: output_delta, - _phantom: PhantomData, - } + Stream::new( + self.node, + self.ir_leaves, + HfPlusNode::CrossProduct( + Box::new(self.ir_node.into_inner()), + Box::new(other.ir_node.into_inner()), + ), + ) } - pub fn union(&self, other: &Stream<'a, T, W, N>) -> Stream<'a, T, W, N> { + pub fn union(self, other: Stream<'a, T, W, N>) -> Stream<'a, T, W, N> { if self.node.id() != other.node.id() { panic!("union must be called on streams on the same node"); } - let next_id = { - let mut next_id = self.next_id.borrow_mut(); - let id = *next_id; - *next_id += 1; - id - }; - - let self_ident = &self.ensure_concrete().ident; - let other_ident = &other.ensure_concrete().ident; - let ident = syn::Ident::new(&format!("stream_{}", next_id), Span::call_site()); - - let mut builders = self.builders.borrow_mut(); - let builder = builders - .as_mut() - .unwrap() - .entry(self.node.id()) - .or_default(); - - builder.add_statement(parse_quote! { - #ident = union() -> tee(); - }); - - builder.add_statement(parse_quote! { - #self_ident -> [0]#ident; - }); + Stream::new( + self.node, + self.ir_leaves, + HfPlusNode::Union( + Box::new(self.ir_node.into_inner()), + Box::new(other.ir_node.into_inner()), + ), + ) + } - builder.add_statement(parse_quote! { - #other_ident -> [1]#ident; + pub fn for_each(self, f: impl IntoQuotedMut<'a, F>) { + self.ir_leaves.borrow_mut().push(HfPlusLeaf::ForEach { + input: Box::new(self.ir_node.into_inner()), + f: f.splice().into(), }); - - Stream { - ident, - node: self.node.clone(), - next_id: self.next_id, - builders: self.builders, - is_delta: false, - _phantom: PhantomData, - } } - pub fn for_each(&self, f: impl IntoQuotedMut<'a, F>) { - let self_ident = &self.ensure_concrete().ident; - let f = f.splice(); - - self.builders - .borrow_mut() - .as_mut() - .unwrap() - .entry(self.node.id()) - .or_default() - .add_statement(parse_quote! { - #self_ident -> for_each(#f); - }); + pub fn dest_sink + 'a>(self, sink: impl Quoted<'a, S>) { + self.ir_leaves.borrow_mut().push(HfPlusLeaf::DestSink { + sink: sink.splice().into(), + input: Box::new(self.ir_node.into_inner()), + }); } - pub fn dest_sink + 'a>(&self, sink: impl Quoted<'a, S>) { - let self_ident = &self.ensure_concrete().ident; - let sink = sink.splice(); - - self.builders - .borrow_mut() - .as_mut() - .unwrap() - .entry(self.node.id()) - .or_default() - .add_statement(parse_quote! { - #self_ident -> dest_sink(#sink); - }); + pub fn all_ticks(self) -> Stream<'a, T, Windowed, N> { + Stream::new( + self.node, + self.ir_leaves, + HfPlusNode::Persist(Box::new(self.ir_node.into_inner())), + ) } - pub fn all_ticks(&self) -> Stream<'a, T, Windowed, N> { - if self.is_delta { - self.ensure_concrete().all_ticks() - } else { - Stream { - ident: self.ident.clone(), - node: self.node.clone(), - next_id: self.next_id, - builders: self.builders, - is_delta: true, - _phantom: PhantomData, - } - } - } - - pub fn assume_windowed(&self) -> Stream<'a, T, Windowed, N> { - Stream { - ident: self.ident.clone(), - node: self.node.clone(), - next_id: self.next_id, - builders: self.builders, - is_delta: self.is_delta, - _phantom: PhantomData, - } + pub fn assume_windowed(self) -> Stream<'a, T, Windowed, N> { + Stream::new(self.node, self.ir_leaves, self.ir_node.into_inner()) } } impl<'a, T, N: Location<'a>> Stream<'a, T, Async, N> { - pub fn tick_batch(&self) -> Stream<'a, T, Windowed, N> { - Stream { - ident: self.ident.clone(), - node: self.node.clone(), - next_id: self.next_id, - builders: self.builders, - is_delta: self.is_delta, - _phantom: PhantomData, - } + pub fn tick_batch(self) -> Stream<'a, T, Windowed, N> { + Stream::new(self.node, self.ir_leaves, self.ir_node.into_inner()) } } impl<'a, T, N: Location<'a>> Stream<'a, T, Windowed, N> { pub fn fold A + 'a, C: Fn(&mut A, T)>( - &self, + self, init: impl IntoQuotedMut<'a, I>, comb: impl IntoQuotedMut<'a, C>, ) -> Stream<'a, A, Windowed, N> { let init = init.splice(); let comb = comb.splice(); - if self.is_delta { - self.pipeline_op(parse_quote!(fold::<'static>(#init, #comb)), false) - } else { - self.pipeline_op(parse_quote!(fold::<'tick>(#init, #comb)), false) - } + self.pipeline_op("fold", move |d| { + if d { + Some((parse_quote!(fold::<'static>(#init, #comb)), false)) + } else { + Some((parse_quote!(fold::<'tick>(#init, #comb)), false)) + } + }) } pub fn reduce( - &self, + self, comb: impl IntoQuotedMut<'a, C>, ) -> Stream<'a, T, Windowed, N> { let comb = comb.splice(); - if self.is_delta { - self.pipeline_op(parse_quote!(reduce::<'static>(#comb)), false) - } else { - self.pipeline_op(parse_quote!(reduce::<'tick>(#comb)), false) - } + self.pipeline_op("reduce", move |d| { + if d { + Some((parse_quote!(reduce::<'static>(#comb)), false)) + } else { + Some((parse_quote!(reduce::<'tick>(#comb)), false)) + } + }) } - pub fn count(&self) -> Stream<'a, usize, Windowed, N> { + pub fn count(self) -> Stream<'a, usize, Windowed, N> { self.fold(q!(|| 0usize), q!(|count, _| *count += 1)) } - pub fn delta(&self) -> Stream<'a, T, Windowed, N> { - if self.is_delta { - Stream { - ident: self.ident.clone(), - node: self.node.clone(), - next_id: self.next_id, - builders: self.builders, - is_delta: false, - _phantom: PhantomData, - } - } else { - self.pipeline_op(parse_quote!(multiset_delta()), false) - } + pub fn delta(self) -> Stream<'a, T, Windowed, N> { + Stream::new( + self.node, + self.ir_leaves, + HfPlusNode::Delta(Box::new(self.ir_node.into_inner())), + ) } - pub fn unique(&self) -> Stream<'a, T, Windowed, N> + pub fn unique(self) -> Stream<'a, T, Windowed, N> where T: Eq + Hash, { - self.ensure_concrete() - .pipeline_op(parse_quote!(unique::<'tick>()), false) + self.pipeline_op("unique", |d| { + if d { + None + } else { + Some((parse_quote!(unique::<'tick>()), false)) + } + }) } - pub fn filter_not_in(&self, other: &Stream<'a, T, Windowed, N>) -> Stream<'a, T, Windowed, N> + pub fn filter_not_in(self, other: Stream<'a, T, Windowed, N>) -> Stream<'a, T, Windowed, N> where T: Eq + Hash, { @@ -386,100 +289,34 @@ impl<'a, T, N: Location<'a>> Stream<'a, T, Windowed, N> { panic!("union must be called on streams on the same node"); } - let next_id = { - let mut next_id = self.next_id.borrow_mut(); - let id = *next_id; - *next_id += 1; - id - }; - - let self_ident = if (self.is_delta, other.is_delta) == (true, false) { - self.ensure_concrete().ident - } else { - self.ident.clone() - }; - - let other_ident = &other.ident; - let ident = syn::Ident::new(&format!("stream_{}", next_id), Span::call_site()); - - let mut builders = self.builders.borrow_mut(); - let builder = builders - .as_mut() - .unwrap() - .entry(self.node.id()) - .or_default(); - - let output_delta = match (self.is_delta, other.is_delta) { - (true, true) => { - // we don't gain any performance by having the first be 'tick, - // just persist the second one and we get deltas out - builder.add_statement(parse_quote! { - #ident = difference::<'tick, 'static>() -> tee(); - }); - - true - } - (true, false) => { - // difference/anti_join<'static, _> does not replay - // but we need to re-filter every tick - builder.add_statement(parse_quote! { - #ident = difference::<'tick, 'tick>() -> tee(); - }); - - false - } - (false, true) => { - builder.add_statement(parse_quote! { - #ident = difference::<'tick, 'static>() -> tee(); - }); - - false - } - (false, false) => { - builder.add_statement(parse_quote! { - #ident = difference::<'tick, 'tick>() -> tee(); - }); - - false - } - }; - - builder.add_statement(parse_quote! { - #self_ident -> [pos]#ident; - }); - - builder.add_statement(parse_quote! { - #other_ident -> [neg]#ident; - }); - - Stream { - ident, - node: self.node.clone(), - next_id: self.next_id, - builders: self.builders, - is_delta: output_delta, - _phantom: PhantomData, - } + Stream::new( + self.node, + self.ir_leaves, + HfPlusNode::Difference( + Box::new(self.ir_node.into_inner()), + Box::new(other.ir_node.into_inner()), + ), + ) } pub fn sample_every( - &self, + self, duration: impl Quoted<'a, std::time::Duration> + Copy + 'a, ) -> Stream<'a, T, Windowed, N> { - self.cross_product(&self.node.source_interval(duration).tick_batch()) - .map(q!(|(a, _)| a)) + let samples = self.node.source_interval(duration).tick_batch(); + self.cross_product(samples).map(q!(|(a, _)| a)) } } impl<'a, T: Clone, W, N: Location<'a>> Stream<'a, &T, W, N> { - pub fn cloned(&self) -> Stream<'a, T, W, N> { - self.pipeline_op(parse_quote!(map(|d| d.clone())), self.is_delta) + pub fn cloned(self) -> Stream<'a, T, W, N> { + self.pipeline_op("cloned", |d| Some((parse_quote!(map(|d| d.clone())), d))) } } impl<'a, K, V1, W, N: Location<'a>> Stream<'a, (K, V1), W, N> { // TODO(shadaj): figure out window semantics - pub fn join(&self, n: &Stream<'a, (K, V2), W2, N>) -> Stream<'a, (K, (V1, V2)), W, N> + pub fn join(self, n: Stream<'a, (K, V2), W2, N>) -> Stream<'a, (K, (V1, V2)), W, N> where K: Eq + Hash, { @@ -487,74 +324,17 @@ impl<'a, K, V1, W, N: Location<'a>> Stream<'a, (K, V1), W, N> { panic!("join must be called on streams on the same node"); } - let next_id = { - let mut next_id = self.next_id.borrow_mut(); - let id = *next_id; - *next_id += 1; - id - }; - - let self_ident = &self.ident; - let other_ident = &n.ident; - let ident = syn::Ident::new(&format!("stream_{}", next_id), Span::call_site()); - - let mut builders = self.builders.borrow_mut(); - let builder = builders - .as_mut() - .unwrap() - .entry(self.node.id()) - .or_default(); - - let output_delta = match (self.is_delta, n.is_delta) { - (true, true) => { - builder.add_statement(parse_quote! { - #ident = join::<'static, 'static>() -> tee(); - }); - - false // TODO(shadaj): join already replays? - } - (true, false) => { - builder.add_statement(parse_quote! { - #ident = join::<'static, 'tick>() -> tee(); - }); - - false - } - (false, true) => { - builder.add_statement(parse_quote! { - #ident = join::<'tick, 'static>() -> tee(); - }); - - false - } - (false, false) => { - builder.add_statement(parse_quote! { - #ident = join::<'tick, 'tick>() -> tee(); - }); - - false - } - }; - - builder.add_statement(parse_quote! { - #self_ident -> [0]#ident; - }); - - builder.add_statement(parse_quote! { - #other_ident -> [1]#ident; - }); - - Stream { - ident, - node: self.node.clone(), - next_id: self.next_id, - builders: self.builders, - is_delta: output_delta, - _phantom: PhantomData, - } + Stream::new( + self.node, + self.ir_leaves, + HfPlusNode::Join( + Box::new(self.ir_node.into_inner()), + Box::new(n.ir_node.into_inner()), + ), + ) } - pub fn anti_join(&self, n: &Stream<'a, K, W2, N>) -> Stream<'a, (K, V1), W, N> + pub fn anti_join(self, n: Stream<'a, K, W2, N>) -> Stream<'a, (K, V1), W, N> where K: Eq + Hash, { @@ -562,110 +342,48 @@ impl<'a, K, V1, W, N: Location<'a>> Stream<'a, (K, V1), W, N> { panic!("anti_join must be called on streams on the same node"); } - let next_id = { - let mut next_id = self.next_id.borrow_mut(); - let id = *next_id; - *next_id += 1; - id - }; - - let self_ident = if (self.is_delta, n.is_delta) == (true, false) { - self.ensure_concrete().ident - } else { - self.ident.clone() - }; - - let other_ident = &n.ident; - let ident = syn::Ident::new(&format!("stream_{}", next_id), Span::call_site()); - - let mut builders = self.builders.borrow_mut(); - let builder = builders - .as_mut() - .unwrap() - .entry(self.node.id()) - .or_default(); - - let output_delta = match (self.is_delta, n.is_delta) { - (true, true) => { - // we don't gain any performance by having the first be 'tick, - // just persist the second one and we get deltas out - builder.add_statement(parse_quote! { - #ident = anti_join::<'tick, 'static>() -> tee(); - }); - - true - } - (true, false) => { - // difference/anti_join<'static, _> does not replay - // but we need to re-filter every tick - builder.add_statement(parse_quote! { - #ident = anti_join::<'tick, 'tick>() -> tee(); - }); - - false - } - (false, true) => { - builder.add_statement(parse_quote! { - #ident = anti_join::<'tick, 'static>() -> tee(); - }); - - false - } - (false, false) => { - builder.add_statement(parse_quote! { - #ident = anti_join::<'tick, 'tick>() -> tee(); - }); - - false - } - }; - - builder.add_statement(parse_quote! { - #self_ident -> [pos]#ident; - }); - - builder.add_statement(parse_quote! { - #other_ident -> [neg]#ident; - }); - - Stream { - ident, - node: self.node.clone(), - next_id: self.next_id, - builders: self.builders, - is_delta: output_delta, - _phantom: PhantomData, - } + Stream::new( + self.node, + self.ir_leaves, + HfPlusNode::AntiJoin( + Box::new(self.ir_node.into_inner()), + Box::new(n.ir_node.into_inner()), + ), + ) } } impl<'a, K: Eq + Hash, V, N: Location<'a>> Stream<'a, (K, V), Windowed, N> { pub fn fold_keyed A + 'a, C: Fn(&mut A, V) + 'a>( - &self, + self, init: impl IntoQuotedMut<'a, I>, comb: impl IntoQuotedMut<'a, C>, ) -> Stream<'a, (K, A), Windowed, N> { let init = init.splice(); let comb = comb.splice(); - if self.is_delta { - self.pipeline_op(parse_quote!(fold_keyed::<'static>(#init, #comb)), false) - } else { - self.pipeline_op(parse_quote!(fold_keyed::<'tick>(#init, #comb)), false) - } + self.pipeline_op("fold_keyed", move |d| { + if d { + Some((parse_quote!(fold_keyed::<'static>(#init, #comb)), false)) + } else { + Some((parse_quote!(fold_keyed::<'tick>(#init, #comb)), false)) + } + }) } pub fn reduce_keyed( - &self, + self, comb: impl IntoQuotedMut<'a, F>, ) -> Stream<'a, (K, V), Windowed, N> { let comb = comb.splice(); - if self.is_delta { - self.pipeline_op(parse_quote!(reduce_keyed::<'static>(#comb)), false) - } else { - self.pipeline_op(parse_quote!(reduce_keyed::<'tick>(#comb)), false) - } + self.pipeline_op("reduce_keyed", move |d| { + if d { + Some((parse_quote!(reduce_keyed::<'static>(#comb)), false)) + } else { + Some((parse_quote!(reduce_keyed::<'tick>(#comb)), false)) + } + }) } } @@ -698,194 +416,112 @@ impl VisitMut for RewriteAlloc { } } -fn node_send_direct<'a, T, W, N: Location<'a>>(me: &Stream<'a, T, W, N>, sink: Pipeline) { - let self_ident = &me.ident; - - let mut builders_borrowed = me.builders.borrow_mut(); - let builders = builders_borrowed.as_mut().unwrap(); - - builders - .entry(me.node.id()) - .or_default() - .add_statement(parse_quote! { - #self_ident -> #sink; - }); -} - -fn node_send_bincode<'a, T: Serialize, W, N: Location<'a>>( - me: &Stream<'a, T, W, N>, - sink: Pipeline, -) { - let self_ident = &me.ident; - - let mut builders_borrowed = me.builders.borrow_mut(); - let builders = builders_borrowed.as_mut().unwrap(); - +fn serialize_bincode(is_demux: bool) -> Pipeline { let root = get_this_crate(); // This may fail when instantiated in an environment with different deps let mut t_type: syn::Type = syn::parse_str(std::any::type_name::()).unwrap(); RewriteAlloc {}.visit_type_mut(&mut t_type); - builders - .entry(me.node.id()) - .or_default() - .add_statement(parse_quote! { - #self_ident -> map(|data| { - #root::runtime_support::bincode::serialize::<#t_type>(&data).unwrap().into() - }) -> #sink; - }); -} - -fn cluster_demux_bincode<'a, T, W, N: Location<'a>>( - me: &Stream<'a, (u32, T), W, N>, - sink: Pipeline, -) { - let self_ident = &me.ident; - - let mut builders_borrowed = me.builders.borrow_mut(); - let builders = builders_borrowed.as_mut().unwrap(); - - let root = get_this_crate(); - - // This may fail when instantiated in an environment with different deps - let mut t_type: syn::Type = syn::parse_str(std::any::type_name::()).unwrap(); - RewriteAlloc {}.visit_type_mut(&mut t_type); - - builders - .entry(me.node.id()) - .or_default() - .add_statement(parse_quote! { - #self_ident -> map(|(id, data)| { + if is_demux { + parse_quote! { + map(|(id, data)| { (id, #root::runtime_support::bincode::serialize::<#t_type>(&data).unwrap().into()) - }) -> #sink; - }); -} - -fn node_recv_direct<'a, T, W, N: Location<'a>, N2: Location<'a>>( - me: &Stream<'a, T, W, N>, - other: &N2, - source: Pipeline, -) -> syn::Ident { - let recipient_next_id = { - let mut next_id = me.next_id.borrow_mut(); - let id = *next_id; - *next_id += 1; - id - }; - - let ident = syn::Ident::new(&format!("stream_{}", recipient_next_id), Span::call_site()); - - let mut builders_borrowed = me.builders.borrow_mut(); - let builders = builders_borrowed.as_mut().unwrap(); - - builders - .entry(other.id()) - .or_default() - .add_statement(parse_quote! { - #ident = #source -> tee(); - }); - - ident + }) + } + } else { + parse_quote! { + map(|data| { + #root::runtime_support::bincode::serialize::<#t_type>(&data).unwrap().into() + }) + } + } } -fn node_recv_bincode<'a, T1, T2: DeserializeOwned, W, N: Location<'a>, N2: Location<'a>>( - me: &Stream<'a, T1, W, N>, - other: &N2, - source: Pipeline, - tagged: bool, -) -> syn::Ident { - let recipient_next_id = { - let mut next_id = me.next_id.borrow_mut(); - let id = *next_id; - *next_id += 1; - id - }; - - let ident = syn::Ident::new(&format!("stream_{}", recipient_next_id), Span::call_site()); - - let mut builders_borrowed = me.builders.borrow_mut(); - let builders = builders_borrowed.as_mut().unwrap(); - +fn deserialize_bincode(tagged: bool) -> Pipeline { let root = get_this_crate(); // This may fail when instantiated in an environment with different deps let mut t_type: syn::Type = syn::parse_str(std::any::type_name::()).unwrap(); RewriteAlloc {}.visit_type_mut(&mut t_type); - builders.entry(other.id()).or_default().add_statement({ - if tagged { - parse_quote! { - #ident = #source -> map(|res| { - let (id, b) = res.unwrap(); - (id, #root::runtime_support::bincode::deserialize::<#t_type>(&b).unwrap()) - }) -> tee(); - } - } else { - parse_quote! { - #ident = #source -> map(|res| { - #root::runtime_support::bincode::deserialize::<#t_type>(&res.unwrap()).unwrap() - }) -> tee(); - } + if tagged { + parse_quote! { + map(|res| { + let (id, b) = res.unwrap(); + (id, #root::runtime_support::bincode::deserialize::<#t_type>(&b).unwrap()) + }) } - }); - - ident + } else { + parse_quote! { + map(|res| { + #root::runtime_support::bincode::deserialize::<#t_type>(&res.unwrap()).unwrap() + }) + } + } } impl<'a, W, N: Location<'a>> Stream<'a, Bytes, W, N> { pub fn send_bytes>( - &self, + self, other: &N2, ) -> Stream<'a, Result, Async, N2> where N: HfSendOneToOne<'a, N2>, { let send_port = self.node.next_port(); - node_send_direct(self, self.node.gen_sink_statement(&send_port)); + let sink_expr = self.node.gen_sink_statement(&send_port).into(); let recv_port = other.next_port(); - let ident = node_recv_direct(self, other, N::gen_source_statement(other, &recv_port)); + let source_expr = N::gen_source_statement(other, &recv_port).into(); self.node.connect(other, &send_port, &recv_port); - Stream { - ident, - node: other.clone(), - next_id: self.next_id, - builders: self.builders, - is_delta: self.is_delta, - _phantom: PhantomData, - } + Stream::new( + other.clone(), + self.ir_leaves, + HfPlusNode::Network { + to_location: other.id(), + serialize_pipeline: None, + sink_expr, + source_expr, + deserialize_pipeline: None, + input: Box::new(self.ir_node.into_inner()), + }, + ) } pub fn send_bytes_tagged>( - &self, + self, other: &N2, ) -> Stream<'a, Result<(u32, BytesMut), io::Error>, Async, N2> where N: HfSendManyToOne<'a, N2>, { let send_port = self.node.next_port(); - node_send_direct(self, self.node.gen_sink_statement(&send_port)); + let sink_expr = self.node.gen_sink_statement(&send_port).into(); let recv_port = other.next_port(); - let ident = node_recv_direct(self, other, N::gen_source_statement(other, &recv_port)); + let source_expr = N::gen_source_statement(other, &recv_port).into(); self.node.connect(other, &send_port, &recv_port); - Stream { - ident, - node: other.clone(), - next_id: self.next_id, - builders: self.builders, - is_delta: self.is_delta, - _phantom: PhantomData, - } + Stream::new( + other.clone(), + self.ir_leaves, + HfPlusNode::Network { + to_location: other.id(), + serialize_pipeline: None, + sink_expr, + source_expr, + deserialize_pipeline: None, + input: Box::new(self.ir_node.into_inner()), + }, + ) } pub fn send_bytes_interleaved>( - &self, + self, other: &N2, ) -> Stream<'a, Result, Async, N2> where @@ -895,7 +531,7 @@ impl<'a, W, N: Location<'a>> Stream<'a, Bytes, W, N> { } pub fn broadcast_bytes + Cluster<'a>>( - &self, + self, other: &N2, ) -> Stream<'a, Result, Async, N2> where @@ -903,12 +539,12 @@ impl<'a, W, N: Location<'a>> Stream<'a, Bytes, W, N> { { let other_ids = self.node.source_iter(other.ids()).cloned().all_ticks(); other_ids - .cross_product(&self.assume_windowed()) + .cross_product(self.assume_windowed()) .demux_bytes(other) } pub fn broadcast_bytes_tagged + Cluster<'a>>( - &self, + self, other: &N2, ) -> Stream<'a, Result<(u32, BytesMut), io::Error>, Async, N2> where @@ -916,12 +552,12 @@ impl<'a, W, N: Location<'a>> Stream<'a, Bytes, W, N> { { let other_ids = self.node.source_iter(other.ids()).cloned().all_ticks(); other_ids - .cross_product(&self.assume_windowed()) + .cross_product(self.assume_windowed()) .demux_bytes_tagged(other) } pub fn broadcast_bytes_interleaved + Cluster<'a>>( - &self, + self, other: &N2, ) -> Stream<'a, Result, Async, N2> where @@ -933,64 +569,66 @@ impl<'a, W, N: Location<'a>> Stream<'a, Bytes, W, N> { } impl<'a, T: Serialize + DeserializeOwned, W, N: Location<'a>> Stream<'a, T, W, N> { - pub fn send_bincode>(&self, other: &N2) -> Stream<'a, T, Async, N2> + pub fn send_bincode>(self, other: &N2) -> Stream<'a, T, Async, N2> where N: HfSendOneToOne<'a, N2>, { let send_port = self.node.next_port(); - node_send_bincode(self, self.node.gen_sink_statement(&send_port)); + let serialize_pipeline = Some(serialize_bincode::(false)); + let sink_expr = self.node.gen_sink_statement(&send_port).into(); let recv_port = other.next_port(); - let ident = node_recv_bincode::<_, T, _, _, _>( - self, - other, - N::gen_source_statement(other, &recv_port), - false, - ); + let deserialize_pipeline = Some(deserialize_bincode::(false)); + let source_expr = N::gen_source_statement(other, &recv_port).into(); self.node.connect(other, &send_port, &recv_port); - Stream { - ident, - node: other.clone(), - next_id: self.next_id, - builders: self.builders, - is_delta: self.is_delta, - _phantom: PhantomData, - } + Stream::new( + other.clone(), + self.ir_leaves, + HfPlusNode::Network { + to_location: other.id(), + serialize_pipeline, + sink_expr, + source_expr, + deserialize_pipeline, + input: Box::new(self.ir_node.into_inner()), + }, + ) } pub fn send_bincode_tagged>( - &self, + self, other: &N2, ) -> Stream<'a, (u32, T), Async, N2> where N: HfSendManyToOne<'a, N2>, { let send_port = self.node.next_port(); - node_send_bincode(self, self.node.gen_sink_statement(&send_port)); + let serialize_pipeline = Some(serialize_bincode::(false)); + let sink_expr = self.node.gen_sink_statement(&send_port).into(); let recv_port = other.next_port(); - let ident = node_recv_bincode::<_, T, _, _, _>( - self, - other, - N::gen_source_statement(other, &recv_port), - true, - ); + let deserialize_pipeline = Some(deserialize_bincode::(true)); + let source_expr = N::gen_source_statement(other, &recv_port).into(); self.node.connect(other, &send_port, &recv_port); - Stream { - ident, - node: other.clone(), - next_id: self.next_id, - builders: self.builders, - is_delta: self.is_delta, - _phantom: PhantomData, - } - } - - pub fn send_bincode_interleaved>(&self, other: &N2) -> Stream<'a, T, Async, N2> + Stream::new( + other.clone(), + self.ir_leaves, + HfPlusNode::Network { + to_location: other.id(), + serialize_pipeline, + sink_expr, + source_expr, + deserialize_pipeline, + input: Box::new(self.ir_node.into_inner()), + }, + ) + } + + pub fn send_bincode_interleaved>(self, other: &N2) -> Stream<'a, T, Async, N2> where N: HfSendManyToOne<'a, N2>, { @@ -998,7 +636,7 @@ impl<'a, T: Serialize + DeserializeOwned, W, N: Location<'a>> Stream<'a, T, W, N } pub fn broadcast_bincode + Cluster<'a>>( - &self, + self, other: &N2, ) -> Stream<'a, T, Async, N2> where @@ -1006,12 +644,12 @@ impl<'a, T: Serialize + DeserializeOwned, W, N: Location<'a>> Stream<'a, T, W, N { let other_ids = self.node.source_iter(other.ids()).cloned().all_ticks(); other_ids - .cross_product(&self.assume_windowed()) + .cross_product(self.assume_windowed()) .demux_bincode(other) } pub fn broadcast_bincode_tagged + Cluster<'a>>( - &self, + self, other: &N2, ) -> Stream<'a, (u32, T), Async, N2> where @@ -1019,12 +657,12 @@ impl<'a, T: Serialize + DeserializeOwned, W, N: Location<'a>> Stream<'a, T, W, N { let other_ids = self.node.source_iter(other.ids()).cloned().all_ticks(); other_ids - .cross_product(&self.assume_windowed()) + .cross_product(self.assume_windowed()) .demux_bincode_tagged(other) } pub fn broadcast_bincode_interleaved + Cluster<'a>>( - &self, + self, other: &N2, ) -> Stream<'a, T, Async, N2> where @@ -1036,88 +674,97 @@ impl<'a, T: Serialize + DeserializeOwned, W, N: Location<'a>> Stream<'a, T, W, N impl<'a, W, N: Location<'a>> Stream<'a, (u32, Bytes), W, N> { pub fn demux_bytes>( - &self, + self, other: &N2, ) -> Stream<'a, Result, Async, N2> where N: HfSendOneToMany<'a, N2>, { let send_port = self.node.next_port(); - node_send_direct(self, self.node.gen_sink_statement(&send_port)); + let sink_expr = self.node.gen_sink_statement(&send_port).into(); let recv_port = other.next_port(); - let ident = node_recv_direct(self, other, N::gen_source_statement(other, &recv_port)); + let source_expr = N::gen_source_statement(other, &recv_port).into(); self.node.connect(other, &send_port, &recv_port); - Stream { - ident, - node: other.clone(), - next_id: self.next_id, - builders: self.builders, - is_delta: self.is_delta, - _phantom: PhantomData, - } + Stream::new( + other.clone(), + self.ir_leaves, + HfPlusNode::Network { + to_location: other.id(), + serialize_pipeline: None, + sink_expr, + source_expr, + deserialize_pipeline: None, + input: Box::new(self.ir_node.into_inner()), + }, + ) } } impl<'a, T: Serialize + DeserializeOwned, W, N: Location<'a>> Stream<'a, (u32, T), W, N> { - pub fn demux_bincode>(&self, other: &N2) -> Stream<'a, T, Async, N2> + pub fn demux_bincode>(self, other: &N2) -> Stream<'a, T, Async, N2> where N: HfSendOneToMany<'a, N2>, { let send_port = self.node.next_port(); - cluster_demux_bincode(self, self.node.gen_sink_statement(&send_port)); + let serialize_pipeline = Some(serialize_bincode::(true)); + let sink_expr = self.node.gen_sink_statement(&send_port).into(); let recv_port = other.next_port(); - let ident = node_recv_bincode::<_, T, _, _, _>( - self, - other, - N::gen_source_statement(other, &recv_port), - false, - ); + let deserialize_pipeline = Some(deserialize_bincode::(false)); + let source_expr = N::gen_source_statement(other, &recv_port).into(); self.node.connect(other, &send_port, &recv_port); - Stream { - ident, - node: other.clone(), - next_id: self.next_id, - builders: self.builders, - is_delta: self.is_delta, - _phantom: PhantomData, - } + Stream::new( + other.clone(), + self.ir_leaves, + HfPlusNode::Network { + to_location: other.id(), + serialize_pipeline, + sink_expr, + source_expr, + deserialize_pipeline, + input: Box::new(self.ir_node.into_inner()), + }, + ) } } impl<'a, W, N: Location<'a>> Stream<'a, (u32, Bytes), W, N> { pub fn demux_bytes_tagged>( - &self, + self, other: &N2, ) -> Stream<'a, Result<(u32, BytesMut), io::Error>, Async, N2> where N: HfSendManyToMany<'a, N2>, { let send_port = self.node.next_port(); - node_send_direct(self, self.node.gen_sink_statement(&send_port)); + let sink_expr = self.node.gen_sink_statement(&send_port).into(); let recv_port = other.next_port(); - let ident = node_recv_direct(self, other, N::gen_source_statement(other, &recv_port)); + let source_expr = N::gen_source_statement(other, &recv_port).into(); self.node.connect(other, &send_port, &recv_port); - Stream { - ident, - node: other.clone(), - next_id: self.next_id, - builders: self.builders, - is_delta: self.is_delta, - _phantom: PhantomData, - } + Stream::new( + other.clone(), + self.ir_leaves, + HfPlusNode::Network { + to_location: other.id(), + serialize_pipeline: None, + sink_expr, + source_expr, + deserialize_pipeline: None, + input: Box::new(self.ir_node.into_inner()), + }, + ) } pub fn demux_bytes_interleaved>( - &self, + self, other: &N2, ) -> Stream<'a, Result, Async, N2> where @@ -1130,39 +777,37 @@ impl<'a, W, N: Location<'a>> Stream<'a, (u32, Bytes), W, N> { impl<'a, T: Serialize + DeserializeOwned, W, N: Location<'a>> Stream<'a, (u32, T), W, N> { pub fn demux_bincode_tagged>( - &self, + self, other: &N2, ) -> Stream<'a, (u32, T), Async, N2> where N: HfSendManyToMany<'a, N2>, { let send_port = self.node.next_port(); - cluster_demux_bincode(self, self.node.gen_sink_statement(&send_port)); + let serialize_pipeline = Some(serialize_bincode::(true)); + let sink_expr = self.node.gen_sink_statement(&send_port).into(); let recv_port = other.next_port(); - let ident = node_recv_bincode::<_, T, _, _, _>( - self, - other, - N::gen_source_statement(other, &recv_port), - true, - ); + let deserialize_pipeline = Some(deserialize_bincode::(true)); + let source_expr = N::gen_source_statement(other, &recv_port).into(); self.node.connect(other, &send_port, &recv_port); - Stream { - ident, - node: other.clone(), - next_id: self.next_id, - builders: self.builders, - is_delta: self.is_delta, - _phantom: PhantomData, - } - } - - pub fn demux_bincode_interleaved>( - &self, - other: &N2, - ) -> Stream<'a, T, Async, N2> + Stream::new( + other.clone(), + self.ir_leaves, + HfPlusNode::Network { + to_location: other.id(), + serialize_pipeline, + sink_expr, + source_expr, + deserialize_pipeline, + input: Box::new(self.ir_node.into_inner()), + }, + ) + } + + pub fn demux_bincode_interleaved>(self, other: &N2) -> Stream<'a, T, Async, N2> where N: HfSendManyToMany<'a, N2>, { diff --git a/hydroflow_plus_test/src/cluster.rs b/hydroflow_plus_test/src/cluster.rs index d7cdfe182f16..2219501e4f41 100644 --- a/hydroflow_plus_test/src/cluster.rs +++ b/hydroflow_plus_test/src/cluster.rs @@ -14,7 +14,7 @@ pub fn simple_cluster<'a, D: Deploy<'a>>( let numbers = process.source_iter(q!(0..5)); let ids = process.source_iter(cluster.ids()).map(q!(|&id| id)); - ids.cross_product(&numbers) + ids.cross_product(numbers) .map(q!(|(id, n)| (id, (id, n)))) .demux_bincode(&cluster) .inspect(q!(|n| println!("cluster received: {:?}", n))) @@ -161,6 +161,7 @@ mod tests { use hydroflow_plus_cli_integration::{ DeployClusterSpec, DeployCrateWrapper, DeployProcessSpec, }; + use stageleft::RuntimeData; #[tokio::test] async fn simple_cluster() { @@ -190,6 +191,8 @@ mod tests { }), ); + insta::assert_debug_snapshot!(builder.ir()); + let mut deployment = deployment.into_inner(); deployment.deploy().await.unwrap(); @@ -244,6 +247,8 @@ mod tests { }), ); + insta::assert_debug_snapshot!(builder.ir()); + let mut deployment = deployment.into_inner(); deployment.deploy().await.unwrap(); @@ -272,4 +277,40 @@ mod tests { } } } + + #[test] + fn map_reduce_ir() { + let builder = hydroflow_plus::FlowBuilder::new(); + let _ = super::map_reduce( + &builder, + &RuntimeData::new("FAKE"), + &RuntimeData::new("FAKE"), + ); + + insta::assert_debug_snapshot!(builder.ir()); + + for (id, ir) in builder.hydroflow_ir() { + insta::with_settings!({snapshot_suffix => format!("surface_graph_{id}")}, { + insta::assert_display_snapshot!(ir.surface_syntax_string()); + }); + } + } + + #[test] + fn compute_pi_ir() { + let builder = hydroflow_plus::FlowBuilder::new(); + let _ = super::compute_pi( + &builder, + &RuntimeData::new("FAKE"), + &RuntimeData::new("FAKE"), + ); + + insta::assert_debug_snapshot!(builder.ir()); + + for (id, ir) in builder.hydroflow_ir() { + insta::with_settings!({snapshot_suffix => format!("surface_graph_{id}")}, { + insta::assert_display_snapshot!(ir.surface_syntax_string()); + }); + } + } } diff --git a/hydroflow_plus_test/src/first_ten.rs b/hydroflow_plus_test/src/first_ten.rs index ff2407613588..cda7ddb35a6e 100644 --- a/hydroflow_plus_test/src/first_ten.rs +++ b/hydroflow_plus_test/src/first_ten.rs @@ -68,6 +68,8 @@ mod tests { }), ); + insta::assert_debug_snapshot!(builder.ir()); + deployment.deploy().await.unwrap(); let second_node_stdout = second_node.stdout().await; diff --git a/hydroflow_plus_test/src/lib.rs b/hydroflow_plus_test/src/lib.rs index 11883c8fbd9c..e3f4c5b816f8 100644 --- a/hydroflow_plus_test/src/lib.rs +++ b/hydroflow_plus_test/src/lib.rs @@ -23,12 +23,12 @@ pub fn teed_join<'a, S: Stream + Unpin + 'a>( let node_one = flow.process(&()); let source = node_zero.source_stream(input_stream); - let map1 = source.map(q!(|v| (v + 1, ()))); + let map1 = source.clone().map(q!(|v| (v + 1, ()))); let map2 = source.map(q!(|v| (v - 1, ()))); - let joined = map1.join(&map2).map(q!(|t| t.0)); + let joined = map1.join(map2).map(q!(|t| t.0)); - joined.for_each(q!(|v| { + joined.clone().for_each(q!(|v| { output.send(v).unwrap(); })); @@ -64,7 +64,7 @@ pub fn chat_app<'a>( messages.tick_batch() }; - let mut joined = users.cross_product(&messages); + let mut joined = users.cross_product(messages); if replay_messages { joined = joined.delta(); } @@ -90,12 +90,13 @@ pub fn graph_reachability<'a>( let (set_reached_cycle, reached_cycle) = process.cycle(); - let reached = roots.union(&reached_cycle); + let reached = roots.union(reached_cycle); let reachable = reached + .clone() .map(q!(|r| (r, ()))) - .join(&edges) + .join(edges) .map(q!(|(_from, (_, to))| to)); - set_reached_cycle.complete(&reachable); + set_reached_cycle.complete(reachable); reached.tick_batch().unique().for_each(q!(|v| { reached_out.send(v).unwrap(); diff --git a/hydroflow_plus_test/src/negation.rs b/hydroflow_plus_test/src/negation.rs index 80e3989be03a..5c5a2067c133 100644 --- a/hydroflow_plus_test/src/negation.rs +++ b/hydroflow_plus_test/src/negation.rs @@ -21,7 +21,7 @@ pub fn test_difference<'a>( source2 = source2.all_ticks(); } - source.filter_not_in(&source2).for_each(q!(|v| { + source.filter_not_in(source2).for_each(q!(|v| { output.send(v).unwrap(); })); @@ -48,7 +48,7 @@ pub fn test_anti_join<'a>( } // TODO(shadaj): inference fails without a for_each type annotation here - source.anti_join(&source2).for_each(q!(|v: (u32, u32)| { + source.anti_join(source2).for_each(q!(|v: (u32, u32)| { output.send(v.0).unwrap(); })); diff --git a/hydroflow_plus_test/src/networked.rs b/hydroflow_plus_test/src/networked.rs index cef6e9fe012a..5b697868f651 100644 --- a/hydroflow_plus_test/src/networked.rs +++ b/hydroflow_plus_test/src/networked.rs @@ -96,6 +96,8 @@ mod tests { }), ); + insta::assert_debug_snapshot!(builder.ir()); + let mut deployment = deployment.into_inner(); let port_to_zero = io diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__cluster__tests__compute_pi_ir.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__cluster__tests__compute_pi_ir.snap new file mode 100644 index 000000000000..9613c1f64889 --- /dev/null +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__cluster__tests__compute_pi_ir.snap @@ -0,0 +1,77 @@ +--- +source: hydroflow_plus_test/src/cluster.rs +expression: builder.ir() +--- +[ + ForEach { + f: { use crate :: __staged :: cluster :: * ; | (inside , total) | { println ! ("pi: {} ({} trials)" , 4.0 * inside as f64 / total as f64 , total) ; } }, + input: Map { + f: { use hydroflow_plus :: __staged :: stream :: * ; | (a , _) | a }, + input: CrossProduct( + PipelineOp { + kind: "reduce", + gen_pipeline: , + input: Persist( + Map { + f: { use hydroflow_plus :: __staged :: stream :: * ; | (_ , b) | b }, + input: Network { + to_location: 1, + serialize_pipeline: Some( + Operator( + Operator { + path: "map", + args: [ + "| data | { hydroflow_plus :: runtime_support :: bincode :: serialize :: < (u64 , u64) > (& data) . unwrap () . into () }", + ], + }, + ), + ), + sink_expr: { use hydroflow_plus_cli_integration :: __staged :: runtime :: * ; let self_cli = FAKE ; let port = "port_0" ; { self_cli . port (port) . connect_local_blocking :: < ConnectedDirect > () . into_sink () } }, + source_expr: { use hydroflow_plus_cli_integration :: __staged :: runtime :: * ; let self_cli = FAKE ; let port = "port_0" ; { self_cli . port (port) . connect_local_blocking :: < ConnectedTagged < ConnectedDirect > > () . into_source () } }, + deserialize_pipeline: Some( + Operator( + Operator { + path: "map", + args: [ + "| res | { let (id , b) = res . unwrap () ; (id , hydroflow_plus :: runtime_support :: bincode :: deserialize :: < (u64 , u64) > (& b) . unwrap ()) }", + ], + }, + ), + ), + input: PipelineOp { + kind: "fold", + gen_pipeline: , + input: Map { + f: { use crate :: __staged :: cluster :: * ; | (x , y) | x * x + y * y < 1.0 }, + input: Map { + f: { use crate :: __staged :: cluster :: * ; | _ | rand :: random :: < (f64 , f64) > () }, + input: Map { + f: { use hydroflow_plus :: __staged :: location :: * ; | _ | () }, + input: PipelineOp { + kind: "flat_map", + gen_pipeline: , + input: Source { + source: Spin, + produces_delta: false, + location_id: 0, + }, + }, + }, + }, + }, + }, + }, + }, + ), + }, + Source { + source: Interval( + { use crate :: __staged :: cluster :: * ; Duration :: from_secs (1) }, + ), + produces_delta: false, + location_id: 1, + }, + ), + }, + }, +] diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__cluster__tests__compute_pi_ir@surface_graph_0.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__cluster__tests__compute_pi_ir@surface_graph_0.snap new file mode 100644 index 000000000000..b365e9e82c1c --- /dev/null +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__cluster__tests__compute_pi_ir@surface_graph_0.snap @@ -0,0 +1,21 @@ +--- +source: hydroflow_plus_test/src/cluster.rs +expression: ir.surface_syntax_string() +--- +1v1 = spin (); +2v1 = flat_map ({ use hydroflow_plus :: __staged :: location :: * ; let batch_size = 8192usize ; move | _ | 0 .. batch_size }); +3v1 = map ({ use hydroflow_plus :: __staged :: location :: * ; | _ | () }); +4v1 = map ({ use crate :: __staged :: cluster :: * ; | _ | rand :: random :: < (f64 , f64) > () }); +5v1 = map ({ use crate :: __staged :: cluster :: * ; | (x , y) | x * x + y * y < 1.0 }); +6v1 = fold :: < 'tick > ({ use crate :: __staged :: cluster :: * ; | | (0u64 , 0u64) } , { use crate :: __staged :: cluster :: * ; | (inside , total) , sample_inside | { if sample_inside { * inside += 1 ; } * total += 1 ; } }); +7v1 = map (| data | { hydroflow_plus :: runtime_support :: bincode :: serialize :: < (u64 , u64) > (& data) . unwrap () . into () }); +8v1 = dest_sink ({ use hydroflow_plus_cli_integration :: __staged :: runtime :: * ; let self_cli = FAKE ; let port = "port_0" ; { self_cli . port (port) . connect_local_blocking :: < ConnectedDirect > () . into_sink () } }); + +1v1 -> 2v1; +2v1 -> 3v1; +3v1 -> 4v1; +4v1 -> 5v1; +5v1 -> 6v1; +7v1 -> 8v1; +6v1 -> 7v1; + diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__cluster__tests__compute_pi_ir@surface_graph_1.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__cluster__tests__compute_pi_ir@surface_graph_1.snap new file mode 100644 index 000000000000..92c1279cb8cf --- /dev/null +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__cluster__tests__compute_pi_ir@surface_graph_1.snap @@ -0,0 +1,21 @@ +--- +source: hydroflow_plus_test/src/cluster.rs +expression: ir.surface_syntax_string() +--- +1v1 = source_stream ({ use hydroflow_plus_cli_integration :: __staged :: runtime :: * ; let self_cli = FAKE ; let port = "port_0" ; { self_cli . port (port) . connect_local_blocking :: < ConnectedTagged < ConnectedDirect > > () . into_source () } }); +2v1 = map (| res | { let (id , b) = res . unwrap () ; (id , hydroflow_plus :: runtime_support :: bincode :: deserialize :: < (u64 , u64) > (& b) . unwrap ()) }); +3v1 = map ({ use hydroflow_plus :: __staged :: stream :: * ; | (_ , b) | b }); +4v1 = reduce :: < 'static > ({ use crate :: __staged :: cluster :: * ; | (inside , total) , (inside_batch , total_batch) | { * inside += inside_batch ; * total += total_batch ; } }); +5v1 = source_interval ({ use crate :: __staged :: cluster :: * ; Duration :: from_secs (1) }); +6v1 = cross_join :: < 'tick , 'tick > (); +7v1 = map ({ use hydroflow_plus :: __staged :: stream :: * ; | (a , _) | a }); +8v1 = for_each ({ use crate :: __staged :: cluster :: * ; | (inside , total) | { println ! ("pi: {} ({} trials)" , 4.0 * inside as f64 / total as f64 , total) ; } }); + +1v1 -> 2v1; +2v1 -> 3v1; +3v1 -> 4v1; +4v1 -> 6v1; +5v1 -> 6v1; +6v1 -> 7v1; +7v1 -> 8v1; + diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__cluster__tests__many_to_many.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__cluster__tests__many_to_many.snap new file mode 100644 index 000000000000..d05891677d30 --- /dev/null +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__cluster__tests__many_to_many.snap @@ -0,0 +1,56 @@ +--- +source: hydroflow_plus_test/src/cluster.rs +expression: builder.ir() +--- +[ + ForEach { + f: { use crate :: __staged :: cluster :: * ; | n | println ! ("cluster received: {:?}" , n) }, + input: Network { + to_location: 0, + serialize_pipeline: Some( + Operator( + Operator { + path: "map", + args: [ + "| (id , data) | { (id , hydroflow_plus :: runtime_support :: bincode :: serialize :: < i32 > (& data) . unwrap () . into ()) }", + ], + }, + ), + ), + sink_expr: null, + source_expr: null, + deserialize_pipeline: Some( + Operator( + Operator { + path: "map", + args: [ + "| res | { let (id , b) = res . unwrap () ; (id , hydroflow_plus :: runtime_support :: bincode :: deserialize :: < i32 > (& b) . unwrap ()) }", + ], + }, + ), + ), + input: CrossProduct( + Persist( + PipelineOp { + kind: "cloned", + gen_pipeline: , + input: Source { + source: Iter( + { use hydroflow_plus_cli_integration :: __staged :: deploy :: * ; panic ! () }, + ), + produces_delta: false, + location_id: 0, + }, + }, + ), + Source { + source: Iter( + { use crate :: __staged :: cluster :: * ; 0 .. 2 }, + ), + produces_delta: false, + location_id: 0, + }, + ), + }, + }, +] diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__cluster__tests__map_reduce_ir.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__cluster__tests__map_reduce_ir.snap new file mode 100644 index 000000000000..8cec2daa90ee --- /dev/null +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__cluster__tests__map_reduce_ir.snap @@ -0,0 +1,96 @@ +--- +source: hydroflow_plus_test/src/cluster.rs +expression: builder.ir() +--- +[ + ForEach { + f: { use crate :: __staged :: cluster :: * ; | (string , count) | println ! ("{}: {}" , string , count) }, + input: PipelineOp { + kind: "reduce_keyed", + gen_pipeline: , + input: Persist( + Map { + f: { use hydroflow_plus :: __staged :: stream :: * ; | (_ , b) | b }, + input: Network { + to_location: 0, + serialize_pipeline: Some( + Operator( + Operator { + path: "map", + args: [ + "| data | { hydroflow_plus :: runtime_support :: bincode :: serialize :: < (std :: string :: String , i32) > (& data) . unwrap () . into () }", + ], + }, + ), + ), + sink_expr: { use hydroflow_plus_cli_integration :: __staged :: runtime :: * ; let self_cli = FAKE ; let port = "port_1" ; { self_cli . port (port) . connect_local_blocking :: < ConnectedDirect > () . into_sink () } }, + source_expr: { use hydroflow_plus_cli_integration :: __staged :: runtime :: * ; let self_cli = FAKE ; let port = "port_1" ; { self_cli . port (port) . connect_local_blocking :: < ConnectedTagged < ConnectedDirect > > () . into_source () } }, + deserialize_pipeline: Some( + Operator( + Operator { + path: "map", + args: [ + "| res | { let (id , b) = res . unwrap () ; (id , hydroflow_plus :: runtime_support :: bincode :: deserialize :: < (std :: string :: String , i32) > (& b) . unwrap ()) }", + ], + }, + ), + ), + input: PipelineOp { + kind: "inspect", + gen_pipeline: , + input: PipelineOp { + kind: "fold_keyed", + gen_pipeline: , + input: Map { + f: { use crate :: __staged :: cluster :: * ; | string | (string , ()) }, + input: Network { + to_location: 1, + serialize_pipeline: Some( + Operator( + Operator { + path: "map", + args: [ + "| (id , data) | { (id , hydroflow_plus :: runtime_support :: bincode :: serialize :: < std :: string :: String > (& data) . unwrap () . into ()) }", + ], + }, + ), + ), + sink_expr: { use hydroflow_plus_cli_integration :: __staged :: runtime :: * ; let self_cli = FAKE ; let port = "port_0" ; { self_cli . port (port) . connect_local_blocking :: < ConnectedDemux < ConnectedDirect > > () . into_sink () } }, + source_expr: { use hydroflow_plus_cli_integration :: __staged :: runtime :: * ; let self_cli = FAKE ; let port = "port_0" ; { self_cli . port (port) . connect_local_blocking :: < ConnectedDirect > () . into_source () } }, + deserialize_pipeline: Some( + Operator( + Operator { + path: "map", + args: [ + "| res | { hydroflow_plus :: runtime_support :: bincode :: deserialize :: < std :: string :: String > (& res . unwrap ()) . unwrap () }", + ], + }, + ), + ), + input: Map { + f: { use crate :: __staged :: cluster :: * ; let all_ids_vec = { use hydroflow_plus_cli_integration :: __staged :: runtime :: * ; let cli = FAKE ; let self_id = 1usize ; cli . meta . clusters . get (& self_id) . unwrap () } ; | (i , w) | ((i % all_ids_vec . len ()) as u32 , w) }, + input: PipelineOp { + kind: "enumerate", + gen_pipeline: , + input: Map { + f: { use crate :: __staged :: cluster :: * ; | s | s . to_string () }, + input: Source { + source: Iter( + { use crate :: __staged :: cluster :: * ; vec ! ["abc" , "abc" , "xyz" , "abc"] }, + ), + produces_delta: false, + location_id: 0, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + ), + }, + }, +] diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__cluster__tests__map_reduce_ir@surface_graph_0.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__cluster__tests__map_reduce_ir@surface_graph_0.snap new file mode 100644 index 000000000000..60e21d0921f7 --- /dev/null +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__cluster__tests__map_reduce_ir@surface_graph_0.snap @@ -0,0 +1,26 @@ +--- +source: hydroflow_plus_test/src/cluster.rs +expression: ir.surface_syntax_string() +--- +1v1 = source_iter ({ use crate :: __staged :: cluster :: * ; vec ! ["abc" , "abc" , "xyz" , "abc"] }); +2v1 = map ({ use crate :: __staged :: cluster :: * ; | s | s . to_string () }); +3v1 = enumerate (); +4v1 = map ({ use crate :: __staged :: cluster :: * ; let all_ids_vec = { use hydroflow_plus_cli_integration :: __staged :: runtime :: * ; let cli = FAKE ; let self_id = 1usize ; cli . meta . clusters . get (& self_id) . unwrap () } ; | (i , w) | ((i % all_ids_vec . len ()) as u32 , w) }); +5v1 = map (| (id , data) | { (id , hydroflow_plus :: runtime_support :: bincode :: serialize :: < std :: string :: String > (& data) . unwrap () . into ()) }); +6v1 = dest_sink ({ use hydroflow_plus_cli_integration :: __staged :: runtime :: * ; let self_cli = FAKE ; let port = "port_0" ; { self_cli . port (port) . connect_local_blocking :: < ConnectedDemux < ConnectedDirect > > () . into_sink () } }); +7v1 = source_stream ({ use hydroflow_plus_cli_integration :: __staged :: runtime :: * ; let self_cli = FAKE ; let port = "port_1" ; { self_cli . port (port) . connect_local_blocking :: < ConnectedTagged < ConnectedDirect > > () . into_source () } }); +8v1 = map (| res | { let (id , b) = res . unwrap () ; (id , hydroflow_plus :: runtime_support :: bincode :: deserialize :: < (std :: string :: String , i32) > (& b) . unwrap ()) }); +9v1 = map ({ use hydroflow_plus :: __staged :: stream :: * ; | (_ , b) | b }); +10v1 = reduce_keyed :: < 'static > ({ use crate :: __staged :: cluster :: * ; | total , count | * total += count }); +11v1 = for_each ({ use crate :: __staged :: cluster :: * ; | (string , count) | println ! ("{}: {}" , string , count) }); + +1v1 -> 2v1; +2v1 -> 3v1; +3v1 -> 4v1; +5v1 -> 6v1; +4v1 -> 5v1; +7v1 -> 8v1; +8v1 -> 9v1; +9v1 -> 10v1; +10v1 -> 11v1; + diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__cluster__tests__map_reduce_ir@surface_graph_1.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__cluster__tests__map_reduce_ir@surface_graph_1.snap new file mode 100644 index 000000000000..935d5acbecba --- /dev/null +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__cluster__tests__map_reduce_ir@surface_graph_1.snap @@ -0,0 +1,19 @@ +--- +source: hydroflow_plus_test/src/cluster.rs +expression: ir.surface_syntax_string() +--- +1v1 = source_stream ({ use hydroflow_plus_cli_integration :: __staged :: runtime :: * ; let self_cli = FAKE ; let port = "port_0" ; { self_cli . port (port) . connect_local_blocking :: < ConnectedDirect > () . into_source () } }); +2v1 = map (| res | { hydroflow_plus :: runtime_support :: bincode :: deserialize :: < std :: string :: String > (& res . unwrap ()) . unwrap () }); +3v1 = map ({ use crate :: __staged :: cluster :: * ; | string | (string , ()) }); +4v1 = fold_keyed :: < 'tick > ({ use crate :: __staged :: cluster :: * ; | | 0 } , { use crate :: __staged :: cluster :: * ; | count , _ | * count += 1 }); +5v1 = inspect ({ use crate :: __staged :: cluster :: * ; | (string , count) | println ! ("partition count: {} - {}" , string , count) }); +6v1 = map (| data | { hydroflow_plus :: runtime_support :: bincode :: serialize :: < (std :: string :: String , i32) > (& data) . unwrap () . into () }); +7v1 = dest_sink ({ use hydroflow_plus_cli_integration :: __staged :: runtime :: * ; let self_cli = FAKE ; let port = "port_1" ; { self_cli . port (port) . connect_local_blocking :: < ConnectedDirect > () . into_sink () } }); + +1v1 -> 2v1; +2v1 -> 3v1; +3v1 -> 4v1; +4v1 -> 5v1; +6v1 -> 7v1; +5v1 -> 6v1; + diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__cluster__tests__simple_cluster.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__cluster__tests__simple_cluster.snap new file mode 100644 index 000000000000..b30d85c3417f --- /dev/null +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__cluster__tests__simple_cluster.snap @@ -0,0 +1,85 @@ +--- +source: hydroflow_plus_test/src/cluster.rs +expression: builder.ir() +--- +[ + ForEach { + f: { use crate :: __staged :: cluster :: * ; | (id , d) | println ! ("node received: ({}, {:?})" , id , d) }, + input: Network { + to_location: 0, + serialize_pipeline: Some( + Operator( + Operator { + path: "map", + args: [ + "| data | { hydroflow_plus :: runtime_support :: bincode :: serialize :: < (u32 , i32) > (& data) . unwrap () . into () }", + ], + }, + ), + ), + sink_expr: null, + source_expr: null, + deserialize_pipeline: Some( + Operator( + Operator { + path: "map", + args: [ + "| res | { let (id , b) = res . unwrap () ; (id , hydroflow_plus :: runtime_support :: bincode :: deserialize :: < (u32 , i32) > (& b) . unwrap ()) }", + ], + }, + ), + ), + input: PipelineOp { + kind: "inspect", + gen_pipeline: , + input: Network { + to_location: 1, + serialize_pipeline: Some( + Operator( + Operator { + path: "map", + args: [ + "| (id , data) | { (id , hydroflow_plus :: runtime_support :: bincode :: serialize :: < (u32 , i32) > (& data) . unwrap () . into ()) }", + ], + }, + ), + ), + sink_expr: null, + source_expr: null, + deserialize_pipeline: Some( + Operator( + Operator { + path: "map", + args: [ + "| res | { hydroflow_plus :: runtime_support :: bincode :: deserialize :: < (u32 , i32) > (& res . unwrap ()) . unwrap () }", + ], + }, + ), + ), + input: Map { + f: { use crate :: __staged :: cluster :: * ; | (id , n) | (id , (id , n)) }, + input: CrossProduct( + Map { + f: { use crate :: __staged :: cluster :: * ; | & id | id }, + input: Source { + source: Iter( + { use hydroflow_plus_cli_integration :: __staged :: deploy :: * ; panic ! () }, + ), + produces_delta: false, + location_id: 0, + }, + }, + Source { + source: Iter( + { use crate :: __staged :: cluster :: * ; 0 .. 5 }, + ), + produces_delta: false, + location_id: 0, + }, + ), + }, + }, + }, + }, + }, +] diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__first_ten__tests__first_ten_distributed.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__first_ten__tests__first_ten_distributed.snap new file mode 100644 index 000000000000..11414bfc9652 --- /dev/null +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__first_ten__tests__first_ten_distributed.snap @@ -0,0 +1,41 @@ +--- +source: hydroflow_plus_test/src/first_ten.rs +expression: builder.ir() +--- +[ + ForEach { + f: { use crate :: __staged :: first_ten :: * ; | n | println ! ("{}" , n) }, + input: Network { + to_location: 1, + serialize_pipeline: Some( + Operator( + Operator { + path: "map", + args: [ + "| data | { hydroflow_plus :: runtime_support :: bincode :: serialize :: < i32 > (& data) . unwrap () . into () }", + ], + }, + ), + ), + sink_expr: null, + source_expr: null, + deserialize_pipeline: Some( + Operator( + Operator { + path: "map", + args: [ + "| res | { hydroflow_plus :: runtime_support :: bincode :: deserialize :: < i32 > (& res . unwrap ()) . unwrap () }", + ], + }, + ), + ), + input: Source { + source: Iter( + { use crate :: __staged :: first_ten :: * ; 0 .. 10 }, + ), + produces_delta: false, + location_id: 0, + }, + }, + }, +] diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_static_static@graphvis_dot.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_static_static@graphvis_dot.snap index e36d6655be0b..cf50ced2245b 100644 --- a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_static_static@graphvis_dot.snap +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_static_static@graphvis_dot.snap @@ -6,26 +6,26 @@ digraph { node [fontname="Monaco,Menlo,Consolas,"Droid Sans Mono",Inconsolata,"Courier New",monospace", style=filled]; edge [fontname="Monaco,Menlo,Consolas,"Droid Sans Mono",Inconsolata,"Courier New",monospace"]; n1v1 [label="(n1v1) source_iter({\l use crate::__staged::negation::*;\l 0..5\l})\l", shape=invhouse, fillcolor="#88aaff"] - n3v1 [label="(n3v1) map({\l use crate::__staged::negation::*;\l |v| (v, v)\l})\l", shape=invhouse, fillcolor="#88aaff"] - n5v1 [label="(n5v1) source_iter({\l use crate::__staged::negation::*;\l 3..6\l})\l", shape=invhouse, fillcolor="#88aaff"] - n7v1 [label="(n7v1) anti_join::<'tick, 'static>()", shape=invhouse, fillcolor="#88aaff"] - n9v1 [label="(n9v1) persist()", shape=invhouse, fillcolor="#88aaff"] - n10v3 [label="(n10v3) handoff", shape=parallelogram, fillcolor="#ddddff"] - n11v1 [label="(n11v1) for_each({\l use crate::__staged::negation::*;\l let output = output;\l |v: (u32, u32)| {\l output.send(v.0).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] - n1v1 -> n3v1 - n3v1 -> n7v1 [label="pos"] - n5v1 -> n10v3 - n10v3 -> n7v1 [label="neg", color=red] - n7v1 -> n9v1 - n9v1 -> n11v1 + n2v1 [label="(n2v1) map({\l use crate::__staged::negation::*;\l |v| (v, v)\l})\l", shape=invhouse, fillcolor="#88aaff"] + n3v1 [label="(n3v1) source_iter({\l use crate::__staged::negation::*;\l 3..6\l})\l", shape=invhouse, fillcolor="#88aaff"] + n4v1 [label="(n4v1) anti_join::<'tick, 'static>()", shape=invhouse, fillcolor="#88aaff"] + n5v1 [label="(n5v1) persist()", shape=invhouse, fillcolor="#88aaff"] + n6v1 [label="(n6v1) for_each({\l use crate::__staged::negation::*;\l let output = output;\l |v: (u32, u32)| {\l output.send(v.0).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] + n7v1 [label="(n7v1) handoff", shape=parallelogram, fillcolor="#ddddff"] + n1v1 -> n2v1 + n5v1 -> n4v1 [label="pos"] + n2v1 -> n5v1 + n3v1 -> n7v1 + n4v1 -> n6v1 + n7v1 -> n4v1 [label="neg", color=red] subgraph "cluster n1v1" { fillcolor="#dddddd" style=filled label = "sg_1v1\nstratum 0" - n5v1 + n3v1 subgraph "cluster_sg_1v1_var_stream_2" { label="var stream_2" - n5v1 + n3v1 } } subgraph "cluster n2v1" { @@ -33,25 +33,21 @@ digraph { style=filled label = "sg_2v1\nstratum 1" n1v1 - n3v1 - n7v1 - n9v1 - n11v1 + n2v1 + n5v1 + n4v1 + n6v1 subgraph "cluster_sg_2v1_var_stream_0" { label="var stream_0" n1v1 } subgraph "cluster_sg_2v1_var_stream_1" { label="var stream_1" - n3v1 + n2v1 } subgraph "cluster_sg_2v1_var_stream_3" { label="var stream_3" - n7v1 - } - subgraph "cluster_sg_2v1_var_stream_4" { - label="var stream_4" - n9v1 + n4v1 } } } diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_static_static@graphvis_mermaid.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_static_static@graphvis_mermaid.snap index 5b9a7df0dd35..79f392f1b4b1 100644 --- a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_static_static@graphvis_mermaid.snap +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_static_static@graphvis_mermaid.snap @@ -9,41 +9,38 @@ classDef pushClass fill:#ff8,stroke:#000,text-align:left,white-space:pre classDef otherClass fill:#fdc,stroke:#000,text-align:left,white-space:pre linkStyle default stroke:#aaa 1v1[\"
(1v1)
source_iter({
use crate::__staged::negation::*;
0..5
})
"/]:::pullClass -3v1[\"
(3v1)
map({
use crate::__staged::negation::*;
|v| (v, v)
})
"/]:::pullClass -5v1[\"
(5v1)
source_iter({
use crate::__staged::negation::*;
3..6
})
"/]:::pullClass -7v1[\"(7v1) anti_join::<'tick, 'static>()"/]:::pullClass -9v1[\"(9v1) persist()"/]:::pullClass -10v3["(10v3) handoff"]:::otherClass -11v1[/"
(11v1)
for_each({
use crate::__staged::negation::*;
let output = output;
|v: (u32, u32)| {
output.send(v.0).unwrap();
}
})
"\]:::pushClass -1v1-->3v1 -3v1-->|pos|7v1 -5v1-->10v3 -10v3--x|neg|7v1; linkStyle 3 stroke:red -7v1-->9v1 -9v1-->11v1 +2v1[\"
(2v1)
map({
use crate::__staged::negation::*;
|v| (v, v)
})
"/]:::pullClass +3v1[\"
(3v1)
source_iter({
use crate::__staged::negation::*;
3..6
})
"/]:::pullClass +4v1[\"(4v1) anti_join::<'tick, 'static>()"/]:::pullClass +5v1[\"(5v1) persist()"/]:::pullClass +6v1[/"
(6v1)
for_each({
use crate::__staged::negation::*;
let output = output;
|v: (u32, u32)| {
output.send(v.0).unwrap();
}
})
"\]:::pushClass +7v1["(7v1) handoff"]:::otherClass +1v1-->2v1 +5v1-->|pos|4v1 +2v1-->5v1 +3v1-->7v1 +4v1-->6v1 +7v1--x|neg|4v1; linkStyle 5 stroke:red subgraph sg_1v1 ["sg_1v1 stratum 0"] - 5v1 + 3v1 subgraph sg_1v1_var_stream_2 ["var stream_2"] - 5v1 + 3v1 end end subgraph sg_2v1 ["sg_2v1 stratum 1"] 1v1 - 3v1 - 7v1 - 9v1 - 11v1 + 2v1 + 5v1 + 4v1 + 6v1 subgraph sg_2v1_var_stream_0 ["var stream_0"] 1v1 end subgraph sg_2v1_var_stream_1 ["var stream_1"] - 3v1 + 2v1 end subgraph sg_2v1_var_stream_3 ["var stream_3"] - 7v1 - end - subgraph sg_2v1_var_stream_4 ["var stream_4"] - 9v1 + 4v1 end end diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_static_tick@graphvis_dot.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_static_tick@graphvis_dot.snap index f3d65467f206..f53c16eff2ee 100644 --- a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_static_tick@graphvis_dot.snap +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_static_tick@graphvis_dot.snap @@ -6,26 +6,26 @@ digraph { node [fontname="Monaco,Menlo,Consolas,"Droid Sans Mono",Inconsolata,"Courier New",monospace", style=filled]; edge [fontname="Monaco,Menlo,Consolas,"Droid Sans Mono",Inconsolata,"Courier New",monospace"]; n1v1 [label="(n1v1) source_iter({\l use crate::__staged::negation::*;\l 0..5\l})\l", shape=invhouse, fillcolor="#88aaff"] - n3v1 [label="(n3v1) map({\l use crate::__staged::negation::*;\l |v| (v, v)\l})\l", shape=invhouse, fillcolor="#88aaff"] - n5v1 [label="(n5v1) source_iter({\l use crate::__staged::negation::*;\l 3..6\l})\l", shape=invhouse, fillcolor="#88aaff"] - n7v1 [label="(n7v1) persist()", shape=invhouse, fillcolor="#88aaff"] - n9v1 [label="(n9v1) anti_join::<'tick, 'tick>()", shape=invhouse, fillcolor="#88aaff"] - n10v3 [label="(n10v3) handoff", shape=parallelogram, fillcolor="#ddddff"] - n11v1 [label="(n11v1) for_each({\l use crate::__staged::negation::*;\l let output = output;\l |v: (u32, u32)| {\l output.send(v.0).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] - n1v1 -> n3v1 + n2v1 [label="(n2v1) map({\l use crate::__staged::negation::*;\l |v| (v, v)\l})\l", shape=invhouse, fillcolor="#88aaff"] + n3v1 [label="(n3v1) source_iter({\l use crate::__staged::negation::*;\l 3..6\l})\l", shape=invhouse, fillcolor="#88aaff"] + n4v1 [label="(n4v1) anti_join::<'tick, 'tick>()", shape=invhouse, fillcolor="#88aaff"] + n5v1 [label="(n5v1) persist()", shape=invhouse, fillcolor="#88aaff"] + n6v1 [label="(n6v1) for_each({\l use crate::__staged::negation::*;\l let output = output;\l |v: (u32, u32)| {\l output.send(v.0).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] + n7v1 [label="(n7v1) handoff", shape=parallelogram, fillcolor="#ddddff"] + n1v1 -> n2v1 + n5v1 -> n4v1 [label="pos"] + n2v1 -> n5v1 n3v1 -> n7v1 - n10v3 -> n9v1 [label="neg", color=red] - n7v1 -> n9v1 [label="pos"] - n5v1 -> n10v3 - n9v1 -> n11v1 + n4v1 -> n6v1 + n7v1 -> n4v1 [label="neg", color=red] subgraph "cluster n1v1" { fillcolor="#dddddd" style=filled label = "sg_1v1\nstratum 0" - n5v1 + n3v1 subgraph "cluster_sg_1v1_var_stream_2" { label="var stream_2" - n5v1 + n3v1 } } subgraph "cluster n2v1" { @@ -33,25 +33,21 @@ digraph { style=filled label = "sg_2v1\nstratum 1" n1v1 - n3v1 - n7v1 - n9v1 - n11v1 + n2v1 + n5v1 + n4v1 + n6v1 subgraph "cluster_sg_2v1_var_stream_0" { label="var stream_0" n1v1 } subgraph "cluster_sg_2v1_var_stream_1" { label="var stream_1" - n3v1 + n2v1 } subgraph "cluster_sg_2v1_var_stream_3" { label="var stream_3" - n9v1 - } - subgraph "cluster_sg_2v1_var_stream_4" { - label="var stream_4" - n7v1 + n4v1 } } } diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_static_tick@graphvis_mermaid.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_static_tick@graphvis_mermaid.snap index 8ed66153e640..6bee1937a039 100644 --- a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_static_tick@graphvis_mermaid.snap +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_static_tick@graphvis_mermaid.snap @@ -9,41 +9,38 @@ classDef pushClass fill:#ff8,stroke:#000,text-align:left,white-space:pre classDef otherClass fill:#fdc,stroke:#000,text-align:left,white-space:pre linkStyle default stroke:#aaa 1v1[\"
(1v1)
source_iter({
use crate::__staged::negation::*;
0..5
})
"/]:::pullClass -3v1[\"
(3v1)
map({
use crate::__staged::negation::*;
|v| (v, v)
})
"/]:::pullClass -5v1[\"
(5v1)
source_iter({
use crate::__staged::negation::*;
3..6
})
"/]:::pullClass -7v1[\"(7v1) persist()"/]:::pullClass -9v1[\"(9v1) anti_join::<'tick, 'tick>()"/]:::pullClass -10v3["(10v3) handoff"]:::otherClass -11v1[/"
(11v1)
for_each({
use crate::__staged::negation::*;
let output = output;
|v: (u32, u32)| {
output.send(v.0).unwrap();
}
})
"\]:::pushClass -1v1-->3v1 +2v1[\"
(2v1)
map({
use crate::__staged::negation::*;
|v| (v, v)
})
"/]:::pullClass +3v1[\"
(3v1)
source_iter({
use crate::__staged::negation::*;
3..6
})
"/]:::pullClass +4v1[\"(4v1) anti_join::<'tick, 'tick>()"/]:::pullClass +5v1[\"(5v1) persist()"/]:::pullClass +6v1[/"
(6v1)
for_each({
use crate::__staged::negation::*;
let output = output;
|v: (u32, u32)| {
output.send(v.0).unwrap();
}
})
"\]:::pushClass +7v1["(7v1) handoff"]:::otherClass +1v1-->2v1 +5v1-->|pos|4v1 +2v1-->5v1 3v1-->7v1 -10v3--x|neg|9v1; linkStyle 2 stroke:red -7v1-->|pos|9v1 -5v1-->10v3 -9v1-->11v1 +4v1-->6v1 +7v1--x|neg|4v1; linkStyle 5 stroke:red subgraph sg_1v1 ["sg_1v1 stratum 0"] - 5v1 + 3v1 subgraph sg_1v1_var_stream_2 ["var stream_2"] - 5v1 + 3v1 end end subgraph sg_2v1 ["sg_2v1 stratum 1"] 1v1 - 3v1 - 7v1 - 9v1 - 11v1 + 2v1 + 5v1 + 4v1 + 6v1 subgraph sg_2v1_var_stream_0 ["var stream_0"] 1v1 end subgraph sg_2v1_var_stream_1 ["var stream_1"] - 3v1 + 2v1 end subgraph sg_2v1_var_stream_3 ["var stream_3"] - 9v1 - end - subgraph sg_2v1_var_stream_4 ["var stream_4"] - 7v1 + 4v1 end end diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_tick_static@graphvis_dot.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_tick_static@graphvis_dot.snap index b414da395a9a..51d4d1200314 100644 --- a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_tick_static@graphvis_dot.snap +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_tick_static@graphvis_dot.snap @@ -6,24 +6,24 @@ digraph { node [fontname="Monaco,Menlo,Consolas,"Droid Sans Mono",Inconsolata,"Courier New",monospace", style=filled]; edge [fontname="Monaco,Menlo,Consolas,"Droid Sans Mono",Inconsolata,"Courier New",monospace"]; n1v1 [label="(n1v1) source_iter({\l use crate::__staged::negation::*;\l 0..5\l})\l", shape=invhouse, fillcolor="#88aaff"] - n3v1 [label="(n3v1) map({\l use crate::__staged::negation::*;\l |v| (v, v)\l})\l", shape=invhouse, fillcolor="#88aaff"] - n5v1 [label="(n5v1) source_iter({\l use crate::__staged::negation::*;\l 3..6\l})\l", shape=invhouse, fillcolor="#88aaff"] - n7v1 [label="(n7v1) anti_join::<'tick, 'static>()", shape=invhouse, fillcolor="#88aaff"] - n8v3 [label="(n8v3) handoff", shape=parallelogram, fillcolor="#ddddff"] - n9v1 [label="(n9v1) for_each({\l use crate::__staged::negation::*;\l let output = output;\l |v: (u32, u32)| {\l output.send(v.0).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] - n1v1 -> n3v1 - n8v3 -> n7v1 [label="neg", color=red] - n3v1 -> n7v1 [label="pos"] - n5v1 -> n8v3 - n7v1 -> n9v1 + n2v1 [label="(n2v1) map({\l use crate::__staged::negation::*;\l |v| (v, v)\l})\l", shape=invhouse, fillcolor="#88aaff"] + n3v1 [label="(n3v1) source_iter({\l use crate::__staged::negation::*;\l 3..6\l})\l", shape=invhouse, fillcolor="#88aaff"] + n4v1 [label="(n4v1) anti_join::<'tick, 'static>()", shape=invhouse, fillcolor="#88aaff"] + n5v1 [label="(n5v1) for_each({\l use crate::__staged::negation::*;\l let output = output;\l |v: (u32, u32)| {\l output.send(v.0).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] + n6v1 [label="(n6v1) handoff", shape=parallelogram, fillcolor="#ddddff"] + n1v1 -> n2v1 + n2v1 -> n4v1 [label="pos"] + n3v1 -> n6v1 + n4v1 -> n5v1 + n6v1 -> n4v1 [label="neg", color=red] subgraph "cluster n1v1" { fillcolor="#dddddd" style=filled label = "sg_1v1\nstratum 0" - n5v1 + n3v1 subgraph "cluster_sg_1v1_var_stream_2" { label="var stream_2" - n5v1 + n3v1 } } subgraph "cluster n2v1" { @@ -31,20 +31,20 @@ digraph { style=filled label = "sg_2v1\nstratum 1" n1v1 - n3v1 - n7v1 - n9v1 + n2v1 + n4v1 + n5v1 subgraph "cluster_sg_2v1_var_stream_0" { label="var stream_0" n1v1 } subgraph "cluster_sg_2v1_var_stream_1" { label="var stream_1" - n3v1 + n2v1 } subgraph "cluster_sg_2v1_var_stream_3" { label="var stream_3" - n7v1 + n4v1 } } } diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_tick_static@graphvis_mermaid.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_tick_static@graphvis_mermaid.snap index af9066fd406e..2510759b48c7 100644 --- a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_tick_static@graphvis_mermaid.snap +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_tick_static@graphvis_mermaid.snap @@ -9,35 +9,35 @@ classDef pushClass fill:#ff8,stroke:#000,text-align:left,white-space:pre classDef otherClass fill:#fdc,stroke:#000,text-align:left,white-space:pre linkStyle default stroke:#aaa 1v1[\"
(1v1)
source_iter({
use crate::__staged::negation::*;
0..5
})
"/]:::pullClass -3v1[\"
(3v1)
map({
use crate::__staged::negation::*;
|v| (v, v)
})
"/]:::pullClass -5v1[\"
(5v1)
source_iter({
use crate::__staged::negation::*;
3..6
})
"/]:::pullClass -7v1[\"(7v1) anti_join::<'tick, 'static>()"/]:::pullClass -8v3["(8v3) handoff"]:::otherClass -9v1[/"
(9v1)
for_each({
use crate::__staged::negation::*;
let output = output;
|v: (u32, u32)| {
output.send(v.0).unwrap();
}
})
"\]:::pushClass -1v1-->3v1 -8v3--x|neg|7v1; linkStyle 1 stroke:red -3v1-->|pos|7v1 -5v1-->8v3 -7v1-->9v1 +2v1[\"
(2v1)
map({
use crate::__staged::negation::*;
|v| (v, v)
})
"/]:::pullClass +3v1[\"
(3v1)
source_iter({
use crate::__staged::negation::*;
3..6
})
"/]:::pullClass +4v1[\"(4v1) anti_join::<'tick, 'static>()"/]:::pullClass +5v1[/"
(5v1)
for_each({
use crate::__staged::negation::*;
let output = output;
|v: (u32, u32)| {
output.send(v.0).unwrap();
}
})
"\]:::pushClass +6v1["(6v1) handoff"]:::otherClass +1v1-->2v1 +2v1-->|pos|4v1 +3v1-->6v1 +4v1-->5v1 +6v1--x|neg|4v1; linkStyle 4 stroke:red subgraph sg_1v1 ["sg_1v1 stratum 0"] - 5v1 + 3v1 subgraph sg_1v1_var_stream_2 ["var stream_2"] - 5v1 + 3v1 end end subgraph sg_2v1 ["sg_2v1 stratum 1"] 1v1 - 3v1 - 7v1 - 9v1 + 2v1 + 4v1 + 5v1 subgraph sg_2v1_var_stream_0 ["var stream_0"] 1v1 end subgraph sg_2v1_var_stream_1 ["var stream_1"] - 3v1 + 2v1 end subgraph sg_2v1_var_stream_3 ["var stream_3"] - 7v1 + 4v1 end end diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_tick_tick@graphvis_dot.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_tick_tick@graphvis_dot.snap index 1f1253eb2e1f..172355294260 100644 --- a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_tick_tick@graphvis_dot.snap +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_tick_tick@graphvis_dot.snap @@ -6,24 +6,24 @@ digraph { node [fontname="Monaco,Menlo,Consolas,"Droid Sans Mono",Inconsolata,"Courier New",monospace", style=filled]; edge [fontname="Monaco,Menlo,Consolas,"Droid Sans Mono",Inconsolata,"Courier New",monospace"]; n1v1 [label="(n1v1) source_iter({\l use crate::__staged::negation::*;\l 0..5\l})\l", shape=invhouse, fillcolor="#88aaff"] - n3v1 [label="(n3v1) map({\l use crate::__staged::negation::*;\l |v| (v, v)\l})\l", shape=invhouse, fillcolor="#88aaff"] - n5v1 [label="(n5v1) source_iter({\l use crate::__staged::negation::*;\l 3..6\l})\l", shape=invhouse, fillcolor="#88aaff"] - n7v1 [label="(n7v1) anti_join::<'tick, 'tick>()", shape=invhouse, fillcolor="#88aaff"] - n8v3 [label="(n8v3) handoff", shape=parallelogram, fillcolor="#ddddff"] - n9v1 [label="(n9v1) for_each({\l use crate::__staged::negation::*;\l let output = output;\l |v: (u32, u32)| {\l output.send(v.0).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] - n1v1 -> n3v1 - n8v3 -> n7v1 [label="neg", color=red] - n3v1 -> n7v1 [label="pos"] - n5v1 -> n8v3 - n7v1 -> n9v1 + n2v1 [label="(n2v1) map({\l use crate::__staged::negation::*;\l |v| (v, v)\l})\l", shape=invhouse, fillcolor="#88aaff"] + n3v1 [label="(n3v1) source_iter({\l use crate::__staged::negation::*;\l 3..6\l})\l", shape=invhouse, fillcolor="#88aaff"] + n4v1 [label="(n4v1) anti_join::<'tick, 'tick>()", shape=invhouse, fillcolor="#88aaff"] + n5v1 [label="(n5v1) for_each({\l use crate::__staged::negation::*;\l let output = output;\l |v: (u32, u32)| {\l output.send(v.0).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] + n6v1 [label="(n6v1) handoff", shape=parallelogram, fillcolor="#ddddff"] + n1v1 -> n2v1 + n2v1 -> n4v1 [label="pos"] + n3v1 -> n6v1 + n4v1 -> n5v1 + n6v1 -> n4v1 [label="neg", color=red] subgraph "cluster n1v1" { fillcolor="#dddddd" style=filled label = "sg_1v1\nstratum 0" - n5v1 + n3v1 subgraph "cluster_sg_1v1_var_stream_2" { label="var stream_2" - n5v1 + n3v1 } } subgraph "cluster n2v1" { @@ -31,20 +31,20 @@ digraph { style=filled label = "sg_2v1\nstratum 1" n1v1 - n3v1 - n7v1 - n9v1 + n2v1 + n4v1 + n5v1 subgraph "cluster_sg_2v1_var_stream_0" { label="var stream_0" n1v1 } subgraph "cluster_sg_2v1_var_stream_1" { label="var stream_1" - n3v1 + n2v1 } subgraph "cluster_sg_2v1_var_stream_3" { label="var stream_3" - n7v1 + n4v1 } } } diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_tick_tick@graphvis_mermaid.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_tick_tick@graphvis_mermaid.snap index e10428bef6e8..7c2af5cfc5d9 100644 --- a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_tick_tick@graphvis_mermaid.snap +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__anti_join_tick_tick@graphvis_mermaid.snap @@ -9,35 +9,35 @@ classDef pushClass fill:#ff8,stroke:#000,text-align:left,white-space:pre classDef otherClass fill:#fdc,stroke:#000,text-align:left,white-space:pre linkStyle default stroke:#aaa 1v1[\"
(1v1)
source_iter({
use crate::__staged::negation::*;
0..5
})
"/]:::pullClass -3v1[\"
(3v1)
map({
use crate::__staged::negation::*;
|v| (v, v)
})
"/]:::pullClass -5v1[\"
(5v1)
source_iter({
use crate::__staged::negation::*;
3..6
})
"/]:::pullClass -7v1[\"(7v1) anti_join::<'tick, 'tick>()"/]:::pullClass -8v3["(8v3) handoff"]:::otherClass -9v1[/"
(9v1)
for_each({
use crate::__staged::negation::*;
let output = output;
|v: (u32, u32)| {
output.send(v.0).unwrap();
}
})
"\]:::pushClass -1v1-->3v1 -8v3--x|neg|7v1; linkStyle 1 stroke:red -3v1-->|pos|7v1 -5v1-->8v3 -7v1-->9v1 +2v1[\"
(2v1)
map({
use crate::__staged::negation::*;
|v| (v, v)
})
"/]:::pullClass +3v1[\"
(3v1)
source_iter({
use crate::__staged::negation::*;
3..6
})
"/]:::pullClass +4v1[\"(4v1) anti_join::<'tick, 'tick>()"/]:::pullClass +5v1[/"
(5v1)
for_each({
use crate::__staged::negation::*;
let output = output;
|v: (u32, u32)| {
output.send(v.0).unwrap();
}
})
"\]:::pushClass +6v1["(6v1) handoff"]:::otherClass +1v1-->2v1 +2v1-->|pos|4v1 +3v1-->6v1 +4v1-->5v1 +6v1--x|neg|4v1; linkStyle 4 stroke:red subgraph sg_1v1 ["sg_1v1 stratum 0"] - 5v1 + 3v1 subgraph sg_1v1_var_stream_2 ["var stream_2"] - 5v1 + 3v1 end end subgraph sg_2v1 ["sg_2v1 stratum 1"] 1v1 - 3v1 - 7v1 - 9v1 + 2v1 + 4v1 + 5v1 subgraph sg_2v1_var_stream_0 ["var stream_0"] 1v1 end subgraph sg_2v1_var_stream_1 ["var stream_1"] - 3v1 + 2v1 end subgraph sg_2v1_var_stream_3 ["var stream_3"] - 7v1 + 4v1 end end diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_static_static@graphvis_dot.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_static_static@graphvis_dot.snap index b08fcc016a23..8a263719c795 100644 --- a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_static_static@graphvis_dot.snap +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_static_static@graphvis_dot.snap @@ -6,24 +6,24 @@ digraph { node [fontname="Monaco,Menlo,Consolas,"Droid Sans Mono",Inconsolata,"Courier New",monospace", style=filled]; edge [fontname="Monaco,Menlo,Consolas,"Droid Sans Mono",Inconsolata,"Courier New",monospace"]; n1v1 [label="(n1v1) source_iter({\l use crate::__staged::negation::*;\l 0..5\l})\l", shape=invhouse, fillcolor="#88aaff"] - n3v1 [label="(n3v1) source_iter({\l use crate::__staged::negation::*;\l 3..6\l})\l", shape=invhouse, fillcolor="#88aaff"] - n5v1 [label="(n5v1) difference::<'tick, 'static>()", shape=invhouse, fillcolor="#88aaff"] - n7v1 [label="(n7v1) persist()", shape=invhouse, fillcolor="#88aaff"] - n8v3 [label="(n8v3) handoff", shape=parallelogram, fillcolor="#ddddff"] - n9v1 [label="(n9v1) for_each({\l use crate::__staged::negation::*;\l let output = output;\l |v| {\l output.send(v).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] - n1v1 -> n5v1 [label="pos"] - n3v1 -> n8v3 - n8v3 -> n5v1 [label="neg", color=red] - n5v1 -> n7v1 - n7v1 -> n9v1 + n2v1 [label="(n2v1) source_iter({\l use crate::__staged::negation::*;\l 3..6\l})\l", shape=invhouse, fillcolor="#88aaff"] + n3v1 [label="(n3v1) difference::<'tick, 'static>()", shape=invhouse, fillcolor="#88aaff"] + n4v1 [label="(n4v1) persist()", shape=invhouse, fillcolor="#88aaff"] + n5v1 [label="(n5v1) for_each({\l use crate::__staged::negation::*;\l let output = output;\l |v| {\l output.send(v).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] + n6v1 [label="(n6v1) handoff", shape=parallelogram, fillcolor="#ddddff"] + n4v1 -> n3v1 [label="pos"] + n1v1 -> n4v1 + n2v1 -> n6v1 + n3v1 -> n5v1 + n6v1 -> n3v1 [label="neg", color=red] subgraph "cluster n1v1" { fillcolor="#dddddd" style=filled label = "sg_1v1\nstratum 0" - n3v1 + n2v1 subgraph "cluster_sg_1v1_var_stream_1" { label="var stream_1" - n3v1 + n2v1 } } subgraph "cluster n2v1" { @@ -31,20 +31,16 @@ digraph { style=filled label = "sg_2v1\nstratum 1" n1v1 + n4v1 + n3v1 n5v1 - n7v1 - n9v1 subgraph "cluster_sg_2v1_var_stream_0" { label="var stream_0" n1v1 } subgraph "cluster_sg_2v1_var_stream_2" { label="var stream_2" - n5v1 - } - subgraph "cluster_sg_2v1_var_stream_3" { - label="var stream_3" - n7v1 + n3v1 } } } diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_static_static@graphvis_mermaid.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_static_static@graphvis_mermaid.snap index 66f4c9bd0e1a..65f9d3ec4b5f 100644 --- a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_static_static@graphvis_mermaid.snap +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_static_static@graphvis_mermaid.snap @@ -9,35 +9,32 @@ classDef pushClass fill:#ff8,stroke:#000,text-align:left,white-space:pre classDef otherClass fill:#fdc,stroke:#000,text-align:left,white-space:pre linkStyle default stroke:#aaa 1v1[\"
(1v1)
source_iter({
use crate::__staged::negation::*;
0..5
})
"/]:::pullClass -3v1[\"
(3v1)
source_iter({
use crate::__staged::negation::*;
3..6
})
"/]:::pullClass -5v1[\"(5v1) difference::<'tick, 'static>()"/]:::pullClass -7v1[\"(7v1) persist()"/]:::pullClass -8v3["(8v3) handoff"]:::otherClass -9v1[/"
(9v1)
for_each({
use crate::__staged::negation::*;
let output = output;
|v| {
output.send(v).unwrap();
}
})
"\]:::pushClass -1v1-->|pos|5v1 -3v1-->8v3 -8v3--x|neg|5v1; linkStyle 2 stroke:red -5v1-->7v1 -7v1-->9v1 +2v1[\"
(2v1)
source_iter({
use crate::__staged::negation::*;
3..6
})
"/]:::pullClass +3v1[\"(3v1) difference::<'tick, 'static>()"/]:::pullClass +4v1[\"(4v1) persist()"/]:::pullClass +5v1[/"
(5v1)
for_each({
use crate::__staged::negation::*;
let output = output;
|v| {
output.send(v).unwrap();
}
})
"\]:::pushClass +6v1["(6v1) handoff"]:::otherClass +4v1-->|pos|3v1 +1v1-->4v1 +2v1-->6v1 +3v1-->5v1 +6v1--x|neg|3v1; linkStyle 4 stroke:red subgraph sg_1v1 ["sg_1v1 stratum 0"] - 3v1 + 2v1 subgraph sg_1v1_var_stream_1 ["var stream_1"] - 3v1 + 2v1 end end subgraph sg_2v1 ["sg_2v1 stratum 1"] 1v1 + 4v1 + 3v1 5v1 - 7v1 - 9v1 subgraph sg_2v1_var_stream_0 ["var stream_0"] 1v1 end subgraph sg_2v1_var_stream_2 ["var stream_2"] - 5v1 - end - subgraph sg_2v1_var_stream_3 ["var stream_3"] - 7v1 + 3v1 end end diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_static_tick@graphvis_dot.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_static_tick@graphvis_dot.snap index 25aa50a13630..6619fc6bac7f 100644 --- a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_static_tick@graphvis_dot.snap +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_static_tick@graphvis_dot.snap @@ -6,24 +6,24 @@ digraph { node [fontname="Monaco,Menlo,Consolas,"Droid Sans Mono",Inconsolata,"Courier New",monospace", style=filled]; edge [fontname="Monaco,Menlo,Consolas,"Droid Sans Mono",Inconsolata,"Courier New",monospace"]; n1v1 [label="(n1v1) source_iter({\l use crate::__staged::negation::*;\l 0..5\l})\l", shape=invhouse, fillcolor="#88aaff"] - n3v1 [label="(n3v1) source_iter({\l use crate::__staged::negation::*;\l 3..6\l})\l", shape=invhouse, fillcolor="#88aaff"] - n5v1 [label="(n5v1) persist()", shape=invhouse, fillcolor="#88aaff"] - n7v1 [label="(n7v1) difference::<'tick, 'tick>()", shape=invhouse, fillcolor="#88aaff"] - n8v3 [label="(n8v3) handoff", shape=parallelogram, fillcolor="#ddddff"] - n9v1 [label="(n9v1) for_each({\l use crate::__staged::negation::*;\l let output = output;\l |v| {\l output.send(v).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] - n1v1 -> n5v1 - n8v3 -> n7v1 [label="neg", color=red] - n5v1 -> n7v1 [label="pos"] - n3v1 -> n8v3 - n7v1 -> n9v1 + n2v1 [label="(n2v1) source_iter({\l use crate::__staged::negation::*;\l 3..6\l})\l", shape=invhouse, fillcolor="#88aaff"] + n3v1 [label="(n3v1) difference::<'tick, 'tick>()", shape=invhouse, fillcolor="#88aaff"] + n4v1 [label="(n4v1) persist()", shape=invhouse, fillcolor="#88aaff"] + n5v1 [label="(n5v1) for_each({\l use crate::__staged::negation::*;\l let output = output;\l |v| {\l output.send(v).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] + n6v1 [label="(n6v1) handoff", shape=parallelogram, fillcolor="#ddddff"] + n4v1 -> n3v1 [label="pos"] + n1v1 -> n4v1 + n2v1 -> n6v1 + n3v1 -> n5v1 + n6v1 -> n3v1 [label="neg", color=red] subgraph "cluster n1v1" { fillcolor="#dddddd" style=filled label = "sg_1v1\nstratum 0" - n3v1 + n2v1 subgraph "cluster_sg_1v1_var_stream_1" { label="var stream_1" - n3v1 + n2v1 } } subgraph "cluster n2v1" { @@ -31,20 +31,16 @@ digraph { style=filled label = "sg_2v1\nstratum 1" n1v1 + n4v1 + n3v1 n5v1 - n7v1 - n9v1 subgraph "cluster_sg_2v1_var_stream_0" { label="var stream_0" n1v1 } subgraph "cluster_sg_2v1_var_stream_2" { label="var stream_2" - n7v1 - } - subgraph "cluster_sg_2v1_var_stream_3" { - label="var stream_3" - n5v1 + n3v1 } } } diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_static_tick@graphvis_mermaid.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_static_tick@graphvis_mermaid.snap index 6dac4acd30c4..6c5fea53b1ba 100644 --- a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_static_tick@graphvis_mermaid.snap +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_static_tick@graphvis_mermaid.snap @@ -9,35 +9,32 @@ classDef pushClass fill:#ff8,stroke:#000,text-align:left,white-space:pre classDef otherClass fill:#fdc,stroke:#000,text-align:left,white-space:pre linkStyle default stroke:#aaa 1v1[\"
(1v1)
source_iter({
use crate::__staged::negation::*;
0..5
})
"/]:::pullClass -3v1[\"
(3v1)
source_iter({
use crate::__staged::negation::*;
3..6
})
"/]:::pullClass -5v1[\"(5v1) persist()"/]:::pullClass -7v1[\"(7v1) difference::<'tick, 'tick>()"/]:::pullClass -8v3["(8v3) handoff"]:::otherClass -9v1[/"
(9v1)
for_each({
use crate::__staged::negation::*;
let output = output;
|v| {
output.send(v).unwrap();
}
})
"\]:::pushClass -1v1-->5v1 -8v3--x|neg|7v1; linkStyle 1 stroke:red -5v1-->|pos|7v1 -3v1-->8v3 -7v1-->9v1 +2v1[\"
(2v1)
source_iter({
use crate::__staged::negation::*;
3..6
})
"/]:::pullClass +3v1[\"(3v1) difference::<'tick, 'tick>()"/]:::pullClass +4v1[\"(4v1) persist()"/]:::pullClass +5v1[/"
(5v1)
for_each({
use crate::__staged::negation::*;
let output = output;
|v| {
output.send(v).unwrap();
}
})
"\]:::pushClass +6v1["(6v1) handoff"]:::otherClass +4v1-->|pos|3v1 +1v1-->4v1 +2v1-->6v1 +3v1-->5v1 +6v1--x|neg|3v1; linkStyle 4 stroke:red subgraph sg_1v1 ["sg_1v1 stratum 0"] - 3v1 + 2v1 subgraph sg_1v1_var_stream_1 ["var stream_1"] - 3v1 + 2v1 end end subgraph sg_2v1 ["sg_2v1 stratum 1"] 1v1 + 4v1 + 3v1 5v1 - 7v1 - 9v1 subgraph sg_2v1_var_stream_0 ["var stream_0"] 1v1 end subgraph sg_2v1_var_stream_2 ["var stream_2"] - 7v1 - end - subgraph sg_2v1_var_stream_3 ["var stream_3"] - 5v1 + 3v1 end end diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_tick_static@graphvis_dot.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_tick_static@graphvis_dot.snap index c1248968c41e..f873615b69e6 100644 --- a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_tick_static@graphvis_dot.snap +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_tick_static@graphvis_dot.snap @@ -6,22 +6,22 @@ digraph { node [fontname="Monaco,Menlo,Consolas,"Droid Sans Mono",Inconsolata,"Courier New",monospace", style=filled]; edge [fontname="Monaco,Menlo,Consolas,"Droid Sans Mono",Inconsolata,"Courier New",monospace"]; n1v1 [label="(n1v1) source_iter({\l use crate::__staged::negation::*;\l 0..5\l})\l", shape=invhouse, fillcolor="#88aaff"] - n3v1 [label="(n3v1) source_iter({\l use crate::__staged::negation::*;\l 3..6\l})\l", shape=invhouse, fillcolor="#88aaff"] - n5v1 [label="(n5v1) difference::<'tick, 'static>()", shape=invhouse, fillcolor="#88aaff"] - n6v3 [label="(n6v3) handoff", shape=parallelogram, fillcolor="#ddddff"] - n7v1 [label="(n7v1) for_each({\l use crate::__staged::negation::*;\l let output = output;\l |v| {\l output.send(v).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] - n6v3 -> n5v1 [label="neg", color=red] - n1v1 -> n5v1 [label="pos"] - n3v1 -> n6v3 - n5v1 -> n7v1 + n2v1 [label="(n2v1) source_iter({\l use crate::__staged::negation::*;\l 3..6\l})\l", shape=invhouse, fillcolor="#88aaff"] + n3v1 [label="(n3v1) difference::<'tick, 'static>()", shape=invhouse, fillcolor="#88aaff"] + n4v1 [label="(n4v1) for_each({\l use crate::__staged::negation::*;\l let output = output;\l |v| {\l output.send(v).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] + n5v1 [label="(n5v1) handoff", shape=parallelogram, fillcolor="#ddddff"] + n1v1 -> n3v1 [label="pos"] + n2v1 -> n5v1 + n3v1 -> n4v1 + n5v1 -> n3v1 [label="neg", color=red] subgraph "cluster n1v1" { fillcolor="#dddddd" style=filled label = "sg_1v1\nstratum 0" - n3v1 + n2v1 subgraph "cluster_sg_1v1_var_stream_1" { label="var stream_1" - n3v1 + n2v1 } } subgraph "cluster n2v1" { @@ -29,15 +29,15 @@ digraph { style=filled label = "sg_2v1\nstratum 1" n1v1 - n5v1 - n7v1 + n3v1 + n4v1 subgraph "cluster_sg_2v1_var_stream_0" { label="var stream_0" n1v1 } subgraph "cluster_sg_2v1_var_stream_2" { label="var stream_2" - n5v1 + n3v1 } } } diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_tick_static@graphvis_mermaid.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_tick_static@graphvis_mermaid.snap index 38799685ffcd..4b99af438434 100644 --- a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_tick_static@graphvis_mermaid.snap +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_tick_static@graphvis_mermaid.snap @@ -9,29 +9,29 @@ classDef pushClass fill:#ff8,stroke:#000,text-align:left,white-space:pre classDef otherClass fill:#fdc,stroke:#000,text-align:left,white-space:pre linkStyle default stroke:#aaa 1v1[\"
(1v1)
source_iter({
use crate::__staged::negation::*;
0..5
})
"/]:::pullClass -3v1[\"
(3v1)
source_iter({
use crate::__staged::negation::*;
3..6
})
"/]:::pullClass -5v1[\"(5v1) difference::<'tick, 'static>()"/]:::pullClass -6v3["(6v3) handoff"]:::otherClass -7v1[/"
(7v1)
for_each({
use crate::__staged::negation::*;
let output = output;
|v| {
output.send(v).unwrap();
}
})
"\]:::pushClass -6v3--x|neg|5v1; linkStyle 0 stroke:red -1v1-->|pos|5v1 -3v1-->6v3 -5v1-->7v1 +2v1[\"
(2v1)
source_iter({
use crate::__staged::negation::*;
3..6
})
"/]:::pullClass +3v1[\"(3v1) difference::<'tick, 'static>()"/]:::pullClass +4v1[/"
(4v1)
for_each({
use crate::__staged::negation::*;
let output = output;
|v| {
output.send(v).unwrap();
}
})
"\]:::pushClass +5v1["(5v1) handoff"]:::otherClass +1v1-->|pos|3v1 +2v1-->5v1 +3v1-->4v1 +5v1--x|neg|3v1; linkStyle 3 stroke:red subgraph sg_1v1 ["sg_1v1 stratum 0"] - 3v1 + 2v1 subgraph sg_1v1_var_stream_1 ["var stream_1"] - 3v1 + 2v1 end end subgraph sg_2v1 ["sg_2v1 stratum 1"] 1v1 - 5v1 - 7v1 + 3v1 + 4v1 subgraph sg_2v1_var_stream_0 ["var stream_0"] 1v1 end subgraph sg_2v1_var_stream_2 ["var stream_2"] - 5v1 + 3v1 end end diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_tick_tick@graphvis_dot.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_tick_tick@graphvis_dot.snap index e46944a42714..f76a74c848e9 100644 --- a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_tick_tick@graphvis_dot.snap +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_tick_tick@graphvis_dot.snap @@ -6,22 +6,22 @@ digraph { node [fontname="Monaco,Menlo,Consolas,"Droid Sans Mono",Inconsolata,"Courier New",monospace", style=filled]; edge [fontname="Monaco,Menlo,Consolas,"Droid Sans Mono",Inconsolata,"Courier New",monospace"]; n1v1 [label="(n1v1) source_iter({\l use crate::__staged::negation::*;\l 0..5\l})\l", shape=invhouse, fillcolor="#88aaff"] - n3v1 [label="(n3v1) source_iter({\l use crate::__staged::negation::*;\l 3..6\l})\l", shape=invhouse, fillcolor="#88aaff"] - n5v1 [label="(n5v1) difference::<'tick, 'tick>()", shape=invhouse, fillcolor="#88aaff"] - n6v3 [label="(n6v3) handoff", shape=parallelogram, fillcolor="#ddddff"] - n7v1 [label="(n7v1) for_each({\l use crate::__staged::negation::*;\l let output = output;\l |v| {\l output.send(v).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] - n6v3 -> n5v1 [label="neg", color=red] - n1v1 -> n5v1 [label="pos"] - n3v1 -> n6v3 - n5v1 -> n7v1 + n2v1 [label="(n2v1) source_iter({\l use crate::__staged::negation::*;\l 3..6\l})\l", shape=invhouse, fillcolor="#88aaff"] + n3v1 [label="(n3v1) difference::<'tick, 'tick>()", shape=invhouse, fillcolor="#88aaff"] + n4v1 [label="(n4v1) for_each({\l use crate::__staged::negation::*;\l let output = output;\l |v| {\l output.send(v).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] + n5v1 [label="(n5v1) handoff", shape=parallelogram, fillcolor="#ddddff"] + n1v1 -> n3v1 [label="pos"] + n2v1 -> n5v1 + n3v1 -> n4v1 + n5v1 -> n3v1 [label="neg", color=red] subgraph "cluster n1v1" { fillcolor="#dddddd" style=filled label = "sg_1v1\nstratum 0" - n3v1 + n2v1 subgraph "cluster_sg_1v1_var_stream_1" { label="var stream_1" - n3v1 + n2v1 } } subgraph "cluster n2v1" { @@ -29,15 +29,15 @@ digraph { style=filled label = "sg_2v1\nstratum 1" n1v1 - n5v1 - n7v1 + n3v1 + n4v1 subgraph "cluster_sg_2v1_var_stream_0" { label="var stream_0" n1v1 } subgraph "cluster_sg_2v1_var_stream_2" { label="var stream_2" - n5v1 + n3v1 } } } diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_tick_tick@graphvis_mermaid.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_tick_tick@graphvis_mermaid.snap index c9240a3484b2..7b55339710f3 100644 --- a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_tick_tick@graphvis_mermaid.snap +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__negation__tests__difference_tick_tick@graphvis_mermaid.snap @@ -9,29 +9,29 @@ classDef pushClass fill:#ff8,stroke:#000,text-align:left,white-space:pre classDef otherClass fill:#fdc,stroke:#000,text-align:left,white-space:pre linkStyle default stroke:#aaa 1v1[\"
(1v1)
source_iter({
use crate::__staged::negation::*;
0..5
})
"/]:::pullClass -3v1[\"
(3v1)
source_iter({
use crate::__staged::negation::*;
3..6
})
"/]:::pullClass -5v1[\"(5v1) difference::<'tick, 'tick>()"/]:::pullClass -6v3["(6v3) handoff"]:::otherClass -7v1[/"
(7v1)
for_each({
use crate::__staged::negation::*;
let output = output;
|v| {
output.send(v).unwrap();
}
})
"\]:::pushClass -6v3--x|neg|5v1; linkStyle 0 stroke:red -1v1-->|pos|5v1 -3v1-->6v3 -5v1-->7v1 +2v1[\"
(2v1)
source_iter({
use crate::__staged::negation::*;
3..6
})
"/]:::pullClass +3v1[\"(3v1) difference::<'tick, 'tick>()"/]:::pullClass +4v1[/"
(4v1)
for_each({
use crate::__staged::negation::*;
let output = output;
|v| {
output.send(v).unwrap();
}
})
"\]:::pushClass +5v1["(5v1) handoff"]:::otherClass +1v1-->|pos|3v1 +2v1-->5v1 +3v1-->4v1 +5v1--x|neg|3v1; linkStyle 3 stroke:red subgraph sg_1v1 ["sg_1v1 stratum 0"] - 3v1 + 2v1 subgraph sg_1v1_var_stream_1 ["var stream_1"] - 3v1 + 2v1 end end subgraph sg_2v1 ["sg_2v1 stratum 1"] 1v1 - 5v1 - 7v1 + 3v1 + 4v1 subgraph sg_2v1_var_stream_0 ["var stream_0"] 1v1 end subgraph sg_2v1_var_stream_2 ["var stream_2"] - 5v1 + 3v1 end end diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__networked__tests__networked_basic.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__networked__tests__networked_basic.snap new file mode 100644 index 000000000000..49fd5e06da6b --- /dev/null +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__networked__tests__networked_basic.snap @@ -0,0 +1,36 @@ +--- +source: hydroflow_plus_test/src/networked.rs +expression: builder.ir() +--- +[ + ForEach { + f: { use crate :: __staged :: networked :: * ; | v : Result < BytesMut , _ > | { println ! ("node one received: {:?}" , std :: str :: from_utf8 (& v . unwrap ()) . unwrap ()) ; } }, + input: Network { + to_location: 1, + serialize_pipeline: None, + sink_expr: null, + source_expr: null, + deserialize_pipeline: None, + input: Map { + f: { use crate :: __staged :: networked :: * ; | v | v . unwrap () . freeze () }, + input: Source { + source: Stream( + null, + ), + produces_delta: false, + location_id: 0, + }, + }, + }, + }, + ForEach { + f: { use crate :: __staged :: networked :: * ; | v : Result < BytesMut , _ > | { println ! ("cluster received: {:?}" , std :: str :: from_utf8 (& v . unwrap ()) . unwrap ()) ; } }, + input: Source { + source: Stream( + null, + ), + produces_delta: false, + location_id: 2, + }, + }, +] diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__chat_app_no_replay@graphvis_dot.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__chat_app_no_replay@graphvis_dot.snap index 051e3e515c60..f423b24cdc00 100644 --- a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__chat_app_no_replay@graphvis_dot.snap +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__chat_app_no_replay@graphvis_dot.snap @@ -6,31 +6,31 @@ digraph { node [fontname="Monaco,Menlo,Consolas,"Droid Sans Mono",Inconsolata,"Courier New",monospace", style=filled]; edge [fontname="Monaco,Menlo,Consolas,"Droid Sans Mono",Inconsolata,"Courier New",monospace"]; n1v1 [label="(n1v1) source_stream(users_stream)", shape=invhouse, fillcolor="#88aaff"] - n3v1 [label="(n3v1) source_stream(messages)", shape=invhouse, fillcolor="#88aaff"] - n5v1 [label="(n5v1) cross_join::<'static, 'tick>()", shape=invhouse, fillcolor="#88aaff"] - n7v1 [label="(n7v1) for_each({\l use crate::__staged::*;\l let output = output;\l |t| {\l output.send(t).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] - n1v1 -> n5v1 [label="0"] - n3v1 -> n5v1 [label="1"] - n5v1 -> n7v1 + n2v1 [label="(n2v1) source_stream(messages)", shape=invhouse, fillcolor="#88aaff"] + n3v1 [label="(n3v1) cross_join::<'static, 'tick>()", shape=invhouse, fillcolor="#88aaff"] + n4v1 [label="(n4v1) for_each({\l use crate::__staged::*;\l let output = output;\l |t| {\l output.send(t).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] + n1v1 -> n3v1 [label="0"] + n2v1 -> n3v1 [label="1"] + n3v1 -> n4v1 subgraph "cluster n1v1" { fillcolor="#dddddd" style=filled label = "sg_1v1\nstratum 0" n1v1 + n2v1 n3v1 - n5v1 - n7v1 + n4v1 subgraph "cluster_sg_1v1_var_stream_0" { label="var stream_0" n1v1 } subgraph "cluster_sg_1v1_var_stream_1" { label="var stream_1" - n3v1 + n2v1 } subgraph "cluster_sg_1v1_var_stream_2" { label="var stream_2" - n5v1 + n3v1 } } } diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__chat_app_no_replay@graphvis_mermaid.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__chat_app_no_replay@graphvis_mermaid.snap index 4eb704215e81..f972925cd858 100644 --- a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__chat_app_no_replay@graphvis_mermaid.snap +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__chat_app_no_replay@graphvis_mermaid.snap @@ -9,25 +9,25 @@ classDef pushClass fill:#ff8,stroke:#000,text-align:left,white-space:pre classDef otherClass fill:#fdc,stroke:#000,text-align:left,white-space:pre linkStyle default stroke:#aaa 1v1[\"(1v1) source_stream(users_stream)"/]:::pullClass -3v1[\"(3v1) source_stream(messages)"/]:::pullClass -5v1[\"(5v1) cross_join::<'static, 'tick>()"/]:::pullClass -7v1[/"
(7v1)
for_each({
use crate::__staged::*;
let output = output;
|t| {
output.send(t).unwrap();
}
})
"\]:::pushClass -1v1-->|0|5v1 -3v1-->|1|5v1 -5v1-->7v1 +2v1[\"(2v1) source_stream(messages)"/]:::pullClass +3v1[\"(3v1) cross_join::<'static, 'tick>()"/]:::pullClass +4v1[/"
(4v1)
for_each({
use crate::__staged::*;
let output = output;
|t| {
output.send(t).unwrap();
}
})
"\]:::pushClass +1v1-->|0|3v1 +2v1-->|1|3v1 +3v1-->4v1 subgraph sg_1v1 ["sg_1v1 stratum 0"] 1v1 + 2v1 3v1 - 5v1 - 7v1 + 4v1 subgraph sg_1v1_var_stream_0 ["var stream_0"] 1v1 end subgraph sg_1v1_var_stream_1 ["var stream_1"] - 3v1 + 2v1 end subgraph sg_1v1_var_stream_2 ["var stream_2"] - 5v1 + 3v1 end end diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__chat_app_replay@graphvis_dot.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__chat_app_replay@graphvis_dot.snap index 462937c27f23..5f0fb782936a 100644 --- a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__chat_app_replay@graphvis_dot.snap +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__chat_app_replay@graphvis_dot.snap @@ -6,38 +6,38 @@ digraph { node [fontname="Monaco,Menlo,Consolas,"Droid Sans Mono",Inconsolata,"Courier New",monospace", style=filled]; edge [fontname="Monaco,Menlo,Consolas,"Droid Sans Mono",Inconsolata,"Courier New",monospace"]; n1v1 [label="(n1v1) source_stream(users_stream)", shape=invhouse, fillcolor="#88aaff"] - n3v1 [label="(n3v1) source_stream(messages)", shape=invhouse, fillcolor="#88aaff"] - n5v1 [label="(n5v1) cross_join::<'static, 'static>()", shape=invhouse, fillcolor="#88aaff"] - n7v1 [label="(n7v1) multiset_delta()", shape=invhouse, fillcolor="#88aaff"] - n9v1 [label="(n9v1) for_each({\l use crate::__staged::*;\l let output = output;\l |t| {\l output.send(t).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] - n1v1 -> n5v1 [label="0"] - n3v1 -> n5v1 [label="1"] - n5v1 -> n7v1 - n7v1 -> n9v1 + n2v1 [label="(n2v1) source_stream(messages)", shape=invhouse, fillcolor="#88aaff"] + n3v1 [label="(n3v1) cross_join::<'static, 'static>()", shape=invhouse, fillcolor="#88aaff"] + n4v1 [label="(n4v1) multiset_delta()", shape=invhouse, fillcolor="#88aaff"] + n5v1 [label="(n5v1) for_each({\l use crate::__staged::*;\l let output = output;\l |t| {\l output.send(t).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] + n1v1 -> n3v1 [label="0"] + n2v1 -> n3v1 [label="1"] + n3v1 -> n4v1 + n4v1 -> n5v1 subgraph "cluster n1v1" { fillcolor="#dddddd" style=filled label = "sg_1v1\nstratum 0" n1v1 + n2v1 n3v1 + n4v1 n5v1 - n7v1 - n9v1 subgraph "cluster_sg_1v1_var_stream_0" { label="var stream_0" n1v1 } subgraph "cluster_sg_1v1_var_stream_1" { label="var stream_1" - n3v1 + n2v1 } subgraph "cluster_sg_1v1_var_stream_2" { label="var stream_2" - n5v1 + n3v1 } subgraph "cluster_sg_1v1_var_stream_3" { label="var stream_3" - n7v1 + n4v1 } } } diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__chat_app_replay@graphvis_mermaid.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__chat_app_replay@graphvis_mermaid.snap index c54f7d30bf23..e64ab65406db 100644 --- a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__chat_app_replay@graphvis_mermaid.snap +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__chat_app_replay@graphvis_mermaid.snap @@ -9,31 +9,31 @@ classDef pushClass fill:#ff8,stroke:#000,text-align:left,white-space:pre classDef otherClass fill:#fdc,stroke:#000,text-align:left,white-space:pre linkStyle default stroke:#aaa 1v1[\"(1v1) source_stream(users_stream)"/]:::pullClass -3v1[\"(3v1) source_stream(messages)"/]:::pullClass -5v1[\"(5v1) cross_join::<'static, 'static>()"/]:::pullClass -7v1[\"(7v1) multiset_delta()"/]:::pullClass -9v1[/"
(9v1)
for_each({
use crate::__staged::*;
let output = output;
|t| {
output.send(t).unwrap();
}
})
"\]:::pushClass -1v1-->|0|5v1 -3v1-->|1|5v1 -5v1-->7v1 -7v1-->9v1 +2v1[\"(2v1) source_stream(messages)"/]:::pullClass +3v1[\"(3v1) cross_join::<'static, 'static>()"/]:::pullClass +4v1[\"(4v1) multiset_delta()"/]:::pullClass +5v1[/"
(5v1)
for_each({
use crate::__staged::*;
let output = output;
|t| {
output.send(t).unwrap();
}
})
"\]:::pushClass +1v1-->|0|3v1 +2v1-->|1|3v1 +3v1-->4v1 +4v1-->5v1 subgraph sg_1v1 ["sg_1v1 stratum 0"] 1v1 + 2v1 3v1 + 4v1 5v1 - 7v1 - 9v1 subgraph sg_1v1_var_stream_0 ["var stream_0"] 1v1 end subgraph sg_1v1_var_stream_1 ["var stream_1"] - 3v1 + 2v1 end subgraph sg_1v1_var_stream_2 ["var stream_2"] - 5v1 + 3v1 end subgraph sg_1v1_var_stream_3 ["var stream_3"] - 7v1 + 4v1 end end diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__count@graphvis_dot.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__count@graphvis_dot.snap index a991b2f4265b..52a3191e1004 100644 --- a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__count@graphvis_dot.snap +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__count@graphvis_dot.snap @@ -6,38 +6,38 @@ digraph { node [fontname="Monaco,Menlo,Consolas,"Droid Sans Mono",Inconsolata,"Courier New",monospace", style=filled]; edge [fontname="Monaco,Menlo,Consolas,"Droid Sans Mono",Inconsolata,"Courier New",monospace"]; n1v1 [label="(n1v1) source_stream(input_stream)", shape=invhouse, fillcolor="#88aaff"] - n3v1 [label="(n3v1) map({\l use crate::__staged::*;\l |_| 1\l})\l", shape=invhouse, fillcolor="#88aaff"] - n5v1 [label="(n5v1) fold::<\l 'tick,\l>(\l {\l use crate::__staged::*;\l || 0\l },\l {\l use crate::__staged::*;\l |a, b| *a += b\l },\l)\l", shape=invhouse, fillcolor="#88aaff"] - n6v3 [label="(n6v3) handoff", shape=parallelogram, fillcolor="#ddddff"] - n7v1 [label="(n7v1) for_each({\l use crate::__staged::*;\l let output = output;\l |v| {\l output.send(v).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] - n1v1 -> n3v1 - n6v3 -> n5v1 [color=red] - n3v1 -> n6v3 - n5v1 -> n7v1 + n2v1 [label="(n2v1) map({\l use crate::__staged::*;\l |_| 1\l})\l", shape=invhouse, fillcolor="#88aaff"] + n3v1 [label="(n3v1) fold::<\l 'tick,\l>(\l {\l use crate::__staged::*;\l || 0\l },\l {\l use crate::__staged::*;\l |a, b| *a += b\l },\l)\l", shape=invhouse, fillcolor="#88aaff"] + n4v1 [label="(n4v1) for_each({\l use crate::__staged::*;\l let output = output;\l |v| {\l output.send(v).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] + n5v1 [label="(n5v1) handoff", shape=parallelogram, fillcolor="#ddddff"] + n1v1 -> n2v1 + n2v1 -> n5v1 + n3v1 -> n4v1 + n5v1 -> n3v1 [color=red] subgraph "cluster n1v1" { fillcolor="#dddddd" style=filled label = "sg_1v1\nstratum 0" n1v1 - n3v1 + n2v1 subgraph "cluster_sg_1v1_var_stream_0" { label="var stream_0" n1v1 } subgraph "cluster_sg_1v1_var_stream_1" { label="var stream_1" - n3v1 + n2v1 } } subgraph "cluster n2v1" { fillcolor="#dddddd" style=filled label = "sg_2v1\nstratum 1" - n5v1 - n7v1 + n3v1 + n4v1 subgraph "cluster_sg_2v1_var_stream_2" { label="var stream_2" - n5v1 + n3v1 } } } diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__count@graphvis_mermaid.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__count@graphvis_mermaid.snap index 45bace491f36..6f60447726f7 100644 --- a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__count@graphvis_mermaid.snap +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__count@graphvis_mermaid.snap @@ -9,29 +9,29 @@ classDef pushClass fill:#ff8,stroke:#000,text-align:left,white-space:pre classDef otherClass fill:#fdc,stroke:#000,text-align:left,white-space:pre linkStyle default stroke:#aaa 1v1[\"(1v1) source_stream(input_stream)"/]:::pullClass -3v1[\"
(3v1)
map({
use crate::__staged::*;
|_| 1
})
"/]:::pullClass -5v1[\"
(5v1)
fold::<
'tick,
>(
{
use crate::__staged::*;
|| 0
},
{
use crate::__staged::*;
|a, b| *a += b
},
)
"/]:::pullClass -6v3["(6v3) handoff"]:::otherClass -7v1[/"
(7v1)
for_each({
use crate::__staged::*;
let output = output;
|v| {
output.send(v).unwrap();
}
})
"\]:::pushClass -1v1-->3v1 -6v3--x5v1; linkStyle 1 stroke:red -3v1-->6v3 -5v1-->7v1 +2v1[\"
(2v1)
map({
use crate::__staged::*;
|_| 1
})
"/]:::pullClass +3v1[\"
(3v1)
fold::<
'tick,
>(
{
use crate::__staged::*;
|| 0
},
{
use crate::__staged::*;
|a, b| *a += b
},
)
"/]:::pullClass +4v1[/"
(4v1)
for_each({
use crate::__staged::*;
let output = output;
|v| {
output.send(v).unwrap();
}
})
"\]:::pushClass +5v1["(5v1) handoff"]:::otherClass +1v1-->2v1 +2v1-->5v1 +3v1-->4v1 +5v1--x3v1; linkStyle 3 stroke:red subgraph sg_1v1 ["sg_1v1 stratum 0"] 1v1 - 3v1 + 2v1 subgraph sg_1v1_var_stream_0 ["var stream_0"] 1v1 end subgraph sg_1v1_var_stream_1 ["var stream_1"] - 3v1 + 2v1 end end subgraph sg_2v1 ["sg_2v1 stratum 1"] - 5v1 - 7v1 + 3v1 + 4v1 subgraph sg_2v1_var_stream_2 ["var stream_2"] - 5v1 + 3v1 end end diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__reachability@graphvis_dot.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__reachability@graphvis_dot.snap index bdda76412bf3..3406809856b1 100644 --- a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__reachability@graphvis_dot.snap +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__reachability@graphvis_dot.snap @@ -6,67 +6,70 @@ digraph { node [fontname="Monaco,Menlo,Consolas,"Droid Sans Mono",Inconsolata,"Courier New",monospace", style=filled]; edge [fontname="Monaco,Menlo,Consolas,"Droid Sans Mono",Inconsolata,"Courier New",monospace"]; n1v1 [label="(n1v1) source_stream(roots)", shape=invhouse, fillcolor="#88aaff"] - n3v1 [label="(n3v1) source_stream(edges)", shape=invhouse, fillcolor="#88aaff"] - n6v1 [label="(n6v1) union()", shape=invhouse, fillcolor="#88aaff"] - n7v1 [label="(n7v1) tee()", shape=house, fillcolor="#ffff88"] - n8v1 [label="(n8v1) map({\l use crate::__staged::*;\l |r| (r, ())\l})\l", shape=house, fillcolor="#ffff88"] - n10v1 [label="(n10v1) join::<'tick, 'tick>()", shape=invhouse, fillcolor="#88aaff"] - n12v1 [label="(n12v1) map({\l use crate::__staged::*;\l |(_from, (_, to))| to\l})\l", shape=invhouse, fillcolor="#88aaff"] - n14v1 [label="(n14v1) unique::<'tick>()", shape=house, fillcolor="#ffff88"] - n15v3 [label="(n15v3) handoff", shape=parallelogram, fillcolor="#ddddff"] - n16v1 [label="(n16v1) for_each({\l use crate::__staged::*;\l let reached_out = reached_out;\l |v| {\l reached_out.send(v).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] + n2v1 [label="(n2v1) union()", shape=invhouse, fillcolor="#88aaff"] + n3v1 [label="(n3v1) tee()", shape=house, fillcolor="#ffff88"] + n4v1 [label="(n4v1) map({\l use crate::__staged::*;\l |r| (r, ())\l})\l", shape=house, fillcolor="#ffff88"] + n5v1 [label="(n5v1) source_stream(edges)", shape=invhouse, fillcolor="#88aaff"] + n6v1 [label="(n6v1) join::<'tick, 'tick>()", shape=invhouse, fillcolor="#88aaff"] + n7v1 [label="(n7v1) map({\l use crate::__staged::*;\l |(_from, (_, to))| to\l})\l", shape=invhouse, fillcolor="#88aaff"] + n8v1 [label="(n8v1) unique::<'tick>()", shape=house, fillcolor="#ffff88"] + n9v1 [label="(n9v1) for_each({\l use crate::__staged::*;\l let reached_out = reached_out;\l |v| {\l reached_out.send(v).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] + n10v1 [label="(n10v1) handoff", shape=parallelogram, fillcolor="#ddddff"] + n1v1 -> n2v1 [label="0"] + n7v1 -> n2v1 [label="1"] + n2v1 -> n3v1 + n3v1 -> n4v1 + n4v1 -> n10v1 + n5v1 -> n6v1 [label="1"] n6v1 -> n7v1 - n1v1 -> n6v1 [label="0"] - n12v1 -> n6v1 [label="1"] - n7v1 -> n8v1 - n8v1 -> n15v3 - n3v1 -> n10v1 [label="1"] - n10v1 -> n12v1 - n15v3 -> n10v1 [label="0"] - n7v1 -> n14v1 - n14v1 -> n16v1 + n3v1 -> n8v1 + n8v1 -> n9v1 + n10v1 -> n6v1 [label="0"] subgraph "cluster n1v1" { fillcolor="#dddddd" style=filled label = "sg_1v1\nstratum 0" - n15v3 - n1v1 - n3v1 n10v1 - n12v1 + n1v1 + n5v1 n6v1 n7v1 + n2v1 + n3v1 + n4v1 n8v1 - n14v1 - n16v1 + n9v1 subgraph "cluster_sg_1v1_var_stream_0" { label="var stream_0" n1v1 } subgraph "cluster_sg_1v1_var_stream_1" { label="var stream_1" + n2v1 + } + subgraph "cluster_sg_1v1_var_stream_2" { + label="var stream_2" n3v1 } subgraph "cluster_sg_1v1_var_stream_3" { label="var stream_3" - n6v1 - n7v1 + n4v1 } subgraph "cluster_sg_1v1_var_stream_4" { label="var stream_4" - n8v1 + n5v1 } subgraph "cluster_sg_1v1_var_stream_5" { label="var stream_5" - n10v1 + n6v1 } subgraph "cluster_sg_1v1_var_stream_6" { label="var stream_6" - n12v1 + n7v1 } subgraph "cluster_sg_1v1_var_stream_7" { label="var stream_7" - n14v1 + n8v1 } } } diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__reachability@graphvis_mermaid.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__reachability@graphvis_mermaid.snap index 4408301d8305..14c4346453a1 100644 --- a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__reachability@graphvis_mermaid.snap +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__reachability@graphvis_mermaid.snap @@ -9,57 +9,59 @@ classDef pushClass fill:#ff8,stroke:#000,text-align:left,white-space:pre classDef otherClass fill:#fdc,stroke:#000,text-align:left,white-space:pre linkStyle default stroke:#aaa 1v1[\"(1v1) source_stream(roots)"/]:::pullClass -3v1[\"(3v1) source_stream(edges)"/]:::pullClass -6v1[\"(6v1) union()"/]:::pullClass -7v1[/"(7v1) tee()"\]:::pushClass -8v1[/"
(8v1)
map({
use crate::__staged::*;
|r| (r, ())
})
"\]:::pushClass -10v1[\"(10v1) join::<'tick, 'tick>()"/]:::pullClass -12v1[\"
(12v1)
map({
use crate::__staged::*;
|(_from, (_, to))| to
})
"/]:::pullClass -14v1[/"(14v1) unique::<'tick>()"\]:::pushClass -15v3["(15v3) handoff"]:::otherClass -16v1[/"
(16v1)
for_each({
use crate::__staged::*;
let reached_out = reached_out;
|v| {
reached_out.send(v).unwrap();
}
})
"\]:::pushClass +2v1[\"(2v1) union()"/]:::pullClass +3v1[/"(3v1) tee()"\]:::pushClass +4v1[/"
(4v1)
map({
use crate::__staged::*;
|r| (r, ())
})
"\]:::pushClass +5v1[\"(5v1) source_stream(edges)"/]:::pullClass +6v1[\"(6v1) join::<'tick, 'tick>()"/]:::pullClass +7v1[\"
(7v1)
map({
use crate::__staged::*;
|(_from, (_, to))| to
})
"/]:::pullClass +8v1[/"(8v1) unique::<'tick>()"\]:::pushClass +9v1[/"
(9v1)
for_each({
use crate::__staged::*;
let reached_out = reached_out;
|v| {
reached_out.send(v).unwrap();
}
})
"\]:::pushClass +10v1["(10v1) handoff"]:::otherClass +1v1-->|0|2v1 +7v1-->|1|2v1 +2v1-->3v1 +3v1-->4v1 +4v1-->10v1 +5v1-->|1|6v1 6v1-->7v1 -1v1-->|0|6v1 -12v1-->|1|6v1 -7v1-->8v1 -8v1-->15v3 -3v1-->|1|10v1 -10v1-->12v1 -15v3-->|0|10v1 -7v1-->14v1 -14v1-->16v1 +3v1-->8v1 +8v1-->9v1 +10v1-->|0|6v1 subgraph sg_1v1 ["sg_1v1 stratum 0"] - 15v3 - 1v1 - 3v1 10v1 - 12v1 + 1v1 + 5v1 6v1 7v1 + 2v1 + 3v1 + 4v1 8v1 - 14v1 - 16v1 + 9v1 subgraph sg_1v1_var_stream_0 ["var stream_0"] 1v1 end subgraph sg_1v1_var_stream_1 ["var stream_1"] + 2v1 + end + subgraph sg_1v1_var_stream_2 ["var stream_2"] 3v1 end subgraph sg_1v1_var_stream_3 ["var stream_3"] - 6v1 - 7v1 + 4v1 end subgraph sg_1v1_var_stream_4 ["var stream_4"] - 8v1 + 5v1 end subgraph sg_1v1_var_stream_5 ["var stream_5"] - 10v1 + 6v1 end subgraph sg_1v1_var_stream_6 ["var stream_6"] - 12v1 + 7v1 end subgraph sg_1v1_var_stream_7 ["var stream_7"] - 14v1 + 8v1 end end diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__teed_join@graphvis_dot.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__teed_join@graphvis_dot.snap index c1d61efa862c..f60dc47e0dbf 100644 --- a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__teed_join@graphvis_dot.snap +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__teed_join@graphvis_dot.snap @@ -8,21 +8,21 @@ digraph { n1v1 [label="(n1v1) source_stream(input_stream)", shape=invhouse, fillcolor="#88aaff"] n2v1 [label="(n2v1) tee()", shape=house, fillcolor="#ffff88"] n3v1 [label="(n3v1) map({\l use crate::__staged::*;\l |v| (v + 1, ())\l})\l", shape=house, fillcolor="#ffff88"] - n5v1 [label="(n5v1) map({\l use crate::__staged::*;\l |v| (v - 1, ())\l})\l", shape=house, fillcolor="#ffff88"] - n7v1 [label="(n7v1) join::<'tick, 'tick>()", shape=invhouse, fillcolor="#88aaff"] - n8v3 [label="(n8v3) handoff", shape=parallelogram, fillcolor="#ddddff"] - n9v1 [label="(n9v1) map({\l use crate::__staged::*;\l |t| t.0\l})\l", shape=invhouse, fillcolor="#88aaff"] - n10v3 [label="(n10v3) handoff", shape=parallelogram, fillcolor="#ddddff"] - n11v1 [label="(n11v1) for_each({\l use crate::__staged::*;\l let output = output;\l |v| {\l output.send(v).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] + n4v1 [label="(n4v1) map({\l use crate::__staged::*;\l |v| (v - 1, ())\l})\l", shape=house, fillcolor="#ffff88"] + n5v1 [label="(n5v1) join::<'tick, 'tick>()", shape=invhouse, fillcolor="#88aaff"] + n6v1 [label="(n6v1) map({\l use crate::__staged::*;\l |t| t.0\l})\l", shape=invhouse, fillcolor="#88aaff"] + n7v3 [label="(n7v3) handoff", shape=parallelogram, fillcolor="#ddddff"] + n8v1 [label="(n8v1) for_each({\l use crate::__staged::*;\l let output = output;\l |v| {\l output.send(v).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] + n9v1 [label="(n9v1) handoff", shape=parallelogram, fillcolor="#ddddff"] n1v1 -> n2v1 n2v1 -> n3v1 - n2v1 -> n5v1 - n8v3 -> n7v1 [label="1"] - n3v1 -> n10v3 - n5v1 -> n8v3 - n10v3 -> n7v1 [label="0"] - n7v1 -> n9v1 - n9v1 -> n11v1 + n2v1 -> n4v1 + n3v1 -> n7v3 + n4v1 -> n9v1 + n5v1 -> n6v1 + n7v3 -> n5v1 [label="0"] + n6v1 -> n8v1 + n9v1 -> n5v1 [label="1"] subgraph "cluster n1v1" { fillcolor="#dddddd" style=filled @@ -30,35 +30,38 @@ digraph { n1v1 n2v1 n3v1 - n5v1 + n4v1 subgraph "cluster_sg_1v1_var_stream_0" { label="var stream_0" n1v1 - n2v1 } subgraph "cluster_sg_1v1_var_stream_1" { label="var stream_1" - n3v1 + n2v1 } subgraph "cluster_sg_1v1_var_stream_2" { label="var stream_2" - n5v1 + n3v1 + } + subgraph "cluster_sg_1v1_var_stream_3" { + label="var stream_3" + n4v1 } } subgraph "cluster n2v1" { fillcolor="#dddddd" style=filled label = "sg_2v1\nstratum 0" - n7v1 - n9v1 - n11v1 - subgraph "cluster_sg_2v1_var_stream_3" { - label="var stream_3" - n7v1 - } + n5v1 + n6v1 + n8v1 subgraph "cluster_sg_2v1_var_stream_4" { label="var stream_4" - n9v1 + n5v1 + } + subgraph "cluster_sg_2v1_var_stream_5" { + label="var stream_5" + n6v1 } } } diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__teed_join@graphvis_mermaid.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__teed_join@graphvis_mermaid.snap index 257614e9cf06..5c0b6e9eb093 100644 --- a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__teed_join@graphvis_mermaid.snap +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__teed_join@graphvis_mermaid.snap @@ -11,46 +11,48 @@ linkStyle default stroke:#aaa 1v1[\"(1v1) source_stream(input_stream)"/]:::pullClass 2v1[/"(2v1) tee()"\]:::pushClass 3v1[/"
(3v1)
map({
use crate::__staged::*;
|v| (v + 1, ())
})
"\]:::pushClass -5v1[/"
(5v1)
map({
use crate::__staged::*;
|v| (v - 1, ())
})
"\]:::pushClass -7v1[\"(7v1) join::<'tick, 'tick>()"/]:::pullClass -8v3["(8v3) handoff"]:::otherClass -9v1[\"
(9v1)
map({
use crate::__staged::*;
|t| t.0
})
"/]:::pullClass -10v3["(10v3) handoff"]:::otherClass -11v1[/"
(11v1)
for_each({
use crate::__staged::*;
let output = output;
|v| {
output.send(v).unwrap();
}
})
"\]:::pushClass +4v1[/"
(4v1)
map({
use crate::__staged::*;
|v| (v - 1, ())
})
"\]:::pushClass +5v1[\"(5v1) join::<'tick, 'tick>()"/]:::pullClass +6v1[\"
(6v1)
map({
use crate::__staged::*;
|t| t.0
})
"/]:::pullClass +7v3["(7v3) handoff"]:::otherClass +8v1[/"
(8v1)
for_each({
use crate::__staged::*;
let output = output;
|v| {
output.send(v).unwrap();
}
})
"\]:::pushClass +9v1["(9v1) handoff"]:::otherClass 1v1-->2v1 2v1-->3v1 -2v1-->5v1 -8v3-->|1|7v1 -3v1-->10v3 -5v1-->8v3 -10v3-->|0|7v1 -7v1-->9v1 -9v1-->11v1 +2v1-->4v1 +3v1-->7v3 +4v1-->9v1 +5v1-->6v1 +7v3-->|0|5v1 +6v1-->8v1 +9v1-->|1|5v1 subgraph sg_1v1 ["sg_1v1 stratum 0"] 1v1 2v1 3v1 - 5v1 + 4v1 subgraph sg_1v1_var_stream_0 ["var stream_0"] 1v1 - 2v1 end subgraph sg_1v1_var_stream_1 ["var stream_1"] - 3v1 + 2v1 end subgraph sg_1v1_var_stream_2 ["var stream_2"] - 5v1 + 3v1 + end + subgraph sg_1v1_var_stream_3 ["var stream_3"] + 4v1 end end subgraph sg_2v1 ["sg_2v1 stratum 0"] - 7v1 - 9v1 - 11v1 - subgraph sg_2v1_var_stream_3 ["var stream_3"] - 7v1 - end + 5v1 + 6v1 + 8v1 subgraph sg_2v1_var_stream_4 ["var stream_4"] - 9v1 + 5v1 + end + subgraph sg_2v1_var_stream_5 ["var stream_5"] + 6v1 end end diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__teed_join_multi_node@graphvis_dot.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__teed_join_multi_node@graphvis_dot.snap index ffd86cc1aba7..517ade444503 100644 --- a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__teed_join_multi_node@graphvis_dot.snap +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__teed_join_multi_node@graphvis_dot.snap @@ -6,16 +6,16 @@ digraph { node [fontname="Monaco,Menlo,Consolas,"Droid Sans Mono",Inconsolata,"Courier New",monospace", style=filled]; edge [fontname="Monaco,Menlo,Consolas,"Droid Sans Mono",Inconsolata,"Courier New",monospace"]; n1v1 [label="(n1v1) source_iter({\l use crate::__staged::*;\l 0..5\l})\l", shape=invhouse, fillcolor="#88aaff"] - n3v1 [label="(n3v1) for_each({\l use crate::__staged::*;\l let output = output;\l |v| {\l output.send(v).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] - n1v1 -> n3v1 + n2v1 [label="(n2v1) for_each({\l use crate::__staged::*;\l let output = output;\l |v| {\l output.send(v).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] + n1v1 -> n2v1 subgraph "cluster n1v1" { fillcolor="#dddddd" style=filled label = "sg_1v1\nstratum 0" n1v1 - n3v1 - subgraph "cluster_sg_1v1_var_stream_5" { - label="var stream_5" + n2v1 + subgraph "cluster_sg_1v1_var_stream_7" { + label="var stream_7" n1v1 } } diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__teed_join_multi_node@graphvis_mermaid.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__teed_join_multi_node@graphvis_mermaid.snap index 9d1dbadc8263..654848f69127 100644 --- a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__teed_join_multi_node@graphvis_mermaid.snap +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__teed_join_multi_node@graphvis_mermaid.snap @@ -9,12 +9,12 @@ classDef pushClass fill:#ff8,stroke:#000,text-align:left,white-space:pre classDef otherClass fill:#fdc,stroke:#000,text-align:left,white-space:pre linkStyle default stroke:#aaa 1v1[\"
(1v1)
source_iter({
use crate::__staged::*;
0..5
})
"/]:::pullClass -3v1[/"
(3v1)
for_each({
use crate::__staged::*;
let output = output;
|v| {
output.send(v).unwrap();
}
})
"\]:::pushClass -1v1-->3v1 +2v1[/"
(2v1)
for_each({
use crate::__staged::*;
let output = output;
|v| {
output.send(v).unwrap();
}
})
"\]:::pushClass +1v1-->2v1 subgraph sg_1v1 ["sg_1v1 stratum 0"] 1v1 - 3v1 - subgraph sg_1v1_var_stream_5 ["var stream_5"] + 2v1 + subgraph sg_1v1_var_stream_7 ["var stream_7"] 1v1 end end diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__teed_join_twice@graphvis_dot.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__teed_join_twice@graphvis_dot.snap index ace69bfc4365..60bea5bf7f76 100644 --- a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__teed_join_twice@graphvis_dot.snap +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__teed_join_twice@graphvis_dot.snap @@ -8,25 +8,25 @@ digraph { n1v1 [label="(n1v1) source_stream(input_stream)", shape=invhouse, fillcolor="#88aaff"] n2v1 [label="(n2v1) tee()", shape=house, fillcolor="#ffff88"] n3v1 [label="(n3v1) map({\l use crate::__staged::*;\l |v| (v + 1, ())\l})\l", shape=house, fillcolor="#ffff88"] - n5v1 [label="(n5v1) map({\l use crate::__staged::*;\l |v| (v - 1, ())\l})\l", shape=house, fillcolor="#ffff88"] - n6v3 [label="(n6v3) handoff", shape=parallelogram, fillcolor="#ddddff"] - n7v1 [label="(n7v1) join::<'tick, 'tick>()", shape=invhouse, fillcolor="#88aaff"] - n8v3 [label="(n8v3) handoff", shape=parallelogram, fillcolor="#ddddff"] - n9v1 [label="(n9v1) map({\l use crate::__staged::*;\l |t| t.0\l})\l", shape=invhouse, fillcolor="#88aaff"] - n10v1 [label="(n10v1) tee()", shape=house, fillcolor="#ffff88"] - n11v1 [label="(n11v1) for_each({\l use crate::__staged::*;\l let output = output;\l |v| {\l output.send(v).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] - n12v1 [label="(n12v1) for_each({\l use crate::__staged::*;\l let output = output;\l |v| {\l output.send(v).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] + n4v1 [label="(n4v1) map({\l use crate::__staged::*;\l |v| (v - 1, ())\l})\l", shape=house, fillcolor="#ffff88"] + n5v1 [label="(n5v1) join::<'tick, 'tick>()", shape=invhouse, fillcolor="#88aaff"] + n6v1 [label="(n6v1) map({\l use crate::__staged::*;\l |t| t.0\l})\l", shape=invhouse, fillcolor="#88aaff"] + n7v1 [label="(n7v1) tee()", shape=house, fillcolor="#ffff88"] + n8v1 [label="(n8v1) for_each({\l use crate::__staged::*;\l let output = output;\l |v| {\l output.send(v).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] + n9v1 [label="(n9v1) for_each({\l use crate::__staged::*;\l let output = output;\l |v| {\l output.send(v).unwrap();\l }\l})\l", shape=house, fillcolor="#ffff88"] + n10v1 [label="(n10v1) handoff", shape=parallelogram, fillcolor="#ddddff"] + n11v1 [label="(n11v1) handoff", shape=parallelogram, fillcolor="#ddddff"] n1v1 -> n2v1 n2v1 -> n3v1 - n6v3 -> n7v1 [label="1"] - n2v1 -> n5v1 - n8v3 -> n7v1 [label="0"] - n3v1 -> n8v3 - n5v1 -> n6v3 - n9v1 -> n10v1 + n2v1 -> n4v1 + n3v1 -> n10v1 + n4v1 -> n11v1 + n5v1 -> n6v1 + n6v1 -> n7v1 + n7v1 -> n8v1 n7v1 -> n9v1 - n10v1 -> n11v1 - n10v1 -> n12v1 + n10v1 -> n5v1 [label="0"] + n11v1 -> n5v1 [label="1"] subgraph "cluster n1v1" { fillcolor="#dddddd" style=filled @@ -34,38 +34,44 @@ digraph { n1v1 n2v1 n3v1 - n5v1 + n4v1 subgraph "cluster_sg_1v1_var_stream_0" { label="var stream_0" n1v1 - n2v1 } subgraph "cluster_sg_1v1_var_stream_1" { label="var stream_1" - n3v1 + n2v1 } subgraph "cluster_sg_1v1_var_stream_2" { label="var stream_2" - n5v1 + n3v1 + } + subgraph "cluster_sg_1v1_var_stream_3" { + label="var stream_3" + n4v1 } } subgraph "cluster n2v1" { fillcolor="#dddddd" style=filled label = "sg_2v1\nstratum 0" + n5v1 + n6v1 n7v1 + n8v1 n9v1 - n10v1 - n11v1 - n12v1 - subgraph "cluster_sg_2v1_var_stream_3" { - label="var stream_3" - n7v1 - } subgraph "cluster_sg_2v1_var_stream_4" { label="var stream_4" - n9v1 - n10v1 + n5v1 + } + subgraph "cluster_sg_2v1_var_stream_5" { + label="var stream_5" + n6v1 + } + subgraph "cluster_sg_2v1_var_stream_6" { + label="var stream_6" + n7v1 } } } diff --git a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__teed_join_twice@graphvis_mermaid.snap b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__teed_join_twice@graphvis_mermaid.snap index d81160f1a859..40abe10fecbd 100644 --- a/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__teed_join_twice@graphvis_mermaid.snap +++ b/hydroflow_plus_test/src/snapshots/hydroflow_plus_test__tests__teed_join_twice@graphvis_mermaid.snap @@ -11,53 +11,57 @@ linkStyle default stroke:#aaa 1v1[\"(1v1) source_stream(input_stream)"/]:::pullClass 2v1[/"(2v1) tee()"\]:::pushClass 3v1[/"
(3v1)
map({
use crate::__staged::*;
|v| (v + 1, ())
})
"\]:::pushClass -5v1[/"
(5v1)
map({
use crate::__staged::*;
|v| (v - 1, ())
})
"\]:::pushClass -6v3["(6v3) handoff"]:::otherClass -7v1[\"(7v1) join::<'tick, 'tick>()"/]:::pullClass -8v3["(8v3) handoff"]:::otherClass -9v1[\"
(9v1)
map({
use crate::__staged::*;
|t| t.0
})
"/]:::pullClass -10v1[/"(10v1) tee()"\]:::pushClass -11v1[/"
(11v1)
for_each({
use crate::__staged::*;
let output = output;
|v| {
output.send(v).unwrap();
}
})
"\]:::pushClass -12v1[/"
(12v1)
for_each({
use crate::__staged::*;
let output = output;
|v| {
output.send(v).unwrap();
}
})
"\]:::pushClass +4v1[/"
(4v1)
map({
use crate::__staged::*;
|v| (v - 1, ())
})
"\]:::pushClass +5v1[\"(5v1) join::<'tick, 'tick>()"/]:::pullClass +6v1[\"
(6v1)
map({
use crate::__staged::*;
|t| t.0
})
"/]:::pullClass +7v1[/"(7v1) tee()"\]:::pushClass +8v1[/"
(8v1)
for_each({
use crate::__staged::*;
let output = output;
|v| {
output.send(v).unwrap();
}
})
"\]:::pushClass +9v1[/"
(9v1)
for_each({
use crate::__staged::*;
let output = output;
|v| {
output.send(v).unwrap();
}
})
"\]:::pushClass +10v1["(10v1) handoff"]:::otherClass +11v1["(11v1) handoff"]:::otherClass 1v1-->2v1 2v1-->3v1 -6v3-->|1|7v1 -2v1-->5v1 -8v3-->|0|7v1 -3v1-->8v3 -5v1-->6v3 -9v1-->10v1 +2v1-->4v1 +3v1-->10v1 +4v1-->11v1 +5v1-->6v1 +6v1-->7v1 +7v1-->8v1 7v1-->9v1 -10v1-->11v1 -10v1-->12v1 +10v1-->|0|5v1 +11v1-->|1|5v1 subgraph sg_1v1 ["sg_1v1 stratum 0"] 1v1 2v1 3v1 - 5v1 + 4v1 subgraph sg_1v1_var_stream_0 ["var stream_0"] 1v1 - 2v1 end subgraph sg_1v1_var_stream_1 ["var stream_1"] - 3v1 + 2v1 end subgraph sg_1v1_var_stream_2 ["var stream_2"] - 5v1 + 3v1 + end + subgraph sg_1v1_var_stream_3 ["var stream_3"] + 4v1 end end subgraph sg_2v1 ["sg_2v1 stratum 0"] + 5v1 + 6v1 7v1 + 8v1 9v1 - 10v1 - 11v1 - 12v1 - subgraph sg_2v1_var_stream_3 ["var stream_3"] - 7v1 - end subgraph sg_2v1_var_stream_4 ["var stream_4"] - 9v1 - 10v1 + 5v1 + end + subgraph sg_2v1_var_stream_5 ["var stream_5"] + 6v1 + end + subgraph sg_2v1_var_stream_6 ["var stream_6"] + 7v1 end end diff --git a/stageleft/src/lib.rs b/stageleft/src/lib.rs index bd26653bbe82..de16687da02a 100644 --- a/stageleft/src/lib.rs +++ b/stageleft/src/lib.rs @@ -91,7 +91,7 @@ impl QuotedContext for () { } pub trait Quoted<'a, T>: FreeVariable { - fn splice(self) -> TokenStream + fn splice(self) -> syn::Expr where Self: Sized, { @@ -100,7 +100,7 @@ pub trait Quoted<'a, T>: FreeVariable { panic!("Quoted value should not have prelude"); } - value.unwrap() + syn::parse2(value.unwrap()).unwrap() } }