Skip to content

Commit d0bf7c3

Browse files
committed
refactor(dfir_lang): remove stratum, add push codegen, test fold, fold_keyed, fold_no_replay
all push ops PR: #2965
1 parent 048eb69 commit d0bf7c3

45 files changed

Lines changed: 312 additions & 388 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

dfir_lang/src/graph/ops/fold.rs

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use quote::quote_spanned;
22

33
use super::{
4-
DelayType, OperatorCategory, OperatorConstraints, OperatorWriteOutput, Persistence, RANGE_0,
4+
OperatorCategory, OperatorConstraints, OperatorWriteOutput, Persistence, RANGE_0,
55
RANGE_1, WriteContextArgs,
66
};
77

@@ -46,7 +46,7 @@ pub const FOLD: OperatorConstraints = OperatorConstraints {
4646
flo_type: None,
4747
ports_inn: None,
4848
ports_out: None,
49-
input_delaytype_fn: |_| Some(DelayType::Stratum),
49+
input_delaytype_fn: |_| None,
5050
write_fn: |wc @ &WriteContextArgs {
5151
root,
5252
op_span,
@@ -126,15 +126,44 @@ pub const FOLD: OperatorConstraints = OperatorConstraints {
126126
)
127127
);
128128
}
129-
} else {
130-
assert_eq!(0, outputs.len());
129+
} else if outputs.is_empty() {
130+
// Terminal push: fold is a singleton reference target with no downstream.
131131
quote_spanned! {op_span=>
132132
let #ident = #root::dfir_pipes::push::for_each(|#item_ident| {
133133
#assign_accum_ident
134134

135135
#foreach_body
136136
});
137137
}
138+
} else {
139+
let output = &outputs[0];
140+
quote_spanned! {op_span=>
141+
let #ident = {
142+
#[inline(always)]
143+
fn __push_fold<'a, Acc, Item, CombFn, Next>(
144+
acc_ref: &'a mut Acc,
145+
comb_fn: CombFn,
146+
next: Next,
147+
) -> #root::dfir_pipes::push::Accumulate<
148+
#root::dfir_pipes::push::FoldState<&'a mut Acc, CombFn, Acc, Item>,
149+
Next,
150+
>
151+
where
152+
CombFn: ::std::ops::FnMut(&mut Acc, Item),
153+
Next: #root::dfir_pipes::push::Push<&'a mut Acc, ()>,
154+
{
155+
#root::dfir_pipes::push::fold(acc_ref, comb_fn, next)
156+
}
157+
__push_fold(
158+
&mut #singleton_output_ident,
159+
|#accumulator_ident: &mut _, #item_ident| { #foreach_body },
160+
#root::dfir_pipes::push::map(
161+
|__val: &mut _| ::std::clone::Clone::clone(&*__val),
162+
#output,
163+
),
164+
)
165+
};
166+
}
138167
};
139168

140169
Ok(OperatorWriteOutput {

dfir_lang/src/graph/ops/fold_keyed.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use quote::{ToTokens, quote_spanned};
22

33
use super::{
4-
DelayType, OpInstGenerics, OperatorCategory, OperatorConstraints, OperatorInstance,
4+
OpInstGenerics, OperatorCategory, OperatorConstraints, OperatorInstance,
55
OperatorWriteOutput, Persistence, RANGE_1, WriteContextArgs,
66
};
77

@@ -79,15 +79,15 @@ pub const FOLD_KEYED: OperatorConstraints = OperatorConstraints {
7979
flo_type: None,
8080
ports_inn: None,
8181
ports_out: None,
82-
input_delaytype_fn: |_| Some(DelayType::Stratum),
82+
input_delaytype_fn: |_| None,
8383
write_fn: |wc @ &WriteContextArgs {
8484
op_span,
8585
work_fn_async,
8686
ident,
8787
inputs,
88+
outputs,
8889
is_pull,
8990
root,
90-
op_name,
9191
op_inst:
9292
OperatorInstance {
9393
generics:
@@ -102,8 +102,6 @@ pub const FOLD_KEYED: OperatorConstraints = OperatorConstraints {
102102
..
103103
},
104104
_| {
105-
assert!(is_pull, "TODO(mingwei): `{}` only supports pull.", op_name);
106-
107105
let persistence = match persistence_args[..] {
108106
[] => Persistence::Tick,
109107
[a] => a,
@@ -143,7 +141,21 @@ pub const FOLD_KEYED: OperatorConstraints = OperatorConstraints {
143141
let mut #hashtable_ident = &mut #singleton_output_ident;
144142
};
145143

146-
let write_iterator = if Persistence::Mutable == persistence {
144+
let write_iterator = if !is_pull {
145+
assert!(
146+
Persistence::Mutable != persistence,
147+
"fold_keyed::<'mutable> on push side is not supported ('mutable is being removed)"
148+
);
149+
let output = &outputs[0];
150+
quote_spanned! {op_span=>
151+
let #ident = #root::dfir_pipes::push::FoldKeyed::new(
152+
&mut #singleton_output_ident,
153+
#initfn,
154+
#aggfn,
155+
#output,
156+
);
157+
}
158+
} else if Persistence::Mutable == persistence {
147159
quote_spanned! {op_span=>
148160
#assign_hashtable_ident
149161

dfir_lang/src/graph/ops/fold_no_replay.rs

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use quote::quote_spanned;
22

33
use super::{
4-
DelayType, OperatorCategory, OperatorConstraints, OperatorWriteOutput, Persistence, RANGE_0,
4+
OperatorCategory, OperatorConstraints, OperatorWriteOutput, Persistence, RANGE_0,
55
RANGE_1, WriteContextArgs,
66
};
77

@@ -28,7 +28,7 @@ pub const FOLD_NO_REPLAY: OperatorConstraints = OperatorConstraints {
2828
flo_type: None,
2929
ports_inn: None,
3030
ports_out: None,
31-
input_delaytype_fn: |_| Some(DelayType::Stratum),
31+
input_delaytype_fn: |_| None,
3232
write_fn: |wc @ &WriteContextArgs {
3333
root,
3434
context,
@@ -117,15 +117,56 @@ pub const FOLD_NO_REPLAY: OperatorConstraints = OperatorConstraints {
117117
)
118118
};
119119
}
120-
} else {
121-
assert_eq!(0, outputs.len());
120+
} else if outputs.is_empty() {
121+
// Terminal push: fold_no_replay is a singleton reference target with no downstream.
122122
quote_spanned! {op_span=>
123123
let #ident = #root::dfir_pipes::push::for_each(|#item_ident| {
124124
#assign_accum_ident
125125

126126
#foreach_body
127127
});
128128
}
129+
} else {
130+
let output = &outputs[0];
131+
let was_updated_ident = wc.make_ident("was_updated");
132+
quote_spanned! {op_span=>
133+
let #was_updated_ident = ::std::cell::Cell::new(false);
134+
let #ident = {
135+
#[inline(always)]
136+
fn __push_fold<'a, Acc, Item, CombFn, Next>(
137+
acc_ref: &'a mut Acc,
138+
comb_fn: CombFn,
139+
next: Next,
140+
) -> #root::dfir_pipes::push::Accumulate<
141+
#root::dfir_pipes::push::FoldState<&'a mut Acc, CombFn, Acc, Item>,
142+
Next,
143+
>
144+
where
145+
CombFn: ::std::ops::FnMut(&mut Acc, Item),
146+
Next: #root::dfir_pipes::push::Push<&'a mut Acc, ()>,
147+
{
148+
#root::dfir_pipes::push::fold(acc_ref, comb_fn, next)
149+
}
150+
__push_fold(
151+
&mut #singleton_output_ident,
152+
|#accumulator_ident: &mut _, #item_ident| {
153+
#was_updated_ident.set(true);
154+
#foreach_body
155+
},
156+
#root::dfir_pipes::push::filter(
157+
{
158+
let __was_updated = &#was_updated_ident;
159+
let __context: &_ = #context;
160+
move |_| __was_updated.get() || __context.current_tick().0 == 0
161+
},
162+
#root::dfir_pipes::push::map(
163+
|__val: &mut _| ::std::clone::Clone::clone(&*__val),
164+
#output,
165+
),
166+
),
167+
)
168+
};
169+
}
129170
};
130171

131172
Ok(OperatorWriteOutput {

dfir_rs/tests/compile-fail/stable/surface_fold_keyed_generics_bad.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0271]: type mismatch resolving `<Iter<Drain<'_, '_, &str>> as Pull>::Item == (_, _)`
1+
error[E0271]: type mismatch resolving `<impl Pull<Item = &str, Meta = (), CanPend = <Iter<&mut impl Iterator<Item = &str>> as Pull>::CanPend, CanEnd = <Iter<&mut impl Iterator<Item = &str>> as Pull>::CanEnd> as Pull>::Item == (_, _)`
22
--> tests/compile-fail/stable/surface_fold_keyed_generics_bad.rs:3:9
33
|
44
3 | source_iter(["hello", "world"])
@@ -14,7 +14,7 @@ note: required by a bound in `check_input`
1414
4 | -> fold_keyed::<'tick, &str, usize>(String::new, |old: &mut _, val| {
1515
| ^^^^^^^^^^ required by this bound in `check_input`
1616

17-
error[E0271]: type mismatch resolving `<Iter<Drain<'_, '_, &str>> as Pull>::Item == (_, _)`
17+
error[E0271]: type mismatch resolving `<impl Pull<Item = &str, Meta = (), CanPend = <Iter<&mut impl Iterator<Item = &str>> as Pull>::CanPend, CanEnd = <Iter<&mut impl Iterator<Item = &str>> as Pull>::CanEnd> as Pull>::Item == (_, _)`
1818
--> tests/compile-fail/stable/surface_fold_keyed_generics_bad.rs:4:16
1919
|
2020
4 | -> fold_keyed::<'tick, &str, usize>(String::new, |old: &mut _, val| {

dfir_rs/tests/compile-fail/stable/surface_reduce_keyed_badtype_int.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0271]: type mismatch resolving `<Iter<Drain<'_, '_, {integer}>> as Pull>::Item == (_, _)`
1+
error[E0271]: type mismatch resolving `<impl Pull<Item = {integer}, Meta = (), CanPend = <Iter<&mut impl Iterator<Item = {integer}>> as Pull>::CanPend, CanEnd = <Iter<&mut impl Iterator<Item = {integer}>> as Pull>::CanEnd> as Pull>::Item == (_, _)`
22
--> tests/compile-fail/stable/surface_reduce_keyed_badtype_int.rs:3:9
33
|
44
3 | source_iter(0..1)
@@ -14,7 +14,7 @@ note: required by a bound in `check_input`
1414
4 | -> fold_keyed(|| 0, |old: &mut u32, val: u32| { *old += val; })
1515
| ^^^^^^^^^^ required by this bound in `check_input`
1616

17-
error[E0271]: type mismatch resolving `<Iter<Drain<'_, '_, {integer}>> as Pull>::Item == (_, _)`
17+
error[E0271]: type mismatch resolving `<impl Pull<Item = {integer}, Meta = (), CanPend = <Iter<&mut impl Iterator<Item = {integer}>> as Pull>::CanPend, CanEnd = <Iter<&mut impl Iterator<Item = {integer}>> as Pull>::CanEnd> as Pull>::Item == (_, _)`
1818
--> tests/compile-fail/stable/surface_reduce_keyed_badtype_int.rs:4:16
1919
|
2020
4 | -> fold_keyed(|| 0, |old: &mut u32, val: u32| { *old += val; })

dfir_rs/tests/compile-fail/stable/surface_reduce_keyed_badtype_option.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0271]: type mismatch resolving `<Iter<Drain<'_, '_, Option<{integer}>>> as Pull>::Item == (_, _)`
1+
error[E0271]: type mismatch resolving `<impl Pull<Item = Option<{integer}>, Meta = (), CanPend = <Iter<&mut impl Iterator<Item = Option<{integer}>>> as Pull>::CanPend, CanEnd = <Iter<&mut impl Iterator<Item = Option<{integer}>>> as Pull>::CanEnd> as Pull>::Item == (_, _)`
22
--> tests/compile-fail/stable/surface_reduce_keyed_badtype_option.rs:3:9
33
|
44
3 | source_iter([ Some(5), None, Some(12) ])
@@ -14,7 +14,7 @@ note: required by a bound in `check_input`
1414
4 | -> fold_keyed(|| 0, |old: &mut u32, val: u32| { *old += val; })
1515
| ^^^^^^^^^^ required by this bound in `check_input`
1616

17-
error[E0271]: type mismatch resolving `<Iter<Drain<'_, '_, Option<{integer}>>> as Pull>::Item == (_, _)`
17+
error[E0271]: type mismatch resolving `<impl Pull<Item = Option<{integer}>, Meta = (), CanPend = <Iter<&mut impl Iterator<Item = Option<{integer}>>> as Pull>::CanPend, CanEnd = <Iter<&mut impl Iterator<Item = Option<{integer}>>> as Pull>::CanEnd> as Pull>::Item == (_, _)`
1818
--> tests/compile-fail/stable/surface_reduce_keyed_badtype_option.rs:4:16
1919
|
2020
4 | -> fold_keyed(|| 0, |old: &mut u32, val: u32| { *old += val; })

dfir_rs/tests/metrics.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ async fn test_handoff_metrics() {
8383
let mut flow = dfir_rs::dfir_syntax! {
8484
source_iter(0..5)
8585
-> map(|x| x * 2)
86-
-> fold(|| 0, |acc: &mut _, x| { *acc += x; })
86+
-> defer_tick()
8787
-> for_each(|x| { output_send.send(x).unwrap(); });
8888
};
8989

@@ -99,7 +99,7 @@ async fn test_handoff_metrics() {
9999

100100
// Verify output
101101
let output: Vec<_> = collect_ready_async(&mut output_recv).await;
102-
assert_eq!(output, vec![20]);
102+
assert_eq!(output, vec![0, 2, 4, 6, 8]);
103103
}
104104

105105
#[multiplatform_test(dfir)]

dfir_rs/tests/snapshots/surface_cross_singleton__union_defer_tick@graphvis_dot.snap

Lines changed: 17 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
---
22
source: dfir_rs/tests/surface_cross_singleton.rs
3-
assertion_line: 58
43
expression: df.meta_graph().unwrap().to_dot(cfg)
54
---
65
digraph {
@@ -16,7 +15,7 @@ digraph {
1615
n8v1 [label="(n8v1) cross_singleton()", shape=invhouse, fillcolor="#88aaff"]
1716
n9v1 [label="(n9v1) tee()", shape=house, fillcolor="#ffff88"]
1817
n10v1 [label="(n10v1) for_each(|x| egress_tx.send(x).unwrap())", shape=house, fillcolor="#ffff88"]
19-
n11v1 [label="(n11v1) fold(|| 0, |_, _| {})", shape=invhouse, fillcolor="#88aaff"]
18+
n11v1 [label="(n11v1) fold(|| 0, |_, _| {})", shape=house, fillcolor="#ffff88"]
2019
n12v1 [label="(n12v1) cross_singleton()", shape=invhouse, fillcolor="#88aaff"]
2120
n13v1 [label="(n13v1) fold(|| 0, |_, _| {})", shape=invhouse, fillcolor="#88aaff"]
2221
n14v1 [label="(n14v1) flat_map(|_| [])", shape=invhouse, fillcolor="#88aaff"]
@@ -26,8 +25,6 @@ digraph {
2625
n18v1 [label="(n18v1) handoff", shape=parallelogram, fillcolor="#ddddff"]
2726
n19v1 [label="(n19v1) handoff", shape=parallelogram, fillcolor="#ddddff"]
2827
n20v1 [label="(n20v1) handoff", shape=parallelogram, fillcolor="#ddddff"]
29-
n21v1 [label="(n21v1) handoff", shape=parallelogram, fillcolor="#ddddff"]
30-
n22v1 [label="(n22v1) handoff", shape=parallelogram, fillcolor="#ddddff"]
3128
n2v1 -> n3v1
3229
n1v1 -> n15v1
3330
n3v1 -> n16v1
@@ -38,19 +35,17 @@ digraph {
3835
n7v1 -> n18v1
3936
n8v1 -> n9v1
4037
n9v1 -> n10v1
41-
n9v1 -> n19v1
42-
n3v1 -> n20v1
43-
n11v1 -> n21v1
38+
n9v1 -> n11v1
39+
n3v1 -> n19v1
40+
n11v1 -> n20v1
4441
n13v1 -> n14v1
45-
n12v1 -> n22v1
42+
n12v1 -> n13v1
4643
n15v1 -> n2v1 [color=red]
4744
n16v1 -> n8v1 [label="input"]
4845
n17v1 -> n4v1 [color=red]
4946
n18v1 -> n8v1 [label="single", color=red]
50-
n19v1 -> n11v1 [color=red]
51-
n20v1 -> n12v1 [label="input"]
52-
n21v1 -> n12v1 [label="single", color=red]
53-
n22v1 -> n13v1 [color=red]
47+
n19v1 -> n12v1 [label="input"]
48+
n20v1 -> n12v1 [label="single", color=red]
5449
subgraph sg_1v1 {
5550
cluster=true
5651
fillcolor="#dddddd"
@@ -98,6 +93,11 @@ digraph {
9893
style=filled
9994
label = "sg_4v1"
10095
n10v1
96+
subgraph sg_4v1_var_folded_thing {
97+
cluster=true
98+
label="var folded_thing"
99+
n11v1
100+
}
101101
subgraph sg_4v1_var_join {
102102
cluster=true
103103
label="var join"
@@ -110,33 +110,16 @@ digraph {
110110
fillcolor="#dddddd"
111111
style=filled
112112
label = "sg_5v1"
113-
subgraph sg_5v1_var_folded_thing {
113+
subgraph sg_5v1_var_deferred_stream {
114114
cluster=true
115-
label="var folded_thing"
116-
n11v1
115+
label="var deferred_stream"
116+
n13v1
117+
n14v1
117118
}
118-
}
119-
subgraph sg_6v1 {
120-
cluster=true
121-
fillcolor="#dddddd"
122-
style=filled
123-
label = "sg_6v1"
124-
subgraph sg_6v1_var_joined_folded {
119+
subgraph sg_5v1_var_joined_folded {
125120
cluster=true
126121
label="var joined_folded"
127122
n12v1
128123
}
129124
}
130-
subgraph sg_7v1 {
131-
cluster=true
132-
fillcolor="#dddddd"
133-
style=filled
134-
label = "sg_7v1"
135-
subgraph sg_7v1_var_deferred_stream {
136-
cluster=true
137-
label="var deferred_stream"
138-
n13v1
139-
n14v1
140-
}
141-
}
142125
}

0 commit comments

Comments
 (0)