-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Dataflow analysis framework #1476
base: main
Are you sure you want to change the base?
Conversation
1594e6f
to
e1c49d7
Compare
718f058
to
6698b1b
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1476 +/- ##
==========================================
+ Coverage 85.79% 85.87% +0.07%
==========================================
Files 136 142 +6
Lines 25180 26287 +1107
Branches 22092 23199 +1107
==========================================
+ Hits 21603 22573 +970
- Misses 2427 2532 +105
- Partials 1150 1182 +32
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
e54c742
to
6cac41a
Compare
* DFContext reinstate fn hugr(), drop AsRef requirement (fixes StackOverflow) * test_tail_loop_iterates_twice: use tail_loop_builder_exts, fix from #1332(?) * Fix only-one-DataflowContext asserts using Arc::ptr_eq
…text interprets load_constant
I had to recombine DFContext with the Hugr to get round some Rust mutable/immutable reference ownership issues in #1603; I tried
but the extra |
/// If this PartialSum had multiple possible tags; or if `typ` was not a [TypeEnum::Sum] | ||
/// supporting the single possible tag with the correct number of elements and no row variables; | ||
/// or if converting a child element failed via [PartialValue::try_into_value]. | ||
pub fn try_into_value<VE, SE, V2: TryFrom<V, Error = VE> + TryFrom<Sum<V2>, Error = SE>>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this is highly parametric. The first case will be the "easy" one, where V2
is hugr_core::ops::Value
, in which case VE = Infallible
and SE = ConstTypeError
. But I think it's important to keep this open for other analysis domains.
It might be more legible if written <V2, VE, SE> ..... where V2: TryFrom<V, Error=VE> + TryFrom<Sum<V2>, Error=SE>>
, happy to do that if anyone shouts.
The bigger issue may be nomenclature - this relates to ExtractValueError
so perhaps should be (try_
)extract_value
? And also to Machine::try_read_wire_value
- so, try_extract_wire_value
?? However I quite like the word "concrete" so could perhaps use that naming to tie the three together - "try_into_concrete", "try_read_wire_concrete", and, erm, "ConcretizationError" (hmmm, not so good....). Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be more legible if written
<V2, VE, SE> ..... where V2: TryFrom<V, Error=VE> + TryFrom<Sum<V2>, Error=SE>>
, happy to do that if anyone shouts.
I think you should!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done - yes good to standardize the order of the args with try_read_wire_value
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any thoughts on naming?
|
||
impl<V: AbstractValue> Machine<V> { | ||
/// Provide initial values for some wires. | ||
// Likely for test purposes only - should we make non-pub or #[cfg(test)] ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure quite what to do here. @doug-q may have opinions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We think this potentially useful (albeit not very powerful, as any prepopulated value will be join
ed with anything computed). A version that "breaks" the wire (replacing any value computed, without join
) would be more effective, also dangerous....
.push((root, IncomingPort::from(i), PartialValue::Top)); | ||
} | ||
} | ||
// Note/TODO, if analysis is running on a subregion then we should do similar |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll raise an issue for this. It's not clear how to identify nonlocal edges into a subregion, or to differentiate between nonlocal edges whose source we can't see, and ports with no edge at all, where perhaps "Bottom" is appropriate (it really can't happen, that bit of Hugr can't run....).
00ff09b
to
8cac194
Compare
_e: &ExtensionOp, | ||
_ins: &[PartialValue<V>], | ||
_outs: &mut [PartialValue<V>], | ||
) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need to provide default implementations for trait methods, you can just write fn f(...);
instead of fn f(...) { }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But this impl is totally ok as a default - it means, I know nothing about any leaf op
Note we could separate the DFContext from HugrView - which would be significantly neater - if we did #1636 first, but we need that because |
Forwards analysis only ATM, parametrized over the abstract domain hence intended to support not only constant folding but (in the future) devirtualization, intergraph-edge-insertion, etc. See #1603 for an "example" use for constant-folding, where it does better than the existing code.
Much complexity is to do with "native" (irrespective of the underlying domain) treatment of Sum types necessary for proper understanding of control flow (e.g. conditionals, loops, CFGs).
Note: we'll be able to separate the DFContext from the HugrView, which'll be neater, if we do #1636 first.
BREAK_TAG
/CONTINUE_TAG
from feat: Add TailLoop::BREAK_TAG and CONTINUE_TAG #1626Intended as a development of #1157, with significant changes:
Constant-folding and ValueHandle now stripped out, these will follow in a second PR
Everything is now in hugr-passes
Underlying domain of values abstracted over a trait AbstractValue (ValueHandle will implement this), which represents non-Sum values
datalog uses PartialValue wrapped around the AbstractValue to represent (Partial)Sums and make into a BoundedLattice
The old
PV
is gone (PartialValue
directly implements BoundedLattice)Interpretation of leaf (extension) ops is handled by the DFContext trait (although MakeTuple, and Untuple are handled by the framework - really prelude
MakeTuple
is just coreTag
andUntuple
is a single-Case Conditional with passthrough wires....); the framework handles routing of sums through these ops and all containers, also loading constants (with the DFContext handling non-Sum leafValue
s).Various refactoring of handling values (inc. in datalog) -
variant_values
+as_sum
+ more use of rows rather than indexing (this got rid of a bunch of unwraps and so on), significant refactoring of join/meet (and no_unsafe
).I've managed to refactor tests not to use ValueHandle etc. - they are only dealing with sum/loop/conditional routing after all.
dataflow/test.rs
uses about the simplest possibleTestContext
which provides zero information after any leaf-op - so we only get the framework-provided handling of Tag/MakeTuple/etc.propolutate_out_wires
largely superceded by passing root-node inputs intoMachine::run
, but still available for tests.