Skip to content
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

Open
wants to merge 176 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
176 commits
Select commit Hold shift + click to select a range
c7a9d89
Just const_fold2 + inside that partial_value (taken from hugr_core)
acl-cqc Aug 6, 2024
ac45e53
merge/update+fmt (ValueName for ConstInt non-compiling as ConstInt no…
acl-cqc Sep 11, 2024
8adaa6e
Missing imports / lints. Now running, but failing w/StackOverflow
acl-cqc Aug 6, 2024
098c735
Fix tests...
acl-cqc Aug 6, 2024
706c892
ValueKey using MaybeHash
acl-cqc Aug 6, 2024
63bc944
tag() does not refer to self.is_compound
acl-cqc Aug 6, 2024
5fa7edb
ValueHandle::{is_compound,num_fields,index} => {variant_values, as_sum}
acl-cqc Aug 6, 2024
98bf94a
Rm ValueHandle::tag, use variant_values - inefficient, presume this i…
acl-cqc Aug 6, 2024
295ec32
add variant_values, rewrite one use of outputs_for_variant
acl-cqc Aug 6, 2024
5c8289e
...and the other two; remove outputs_for_variant
acl-cqc Aug 6, 2024
bf173ab
Rewrite tuple rule to avoid indexing
acl-cqc Aug 6, 2024
0ae4d19
GC unused (tuple,variant)_field_value, iter_with_ports
acl-cqc Aug 6, 2024
8608ba9
Common up via ValueRow.unpack_first
acl-cqc Aug 6, 2024
2dca3e9
No DeRef for ValueHandle, just add get_type()
acl-cqc Aug 6, 2024
51e68ea
ValueKey::{Select->Field,index->field}
acl-cqc Aug 6, 2024
8635474
(join/meet)_mut_unsafe => try_(join/meet)_mut with Err for conflictin…
acl-cqc Aug 7, 2024
80d5b86
Remove ValueHandle::variant_values - just have as_sum
acl-cqc Aug 8, 2024
1c8be99
Optimize as_sum() by returning impl Iterator not Vec
acl-cqc Aug 8, 2024
b0afa54
Machine uses PV not PartialValue
acl-cqc Aug 27, 2024
d09a1fe
Parametrize PartialValue+PV+Machine by AbstractValue/Into<Value>, Con…
acl-cqc Aug 28, 2024
af8827b
Move partial_value.rs inside datalog/
acl-cqc Aug 28, 2024
4b61436
Hide PartialSum/PartialValue
acl-cqc Aug 28, 2024
8b31d8c
refactor: ValueRow::single_among_bottoms
acl-cqc Aug 28, 2024
6a72961
Factor out propagate_leaf_op; add ValueRow::from_iter
acl-cqc Aug 28, 2024
780af9b
Add handling for Tag
acl-cqc Aug 28, 2024
cabcf04
Remove PV (use typedef in datalog.rs)
acl-cqc Aug 28, 2024
5e4a04f
Allow DFContext to interpret any leaf op (except MakeTuple/etc.); pub…
acl-cqc Aug 28, 2024
1453886
Also fold extension ops
acl-cqc Aug 28, 2024
221e96c
Comment as_sum
acl-cqc Aug 30, 2024
cd4e15c
Rename DataflowContext to HugrValueContext
acl-cqc Aug 30, 2024
c5ab2a9
Move {datalog=>value_handle}/context.rs - an impl, datalog uses only …
acl-cqc Aug 30, 2024
6c80acf
Comment re. propagate_leaf_op
acl-cqc Aug 30, 2024
636f14d
Hide PartialValue by abstracting DFContext::InterpretableVal: FromSum…
acl-cqc Aug 30, 2024
0acdcc5
Use Value::sum, adding FromSum::Err; fmt
acl-cqc Aug 30, 2024
1012e0a
Cargo.toml: use explicit git= tag for ascent
acl-cqc Sep 2, 2024
6bd8dba
Fix rebase: TryHash, UnpackTuple/MakeTuple now in prelude
acl-cqc Sep 2, 2024
f7d288f
pub ValueRow+Partial(Value/Sum); add TotalContext
acl-cqc Sep 2, 2024
a62eb0f
Remove DFContext::hugr(), as_ref() does just as well
acl-cqc Sep 2, 2024
f0ec237
Move partial_value out of datalog, combine tests; move ValueRow out o…
acl-cqc Sep 2, 2024
82a3f22
Move FromSum and try_into_value into total_context.rs
acl-cqc Sep 2, 2024
e6dc114
Separate mod dataflow from mod const_fold2
acl-cqc Sep 2, 2024
03ff165
fmt
acl-cqc Sep 2, 2024
25ed1fb
TailLoopTermination just examine whatever PartialValue's we have, rem…
acl-cqc Sep 2, 2024
09911df
Drop non-(Bounded)Lattice impls of (join/meet)(_mut),top,bottom
acl-cqc Sep 2, 2024
248fb07
doc fixes, remove missing-docs for partial_value...how does it still …
acl-cqc Sep 2, 2024
e2ad079
fix all warnings (inc Machine::new() -> impl Default)
acl-cqc Sep 2, 2024
95e2dd9
distribute utils.rs -> machine.rs
acl-cqc Sep 2, 2024
7f1e122
Move dataflow{/datalog=>}/test.rs
acl-cqc Sep 2, 2024
faff556
and more warnings
acl-cqc Sep 2, 2024
401354d
fix extension tests
acl-cqc Sep 2, 2024
c468387
Fix doclink, fix DefaultHasher pre-1.76
acl-cqc Sep 2, 2024
88db5b1
comment conditional test
acl-cqc Sep 11, 2024
738b61b
Clarify (TODO untested) branches of join_mut
acl-cqc Sep 11, 2024
8f9c1ed
Exploit invariant PartialValue::Value is not a sum (even single known…
acl-cqc Sep 11, 2024
a71ba97
Exploit invariant more, RIP join_mut_value_handle
acl-cqc Sep 11, 2024
05280a8
By similar logic, RIP meet_mut_value_handle; assert_(in)variants now …
acl-cqc Sep 11, 2024
96b0856
Rename TestSum(,Leaf)Type::assert_{invariants=>valid}
acl-cqc Sep 13, 2024
f21e278
Rename assert_(=>in)variants (i.e. to match); call in (join/meet)_mut…
acl-cqc Sep 13, 2024
ce53b1c
test unpacking constant tuple
acl-cqc Sep 13, 2024
13f29a9
try_into_value returns new enum ValueOrSum; TryFrom<ValueOrSum> repla…
acl-cqc Sep 12, 2024
9f1a5cd
Hide ValueRow (and move into datalog.rs)
acl-cqc Oct 2, 2024
15e642e
Remove PartialSum::unit()
acl-cqc Oct 2, 2024
514af13
PartialValue is private struct containing PVEnum (with ::Sum not ::Pa…
acl-cqc Oct 2, 2024
5d86f46
variant => new_variant, unit => new_unit
acl-cqc Oct 2, 2024
d8c8140
Simplify PartialOrd for PartialSum, keys(1,2) support cmp
acl-cqc Oct 2, 2024
1315685
PartialSum::variant_values does not take `len` (PartialValue:: still …
acl-cqc Oct 2, 2024
2aaaeb9
clippy
acl-cqc Oct 2, 2024
5619761
Machine::tail_loop_terminates + case_reachable return Option not panic
acl-cqc Oct 2, 2024
f3c175c
Machine::read_out_wire_value fails with ConstTypeError if there was one
acl-cqc Oct 2, 2024
aad2ef0
PartialValue::try_(join|meet)_mut are pub, don't mutate upon failure
acl-cqc Oct 2, 2024
0a8cc12
Remove some commented-out code
acl-cqc Oct 2, 2024
bfcd0a6
Expose PartialSum
acl-cqc Oct 2, 2024
248fb23
dataflow has docs! (enforced)
acl-cqc Oct 2, 2024
5b8654e
clippy
acl-cqc Oct 2, 2024
c40e718
Move PartialValue::join into impl Lattice for
acl-cqc Oct 7, 2024
8732a63
Machine::read_out_wire_value => PartialValue::try_into_wire_value
acl-cqc Oct 7, 2024
346187d
read_out_wire_partial_value => read_out_wire
acl-cqc Oct 7, 2024
a139f9e
Remove ValueOrSum (and add Sum) via complex parametrization of try_in…
acl-cqc Oct 7, 2024
7f2a91a
Datalog works on any AbstractValue; impl'd by PartialValue for a Base…
acl-cqc Oct 7, 2024
1680829
PartialValue proptests: rm TestSumLeafType, replace ValueHandle with …
acl-cqc Oct 8, 2024
2a57a15
tests: Rename type_check -> check_value
acl-cqc Oct 8, 2024
fcfcb6b
tidies
acl-cqc Oct 8, 2024
dcaa928
Add a couple more proptests, and a TEMPORARY FIX for a BUG pending be…
acl-cqc Oct 8, 2024
bcacbcc
Remove redundant test
acl-cqc Oct 8, 2024
5192ed8
Refactor TailLoopTermination::from_control_value
acl-cqc Oct 8, 2024
e21bbd7
pub TailLoopTermination, rename members, doc
acl-cqc Oct 8, 2024
22e0192
Test tidies (and some ALAN wtf? comments)
acl-cqc Oct 8, 2024
cae5e4f
Use Tag
acl-cqc Oct 8, 2024
3014827
Add TestContext (no interpret_leaf_op), propolutate, avoid HugrValueC…
acl-cqc Oct 8, 2024
64b9bb7
Avoid propolutate by interpreting LoadConstant (only)
acl-cqc Oct 8, 2024
8bc5e12
Revert "Avoid propolutate by interpreting LoadConstant (only)"
acl-cqc Oct 8, 2024
a3a6213
tiny const_fold2 doc tweaks
acl-cqc Oct 8, 2024
a96ab20
(TEMP) remove const_fold2 module
acl-cqc Oct 8, 2024
3051183
Merge remote-tracking branch 'origin/main' into acl/const_fold2
acl-cqc Oct 8, 2024
777694c
(TEMP) Rm total_context
acl-cqc Oct 8, 2024
5a16e6b
clippy
acl-cqc Oct 8, 2024
4f31178
Better fix for PartialSum::try_meet_mut
acl-cqc Oct 9, 2024
2b523c9
true_or_false uses pv_true+pv_false
acl-cqc Oct 9, 2024
1d2cb9b
Update to ascent 0.7.0, drop fn join/meet as these are now trait-default
acl-cqc Oct 9, 2024
ee91bbe
Cargo.toml: oops, remove obsolete comment
acl-cqc Oct 9, 2024
e67051f
ValueRow cleanups (remove misleading 'pub's)
acl-cqc Oct 9, 2024
94cee55
Refactor: rm tail_node, clone earlier in ValueRow::unpack_first, rm V…
acl-cqc Oct 9, 2024
5cf5ff0
Add datalog for CFG
acl-cqc Oct 9, 2024
7381087
refactor: follow unpack_first with enumerate
acl-cqc Oct 9, 2024
60e33db
Remove comments from test_tail_loop_(iterates_twice->two_iters)
acl-cqc Oct 9, 2024
ef4f433
Add a test of tail loop around conditional
acl-cqc Oct 9, 2024
5935489
improve that test - loop input is a sum and the variants have differe…
acl-cqc Oct 9, 2024
b198681
clippy/nth
acl-cqc Oct 10, 2024
ed30f80
revert accidental changes to hugr-core/src/types.rs (how?!)
acl-cqc Oct 10, 2024
3f7808a
Cleanup conditional, cfg, unpack_first
acl-cqc Oct 10, 2024
436b635
Complex CFG that does a not-XOR...but analysis generally says "true o…
acl-cqc Oct 9, 2024
0374d13
Propagate case results to conditional output only if case reached; so…
acl-cqc Oct 10, 2024
6a2dd9e
More test cases
acl-cqc Oct 10, 2024
a75fee9
refactor as fixture
acl-cqc Oct 10, 2024
151e571
clippy
acl-cqc Oct 10, 2024
e15b04d
Revert "Datalog works on any AbstractValue; impl'd by PartialValue fo…
acl-cqc Oct 14, 2024
dc08f0d
(Re-)remove PVEnum
acl-cqc Oct 14, 2024
436dcd2
Remove as_sum. AbstractValues are elements not sums
acl-cqc Oct 14, 2024
e817bbe
clippy
acl-cqc Oct 14, 2024
b06cfad
Refactor: remove 'fn input_count'
acl-cqc Oct 14, 2024
fd717be
Try to fix interpret_leaf_op: cannot use Bottom for output! But ascen…
acl-cqc Oct 14, 2024
9b17439
interpret_leaf_op for ExtensionOps only; LoadConstant via value_from_…
acl-cqc Oct 14, 2024
846d1ee
Correct comment BaseValue -> AbstractValue
acl-cqc Oct 15, 2024
328e7f8
test Hugr now returns (XOR, AND) of two inputs, one case wrongly prod…
acl-cqc Oct 15, 2024
da3c05c
BB reachability, fixes!
acl-cqc Oct 10, 2024
6930ad4
Test cases with true_or_false/top, standardize naming (->test_)condit…
acl-cqc Oct 15, 2024
0a3e281
Try to common up by using case_reachable in conditional outputs - 6 t…
acl-cqc Oct 11, 2024
b1e0bfd
Make case_reachable a relation (dropping bool), not lattice - fixes t…
acl-cqc Oct 11, 2024
355e814
Call (+test)
acl-cqc Oct 15, 2024
22f3ce8
propolutate_out_wires => prepopulate and set in wires in run
acl-cqc Oct 15, 2024
68b1d48
Rm/inline value_inputs/value_outputs, use UnpackTuple, comments
acl-cqc Oct 15, 2024
77a5fa3
Merge remote-tracking branch 'origin/main' into acl/const_fold2
acl-cqc Oct 15, 2024
2cc62f0
clippy
acl-cqc Oct 15, 2024
8254771
docs
acl-cqc Oct 15, 2024
7e81b15
Separate AnalysisResults from Machine, use context.exactly_one() not …
acl-cqc Oct 21, 2024
34e82ed
Move try_into_wire_value => AnalysisResults.try_read_wire_value
acl-cqc Oct 21, 2024
015707f
doc fixes and fix comment
acl-cqc Oct 21, 2024
ff39f7d
Try to make clippy happy
acl-cqc Oct 21, 2024
ada7ee1
Use ascent_run to drop context from all the relations. Lots cleanup t…
acl-cqc Oct 22, 2024
7c02d41
DFContext does not Deref, pass Hugr separately
acl-cqc Oct 22, 2024
3d4f016
Massively reduce scope of clippy-allow to inside run_datalog
acl-cqc Oct 22, 2024
8bab4d5
Move ValueRow into own file
acl-cqc Oct 22, 2024
3eccadf
Move Machine into datalog.rs, pub(super) fields in AnalysisResults, r…
acl-cqc Oct 22, 2024
0f4fa52
Move machine.rs to results.rs
acl-cqc Oct 22, 2024
caa8aca
Remove enum IO, replace io_node -> input_child/output_child
acl-cqc Oct 22, 2024
e7f61fc
move docs
acl-cqc Oct 22, 2024
811802c
Remove/inline/dedup dfb_block
acl-cqc Oct 22, 2024
3713ea7
relation doc
acl-cqc Oct 22, 2024
d317809
datalog docs (each relation), move _cfg_succ_dest
acl-cqc Oct 22, 2024
69c3270
comment, use exactly_one
acl-cqc Oct 22, 2024
dc56686
Allow to handle LoadFunction
acl-cqc Oct 23, 2024
33a8592
doc
acl-cqc Oct 23, 2024
b153ada
Separate out ConstLoader
acl-cqc Oct 23, 2024
5052ac0
value_from_(custom_const=>opaque), taking &OpaqueValue
acl-cqc Oct 23, 2024
ad0c6f2
Recombine DFContext with Hugr i.e. reinstate Deref constraint
acl-cqc Oct 28, 2024
16a18f4
Replace Deref with HugrView, trivially obtainable by implementing AsRef
acl-cqc Oct 28, 2024
a0f2b2c
ValueRow Debug; ops default to PartialValue::Top less aggressively
acl-cqc Oct 28, 2024
87eb700
And back to Deref, should allow using a region view not the whole Hugr
acl-cqc Oct 29, 2024
a49221b
fix doclink
acl-cqc Oct 30, 2024
71ea55d
PartialSum::try_into_value also uses Option<...> as error-type
acl-cqc Oct 30, 2024
ea9db2e
Proper errors from try_into_value, Option<Extr...> from try_read_wire…
acl-cqc Oct 30, 2024
df31523
fmt
acl-cqc Oct 30, 2024
a490874
Add test running on region
acl-cqc Oct 30, 2024
3af39aa
fix: provide PartialValue::Top for unspecified Hugr inputs
acl-cqc Oct 30, 2024
dc15999
try_into_value allows TryFrom by giving ExtractValueError *2* errorty…
acl-cqc Oct 30, 2024
2d81264
improve docs
acl-cqc Oct 30, 2024
b61d252
Parametrize Machine::try_read_wire_value the same way
acl-cqc Oct 30, 2024
8cac194
tweaks
acl-cqc Oct 30, 2024
fb3816e
Massively simplify xor_and_cfg, no need for conditionals
acl-cqc Nov 4, 2024
19571f6
Use tru/fals constants
acl-cqc Nov 4, 2024
69d0f5e
try_into_value: reorder type params, separate out where clause
acl-cqc Nov 8, 2024
cb60b5b
Merge remote-tracking branch 'origin/main' into HEAD
acl-cqc Nov 8, 2024
2624ee8
We don't actually use portgraph, nor downcast-rs
acl-cqc Nov 8, 2024
ec526e8
Import RandomState from std::collections::hash_map for rust 1.75
acl-cqc Nov 8, 2024
5650ee4
Use BREAK_TAG/CONTINUE_TAG
acl-cqc Nov 8, 2024
da2981c
No, use make_break/make_continue for easy cases
acl-cqc Nov 8, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions hugr-passes/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ categories = ["compilers"]

[dependencies]
hugr-core = { path = "../hugr-core", version = "0.13.3" }
ascent = { version = "0.7.0" }
itertools = { workspace = true }
lazy_static = { workspace = true }
paste = { workspace = true }
Expand All @@ -25,3 +26,6 @@ extension_inference = ["hugr-core/extension_inference"]

[dev-dependencies]
rstest = { workspace = true }
proptest = { workspace = true }
proptest-derive = { workspace = true }
proptest-recurse = { version = "0.5.0" }
110 changes: 110 additions & 0 deletions hugr-passes/src/dataflow.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#![warn(missing_docs)]
//! Dataflow analysis of Hugrs.

mod datalog;
pub use datalog::Machine;
mod value_row;

mod results;
pub use results::{AnalysisResults, TailLoopTermination};

mod partial_value;
pub use partial_value::{AbstractValue, PartialSum, PartialValue, Sum};

use hugr_core::ops::constant::OpaqueValue;
use hugr_core::ops::{ExtensionOp, Value};
use hugr_core::types::TypeArg;
use hugr_core::{Hugr, HugrView, Node};

/// Clients of the dataflow framework (particular analyses, such as constant folding)
/// must implement this trait (including providing an appropriate domain type `V`).
pub trait DFContext<V>: ConstLoader<V> + std::ops::Deref<Target = Self::View> {
/// Type of view contained within this context. (Ideally we'd constrain
/// by `std::ops::Deref<Target: impl HugrView>` but that's not stable yet.)
type View: HugrView;

/// Given lattice values for each input, update lattice values for the (dataflow) outputs.
/// For extension ops only, excluding [MakeTuple] and [UnpackTuple].
/// `_outs` is an array with one element per dataflow output, each initialized to [PartialValue::Top]
/// which is the correct value to leave if nothing can be deduced about that output.
/// (The default does nothing, i.e. leaves `Top` for all outputs.)
///
/// [MakeTuple]: hugr_core::extension::prelude::MakeTuple
/// [UnpackTuple]: hugr_core::extension::prelude::UnpackTuple
fn interpret_leaf_op(
&self,
_node: Node,
_e: &ExtensionOp,
_ins: &[PartialValue<V>],
_outs: &mut [PartialValue<V>],
) {
Copy link
Contributor

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(...) { }

Copy link
Contributor Author

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

}
}

/// Trait for loading [PartialValue]s from constant [Value]s in a Hugr.
/// Implementors will likely want to override some/all of [Self::value_from_opaque],
/// [Self::value_from_const_hugr], and [Self::value_from_function]: the defaults
/// are "correct" but maximally conservative (minimally informative).
pub trait ConstLoader<V> {
/// Produces a [PartialValue] from a constant. The default impl (expected
/// to be appropriate in most cases) traverses [Sum](Value::Sum) constants
/// to their leaves ([Value::Extension] and [Value::Function]),
/// converts these using [Self::value_from_opaque] and [Self::value_from_const_hugr],
/// and builds nested [PartialValue::new_variant] to represent the structure.
fn value_from_const(&self, n: Node, cst: &Value) -> PartialValue<V> {
Copy link
Contributor Author

@acl-cqc acl-cqc Oct 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatives include
a. moving value_from_const out of the trait and fixing it; I don't have a concrete reason why anyone would need to override it but it seems "reasonable" that one might; or
b. moving value_from_opaque, value_from_const_hugr and value_from_function into a separate trait (say ConstLeafLoader), and then implementing ConstLoader for any type providing those two - this would be the more proper way of doing what I've done here but feels a bit overkill TBH.

traverse_value(self, n, &mut Vec::new(), cst)
}

/// Produces an abstract value from an [OpaqueValue], if possible.
/// The default just returns `None`, which will be interpreted as [PartialValue::Top].
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't these functions just return Top directly?

fn value_from_opaque(&self, _node: Node, _fields: &[usize], _val: &OpaqueValue) -> Option<V> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fields args in these methods need some documentation. I'm not sure what they represent

None
}

/// Produces an abstract value from a Hugr in a [Value::Function], if possible.
/// The default just returns `None`, which will be interpreted as [PartialValue::Top].
fn value_from_const_hugr(&self, _node: Node, _fields: &[usize], _h: &Hugr) -> Option<V> {
None
}

/// Produces an abstract value from a [FuncDefn] or [FuncDecl] node
/// (that has been loaded via a [LoadFunction]), if possible.
/// The default just returns `None`, which will be interpreted as [PartialValue::Top].
///
/// [FuncDefn]: hugr_core::ops::FuncDefn
/// [FuncDecl]: hugr_core::ops::FuncDecl
/// [LoadFunction]: hugr_core::ops::LoadFunction
fn value_from_function(&self, _node: Node, _type_args: &[TypeArg]) -> Option<V> {
None
}
}

fn traverse_value<V>(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why isn't this a method on ConstLoader?

s: &(impl ConstLoader<V> + ?Sized),
n: Node,
fields: &mut Vec<usize>,
cst: &Value,
) -> PartialValue<V> {
match cst {
Value::Sum(hugr_core::ops::constant::Sum { tag, values, .. }) => {
let elems = values.iter().enumerate().map(|(idx, elem)| {
fields.push(idx);
let r = traverse_value(s, n, fields, elem);
fields.pop();
r
});
PartialValue::new_variant(*tag, elems)
}
Value::Extension { e } => s
.value_from_opaque(n, fields, e)
.map(PartialValue::from)
.unwrap_or(PartialValue::Top),
Value::Function { hugr } => s
.value_from_const_hugr(n, fields, hugr)
.map(PartialValue::from)
.unwrap_or(PartialValue::Top),
}
}

#[cfg(test)]
mod test;
Loading
Loading