mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-19 19:08:05 +08:00
Improve resolved types
This commit is contained in:
@@ -7,6 +7,7 @@ pub struct Compiler {}
|
||||
impl Compiler {
|
||||
pub fn compile(&self, mut network: NodeNetwork) -> impl Iterator<Item = Result<ProtoNetwork, String>> {
|
||||
let node_ids = network.nodes.keys().copied().collect::<Vec<_>>();
|
||||
network.generate_node_paths(&[]);
|
||||
network.populate_dependants();
|
||||
for id in node_ids {
|
||||
network.flatten(id);
|
||||
@@ -19,6 +20,9 @@ impl Compiler {
|
||||
proto_networks.map(move |mut proto_network| {
|
||||
proto_network.resolve_inputs()?;
|
||||
proto_network.generate_stable_node_ids();
|
||||
// Deduplication of identical protonodes is more efficient, but also means the type information is lost for the corresponding document node
|
||||
// let mut seen = std::collections::HashSet::new();
|
||||
// proto_network.nodes.retain(|(protonode_id, _)| seen.insert(*protonode_id));
|
||||
Ok(proto_network)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -193,6 +193,11 @@ impl ProtoNode {
|
||||
|
||||
self.identifier.name.hash(&mut hasher);
|
||||
self.construction_args.hash(&mut hasher);
|
||||
// TODO: This is necessary since a mapping of path to type has to be stored for document node
|
||||
// If this is removed, the identical node would be removed and the mapping wouldn't be added
|
||||
// This can be improved by storing a list of paths for each proto node.
|
||||
self.original_location.path.hash(&mut hasher);
|
||||
|
||||
if self.skip_deduplication {
|
||||
self.original_location.path.hash(&mut hasher);
|
||||
}
|
||||
@@ -210,25 +215,6 @@ impl ProtoNode {
|
||||
Some(NodeId(hasher.finish()))
|
||||
}
|
||||
|
||||
/// Construct a new [`ProtoNode`] with the specified construction args and a `ClonedNode` implementation.
|
||||
pub fn value(value: ConstructionArgs, path: Vec<NodeId>) -> Self {
|
||||
let inputs_exposed = match &value {
|
||||
ConstructionArgs::Nodes(nodes) => nodes.len() + 1,
|
||||
_ => 2,
|
||||
};
|
||||
Self {
|
||||
identifier: ProtoNodeIdentifier::new("graphene_core::value::ClonedNode"),
|
||||
construction_args: value,
|
||||
input: ProtoNodeInput::ManualComposition(concrete!(Context)),
|
||||
original_location: OriginalLocation {
|
||||
path: Some(path),
|
||||
inputs_exposed: vec![false; inputs_exposed],
|
||||
..Default::default()
|
||||
},
|
||||
skip_deduplication: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts all references to other node IDs into new IDs by running the specified function on them.
|
||||
/// This can be used when changing the IDs of the nodes, for example in the case of generating stable IDs.
|
||||
pub fn map_ids(&mut self, f: impl Fn(NodeId) -> NodeId, skip_lambdas: bool) {
|
||||
@@ -319,29 +305,6 @@ impl ProtoNetwork {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Remove
|
||||
/// Create a hashmap with the list of nodes this proto network depends on/uses as inputs.
|
||||
pub fn collect_inwards_edges(&self) -> HashMap<NodeId, Vec<NodeId>> {
|
||||
let mut edges: HashMap<NodeId, Vec<NodeId>> = HashMap::new();
|
||||
for (id, node) in &self.nodes {
|
||||
match &node.input {
|
||||
ProtoNodeInput::Node(ref_id) | ProtoNodeInput::NodeLambda(ref_id) => {
|
||||
self.check_ref(ref_id, id);
|
||||
edges.entry(*id).or_default().push(*ref_id)
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
if let ConstructionArgs::Nodes(ref_nodes) = &node.construction_args {
|
||||
for (ref_id, _) in ref_nodes {
|
||||
self.check_ref(ref_id, id);
|
||||
edges.entry(*id).or_default().push(*ref_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
edges
|
||||
}
|
||||
|
||||
fn collect_inwards_edges_with_mapping(&self) -> (Vec<Vec<usize>>, FxHashMap<NodeId, usize>) {
|
||||
let id_map: FxHashMap<_, _> = self.nodes.iter().enumerate().map(|(idx, (id, _))| (*id, idx)).collect();
|
||||
|
||||
@@ -477,9 +440,22 @@ impl ProtoNetwork {
|
||||
fn is_topologically_sorted(&self) -> bool {
|
||||
let mut visited = HashSet::new();
|
||||
|
||||
let inwards_edges = self.collect_inwards_edges();
|
||||
for (id, _) in &self.nodes {
|
||||
for &dependency in inwards_edges.get(id).unwrap_or(&Vec::new()) {
|
||||
for (id, node) in &self.nodes {
|
||||
let mut upstream_nodes = Vec::new();
|
||||
match &node.input {
|
||||
ProtoNodeInput::Node(ref_id) | ProtoNodeInput::NodeLambda(ref_id) => {
|
||||
upstream_nodes.push(*ref_id);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
if let ConstructionArgs::Nodes(ref_nodes) = &node.construction_args {
|
||||
for (ref_id, _) in ref_nodes {
|
||||
upstream_nodes.push(*ref_id);
|
||||
}
|
||||
}
|
||||
|
||||
for dependency in upstream_nodes {
|
||||
if !visited.contains(&dependency) {
|
||||
dbg!(id, dependency);
|
||||
dbg!(&visited);
|
||||
|
||||
Reference in New Issue
Block a user