mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-10-06 06:18:12 +08:00
Remove vestigial async from the execution path
This commit is contained in:
@@ -268,7 +268,7 @@ impl NodeRuntime {
|
|||||||
.into();
|
.into();
|
||||||
if let Some(graph) = self.old_graph.clone() {
|
if let Some(graph) = self.old_graph.clone() {
|
||||||
// We ignore this result as compilation errors should have been reported in an earlier iteration
|
// We ignore this result as compilation errors should have been reported in an earlier iteration
|
||||||
let _ = self.update_network(graph).await;
|
let _ = self.update_network(graph);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GraphRuntimeRequest::GraphUpdate(GraphUpdate {
|
GraphRuntimeRequest::GraphUpdate(GraphUpdate {
|
||||||
@@ -283,7 +283,7 @@ impl NodeRuntime {
|
|||||||
self.resources = resources;
|
self.resources = resources;
|
||||||
|
|
||||||
self.node_graph_errors.clear();
|
self.node_graph_errors.clear();
|
||||||
let result = self.update_network(network).await;
|
let result = self.update_network(network);
|
||||||
let node_graph_errors = self.node_graph_errors.clone();
|
let node_graph_errors = self.node_graph_errors.clone();
|
||||||
|
|
||||||
self.update_thumbnails = true;
|
self.update_thumbnails = true;
|
||||||
@@ -298,7 +298,7 @@ impl NodeRuntime {
|
|||||||
render_config.export_format = ExportFormat::Svg;
|
render_config.export_format = ExportFormat::Svg;
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = self.execute_network(render_config).await;
|
let result = self.execute_network(render_config);
|
||||||
let mut responses = VecDeque::new();
|
let mut responses = VecDeque::new();
|
||||||
// TODO: Only process monitor nodes if the graph has changed, not when only the Footprint changes
|
// TODO: Only process monitor nodes if the graph has changed, not when only the Footprint changes
|
||||||
if !render_config.for_eyedropper {
|
if !render_config.for_eyedropper {
|
||||||
@@ -406,7 +406,7 @@ impl NodeRuntime {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn update_network(&mut self, graph: NodeNetwork) -> Result<ResolvedDocumentNodeTypesDelta, (ResolvedDocumentNodeTypesDelta, String)> {
|
fn update_network(&mut self, graph: NodeNetwork) -> Result<ResolvedDocumentNodeTypesDelta, (ResolvedDocumentNodeTypesDelta, String)> {
|
||||||
let mut scoped_network = wrap_network_in_scope(graph, self.editor_api.clone());
|
let mut scoped_network = wrap_network_in_scope(graph, self.editor_api.clone());
|
||||||
|
|
||||||
if let Err(e) = self.preprocessor.preprocess(&mut scoped_network, &|resource_id| self.resources.hash(&resource_id)) {
|
if let Err(e) = self.preprocessor.preprocess(&mut scoped_network, &|resource_id| self.resources.hash(&resource_id)) {
|
||||||
@@ -429,16 +429,16 @@ impl NodeRuntime {
|
|||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
assert_ne!(proto_network.nodes.len(), 0, "No proto nodes exist?");
|
assert_ne!(proto_network.nodes.len(), 0, "No proto nodes exist?");
|
||||||
self.executor.update(proto_network).await.map_err(|(types, e)| {
|
self.executor.update(proto_network).map_err(|(types, e)| {
|
||||||
self.node_graph_errors.clone_from(&e);
|
self.node_graph_errors.clone_from(&e);
|
||||||
(types, format!("{e:?}"))
|
(types, format!("{e:?}"))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn execute_network(&mut self, render_config: RenderConfig) -> Result<TaggedValue, String> {
|
fn execute_network(&mut self, render_config: RenderConfig) -> Result<TaggedValue, String> {
|
||||||
use graph_craft::graphene_compiler::Executor;
|
use graph_craft::graphene_compiler::Executor;
|
||||||
|
|
||||||
match (&self.executor).execute(render_config).await.map_err(|e| e.to_string())? {
|
match (&self.executor).execute(render_config).map_err(|e| e.to_string())? {
|
||||||
GPoll::Final(value) | GPoll::Partial(value) => Ok(value),
|
GPoll::Final(value) | GPoll::Partial(value) => Ok(value),
|
||||||
GPoll::Fallback(boxed) => {
|
GPoll::Fallback(boxed) => {
|
||||||
let (value, error) = *boxed;
|
let (value, error) = *boxed;
|
||||||
@@ -609,7 +609,7 @@ fn expand_to_thumbnail_aspect(bounds: [DVec2; 2]) -> [DVec2; 2] {
|
|||||||
[center - half, center + half]
|
[center - half, center + half]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn introspect_node(path: &[NodeId]) -> Result<Arc<dyn std::any::Any + Send + Sync + 'static>, IntrospectError> {
|
pub fn introspect_node(path: &[NodeId]) -> Result<Arc<dyn std::any::Any + Send + Sync + 'static>, IntrospectError> {
|
||||||
let runtime = NODE_RUNTIME.lock();
|
let runtime = NODE_RUNTIME.lock();
|
||||||
if let Some(ref mut runtime) = runtime.as_ref() {
|
if let Some(ref mut runtime) = runtime.as_ref() {
|
||||||
return runtime.executor.introspect(path);
|
return runtime.executor.introspect(path);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::document::NodeNetwork;
|
use crate::document::NodeNetwork;
|
||||||
use crate::proto::{LocalFuture, ProtoNetwork};
|
use crate::proto::ProtoNetwork;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
pub struct Compiler {}
|
pub struct Compiler {}
|
||||||
@@ -33,5 +33,5 @@ impl Compiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait Executor<I, O> {
|
pub trait Executor<I, O> {
|
||||||
fn execute(&self, input: I) -> LocalFuture<'_, Result<O, Box<dyn Error>>>;
|
fn execute(&self, input: I) -> Result<O, Box<dyn Error>>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use futures::executor::block_on;
|
||||||
use graph_craft::document::value::{RenderOutputType, TaggedValue, UVec2};
|
use graph_craft::document::value::{RenderOutputType, TaggedValue, UVec2};
|
||||||
use graph_craft::graphene_compiler::Executor;
|
use graph_craft::graphene_compiler::Executor;
|
||||||
use graphene_std::application_io::{ExportFormat, RenderConfig, TimingInformation};
|
use graphene_std::application_io::{ExportFormat, RenderConfig, TimingInformation};
|
||||||
@@ -14,10 +15,10 @@ use std::time::Duration;
|
|||||||
|
|
||||||
const SOURCE_COMPLETION_TIMEOUT: Duration = Duration::from_secs(30);
|
const SOURCE_COMPLETION_TIMEOUT: Duration = Duration::from_secs(30);
|
||||||
|
|
||||||
async fn execute_until_final(executor: &DynamicExecutor, render_config: RenderConfig, completion: &Receiver<()>) -> Result<TaggedValue, Box<dyn Error>> {
|
fn execute_until_final(executor: &DynamicExecutor, render_config: RenderConfig, completion: &Receiver<()>) -> Result<TaggedValue, Box<dyn Error>> {
|
||||||
loop {
|
loop {
|
||||||
while completion.try_recv().is_ok() {}
|
while completion.try_recv().is_ok() {}
|
||||||
match executor.execute(render_config.clone()).await? {
|
match executor.execute(render_config.clone())? {
|
||||||
GPoll::Final(value) => return Ok(value),
|
GPoll::Final(value) => return Ok(value),
|
||||||
GPoll::Fallback(boxed) => {
|
GPoll::Fallback(boxed) => {
|
||||||
let (value, error) = *boxed;
|
let (value, error) = *boxed;
|
||||||
@@ -52,7 +53,7 @@ pub fn detect_file_type(path: &Path) -> Result<FileType, String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn export_document(
|
pub fn export_document(
|
||||||
executor: &DynamicExecutor,
|
executor: &DynamicExecutor,
|
||||||
wgpu_executor: wgpu_executor::WgpuExecutorHandle,
|
wgpu_executor: wgpu_executor::WgpuExecutorHandle,
|
||||||
output_path: PathBuf,
|
output_path: PathBuf,
|
||||||
@@ -82,7 +83,7 @@ pub async fn export_document(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Execute the graph
|
// Execute the graph
|
||||||
let result = execute_until_final(executor, render_config, completion).await?;
|
let result = execute_until_final(executor, render_config, completion)?;
|
||||||
|
|
||||||
// Handle the result based on output type
|
// Handle the result based on output type
|
||||||
match result {
|
match result {
|
||||||
@@ -95,7 +96,7 @@ pub async fn export_document(
|
|||||||
RenderOutputType::Texture(texture) => {
|
RenderOutputType::Texture(texture) => {
|
||||||
// Convert GPU texture to CPU buffer
|
// Convert GPU texture to CPU buffer
|
||||||
let gpu_raster = Raster::<GPU>::new_gpu(texture);
|
let gpu_raster = Raster::<GPU>::new_gpu(texture);
|
||||||
let cpu_raster: Raster<CPU> = gpu_raster.convert(Footprint::BOUNDLESS, wgpu_executor.clone()).await;
|
let cpu_raster: Raster<CPU> = block_on(gpu_raster.convert(Footprint::BOUNDLESS, wgpu_executor.clone()));
|
||||||
let (data, width, height) = cpu_raster.to_flat_u8();
|
let (data, width, height) = cpu_raster.to_flat_u8();
|
||||||
|
|
||||||
// Encode and write raster image
|
// Encode and write raster image
|
||||||
@@ -174,7 +175,7 @@ impl AnimationParams {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Export an animated GIF by rendering multiple frames at different animation times
|
/// Export an animated GIF by rendering multiple frames at different animation times
|
||||||
pub async fn export_gif(
|
pub fn export_gif(
|
||||||
executor: &DynamicExecutor,
|
executor: &DynamicExecutor,
|
||||||
wgpu_executor: wgpu_executor::WgpuExecutorHandle,
|
wgpu_executor: wgpu_executor::WgpuExecutorHandle,
|
||||||
output_path: PathBuf,
|
output_path: PathBuf,
|
||||||
@@ -221,14 +222,14 @@ pub async fn export_gif(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Execute the graph for this frame
|
// Execute the graph for this frame
|
||||||
let result = execute_until_final(executor, render_config, completion).await?;
|
let result = execute_until_final(executor, render_config, completion)?;
|
||||||
|
|
||||||
// Extract RGBA data from result
|
// Extract RGBA data from result
|
||||||
let (data, img_width, img_height) = match result {
|
let (data, img_width, img_height) = match result {
|
||||||
TaggedValue::RenderOutput(output) => match output.data {
|
TaggedValue::RenderOutput(output) => match output.data {
|
||||||
RenderOutputType::Texture(texture) => {
|
RenderOutputType::Texture(texture) => {
|
||||||
let gpu_raster = Raster::<GPU>::new_gpu(texture);
|
let gpu_raster = Raster::<GPU>::new_gpu(texture);
|
||||||
let cpu_raster: Raster<CPU> = gpu_raster.convert(Footprint::BOUNDLESS, wgpu_executor.clone()).await;
|
let cpu_raster: Raster<CPU> = block_on(gpu_raster.convert(Footprint::BOUNDLESS, wgpu_executor.clone()));
|
||||||
cpu_raster.to_flat_u8()
|
cpu_raster.to_flat_u8()
|
||||||
}
|
}
|
||||||
RenderOutputType::Buffer { data, width, height } => (data, width, height),
|
RenderOutputType::Buffer { data, width, height } => (data, width, height),
|
||||||
|
|||||||
@@ -125,8 +125,7 @@ struct GlobalOpts {
|
|||||||
verbose: u8,
|
verbose: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
async fn main() -> Result<(), Box<dyn Error>> {
|
|
||||||
let app = App::parse();
|
let app = App::parse();
|
||||||
|
|
||||||
let log_level = app.global_opts.verbose;
|
let log_level = app.global_opts.verbose;
|
||||||
@@ -154,9 +153,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
let gdd = if is_gdd {
|
let gdd = if is_gdd {
|
||||||
let archive = std::fs::read(document_path).map_err(|error| format!("Failed to read document {}: {error}", document_path.display()))?;
|
let archive = std::fs::read(document_path).map_err(|error| format!("Failed to read document {}: {error}", document_path.display()))?;
|
||||||
let container = AnyContainer::Memory(MemoryBackend::new());
|
let container = AnyContainer::Memory(MemoryBackend::new());
|
||||||
let gdd = document_format::Gdd::open_from_archive(archive.as_ref(), container, GddV1Layout)
|
let gdd = block_on(document_format::Gdd::open_from_archive(archive.as_ref(), container, GddV1Layout)).map_err(|error| format!("Failed to open document: {error}"))?;
|
||||||
.await
|
|
||||||
.map_err(|error| format!("Failed to open document: {error}"))?;
|
|
||||||
Some(gdd)
|
Some(gdd)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@@ -164,7 +161,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
|
|
||||||
if let Command::ExtractLegacyDoc { ref document } = app.command {
|
if let Command::ExtractLegacyDoc { ref document } = app.command {
|
||||||
let Some(gdd) = &gdd else { return Err("ExtractLegacyDoc requires a .gdd document".into()) };
|
let Some(gdd) = &gdd else { return Err("ExtractLegacyDoc requires a .gdd document".into()) };
|
||||||
let Some(legacy_doc) = gdd.read_legacy_document().await else {
|
let Some(legacy_doc) = block_on(gdd.read_legacy_document()) else {
|
||||||
return Err("gdd file did not contain a legacy .graphite document".into());
|
return Err("gdd file did not contain a legacy .graphite document".into());
|
||||||
};
|
};
|
||||||
let mut new_path = document.clone();
|
let mut new_path = document.clone();
|
||||||
@@ -177,7 +174,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
// Build the runtime network: from the `.gdd` registry, or by loading a legacy `.graphite` document.
|
// Build the runtime network: from the `.gdd` registry, or by loading a legacy `.graphite` document.
|
||||||
let node_network = match &gdd {
|
let node_network = match &gdd {
|
||||||
Some(gdd) => {
|
Some(gdd) => {
|
||||||
let declarations = gdd.declarations(gdd).await;
|
let declarations = block_on(gdd.declarations(gdd));
|
||||||
let (node_network, _metadata) = gdd.registry().to_runtime_with_metadata(&declarations)?;
|
let (node_network, _metadata) = gdd.registry().to_runtime_with_metadata(&declarations)?;
|
||||||
node_network
|
node_network
|
||||||
}
|
}
|
||||||
@@ -188,7 +185,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
log::info!("Creating GPU context");
|
log::info!("Creating GPU context");
|
||||||
let mut application_io = PlatformApplicationIo::new().await;
|
let mut application_io = block_on(PlatformApplicationIo::new());
|
||||||
if let Some(gdd) = &gdd {
|
if let Some(gdd) = &gdd {
|
||||||
application_io.inject_resource_proxy(Box::new(gdd.resource_proxy()));
|
application_io.inject_resource_proxy(Box::new(gdd.resource_proxy()));
|
||||||
}
|
}
|
||||||
@@ -257,9 +254,9 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
// Perform export based on file type
|
// Perform export based on file type
|
||||||
if file_type == export::FileType::Gif {
|
if file_type == export::FileType::Gif {
|
||||||
let animation = export::AnimationParams::new(fps, frames, duration);
|
let animation = export::AnimationParams::new(fps, frames, duration);
|
||||||
export::export_gif(&executor, wgpu_executor_ref.clone(), output, scale, (width, height), animation, &completion_receiver).await?;
|
export::export_gif(&executor, wgpu_executor_ref.clone(), output, scale, (width, height), animation, &completion_receiver)?;
|
||||||
} else {
|
} else {
|
||||||
export::export_document(&executor, wgpu_executor_ref.clone(), output, file_type, scale, (width, height), transparent, &completion_receiver).await?;
|
export::export_document(&executor, wgpu_executor_ref.clone(), output, file_type, scale, (width, height), transparent, &completion_receiver)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => unreachable!("All other commands should be handled before this match statement is run"),
|
_ => unreachable!("All other commands should be handled before this match statement is run"),
|
||||||
@@ -316,7 +313,7 @@ fn compile_graph(network: NodeNetwork, editor_api: Arc<PlatformEditorApi>, gdd:
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn create_executor(proto_network: ProtoNetwork, runtime: Arc<DynGraphRuntime>) -> Result<DynamicExecutor, Box<dyn Error>> {
|
fn create_executor(proto_network: ProtoNetwork, runtime: Arc<DynGraphRuntime>) -> Result<DynamicExecutor, Box<dyn Error>> {
|
||||||
let mut executor = block_on(DynamicExecutor::new(proto_network)).map_err(|errors| errors.iter().map(|e| format!("{e:?}")).reduce(|acc, e| format!("{acc}\n{e}")).unwrap_or_default())?;
|
let mut executor = DynamicExecutor::new(proto_network).map_err(|errors| errors.iter().map(|e| format!("{e:?}")).reduce(|acc, e| format!("{acc}\n{e}")).unwrap_or_default())?;
|
||||||
executor.set_runtime(runtime);
|
executor.set_runtime(runtime);
|
||||||
Ok(executor)
|
Ok(executor)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use graph_craft::Type;
|
|||||||
use graph_craft::document::NodeId;
|
use graph_craft::document::NodeId;
|
||||||
use graph_craft::document::value::TaggedValue;
|
use graph_craft::document::value::TaggedValue;
|
||||||
use graph_craft::graphene_compiler::Executor;
|
use graph_craft::graphene_compiler::Executor;
|
||||||
use graph_craft::proto::{ConstructionArgs, GraphError, LocalFuture, ProtoNetwork, ProtoNode, TypingContext};
|
use graph_craft::proto::{ConstructionArgs, GraphError, ProtoNetwork, ProtoNode, TypingContext};
|
||||||
use graph_craft::proto::{GraphErrorType, GraphErrors};
|
use graph_craft::proto::{GraphErrorType, GraphErrors};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
@@ -65,12 +65,12 @@ pub struct ResolvedDocumentNodeTypesDelta {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DynamicExecutor {
|
impl DynamicExecutor {
|
||||||
pub async fn new(proto_network: ProtoNetwork) -> Result<Self, GraphErrors> {
|
pub fn new(proto_network: ProtoNetwork) -> Result<Self, GraphErrors> {
|
||||||
let mut typing_context = TypingContext::new(&node_registry::NODE_REGISTRY);
|
let mut typing_context = TypingContext::new(&node_registry::NODE_REGISTRY);
|
||||||
typing_context.update(&proto_network)?;
|
typing_context.update(&proto_network)?;
|
||||||
let output = proto_network.output;
|
let output = proto_network.output;
|
||||||
let sources = proto_network.source_ids();
|
let sources = proto_network.source_ids();
|
||||||
let tree = BorrowTree::new(proto_network, &typing_context).await?;
|
let tree = BorrowTree::new(proto_network, &typing_context)?;
|
||||||
let runtime = noop_runtime();
|
let runtime = noop_runtime();
|
||||||
runtime.retain_sources(&sources);
|
runtime.retain_sources(&sources);
|
||||||
|
|
||||||
@@ -96,7 +96,7 @@ impl DynamicExecutor {
|
|||||||
|
|
||||||
/// Updates the existing [`BorrowTree`] to reflect the new [`ProtoNetwork`], reusing nodes where possible.
|
/// Updates the existing [`BorrowTree`] to reflect the new [`ProtoNetwork`], reusing nodes where possible.
|
||||||
#[cfg_attr(debug_assertions, inline(never))]
|
#[cfg_attr(debug_assertions, inline(never))]
|
||||||
pub async fn update(&mut self, proto_network: ProtoNetwork) -> Result<ResolvedDocumentNodeTypesDelta, (ResolvedDocumentNodeTypesDelta, GraphErrors)> {
|
pub fn update(&mut self, proto_network: ProtoNetwork) -> Result<ResolvedDocumentNodeTypesDelta, (ResolvedDocumentNodeTypesDelta, GraphErrors)> {
|
||||||
self.output = proto_network.output;
|
self.output = proto_network.output;
|
||||||
self.typing_context.update(&proto_network).map_err(|e| {
|
self.typing_context.update(&proto_network).map_err(|e| {
|
||||||
// If there is an error then get types that have been resolved before the error
|
// If there is an error then get types that have been resolved before the error
|
||||||
@@ -120,11 +120,7 @@ impl DynamicExecutor {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
let sources = proto_network.source_ids();
|
let sources = proto_network.source_ids();
|
||||||
let (add, orphaned) = self
|
let (add, orphaned) = self.tree.update(proto_network, &self.typing_context).map_err(|e| (ResolvedDocumentNodeTypesDelta::default(), e))?;
|
||||||
.tree
|
|
||||||
.update(proto_network, &self.typing_context)
|
|
||||||
.await
|
|
||||||
.map_err(|e| (ResolvedDocumentNodeTypesDelta::default(), e))?;
|
|
||||||
self.runtime.retain_sources(&sources);
|
self.runtime.retain_sources(&sources);
|
||||||
self.live_sources = sources;
|
self.live_sources = sources;
|
||||||
let old_to_remove = core::mem::replace(&mut self.orphaned_nodes, orphaned);
|
let old_to_remove = core::mem::replace(&mut self.orphaned_nodes, orphaned);
|
||||||
@@ -174,27 +170,25 @@ impl<I> Executor<I, GPoll<TaggedValue>> for &DynamicExecutor
|
|||||||
where
|
where
|
||||||
I: VarArg + Send + Sync + std::panic::RefUnwindSafe,
|
I: VarArg + Send + Sync + std::panic::RefUnwindSafe,
|
||||||
{
|
{
|
||||||
fn execute(&self, input: I) -> LocalFuture<'_, Result<GPoll<TaggedValue>, Box<dyn Error>>> {
|
fn execute(&self, input: I) -> Result<GPoll<TaggedValue>, Box<dyn Error>> {
|
||||||
Box::pin(async move {
|
let Some(handle) = self.tree.get(self.output) else {
|
||||||
let Some(handle) = self.tree.get(self.output) else {
|
return Err("Output node not found in executor".into());
|
||||||
return Err("Output node not found in executor".into());
|
};
|
||||||
};
|
let mut arena = self.arena.lock().unwrap_or_else(PoisonError::into_inner);
|
||||||
let mut arena = self.arena.lock().unwrap_or_else(PoisonError::into_inner);
|
let result = eval_root(&mut arena, &self.runtime, &input, |ctx| match TaggedValue::from_edge(handle.duplicate(), ctx) {
|
||||||
let result = eval_root(&mut arena, &self.runtime, &input, |ctx| match TaggedValue::from_edge(handle.duplicate(), ctx) {
|
Ok(poll) => poll.map(Ok),
|
||||||
Ok(poll) => poll.map(Ok),
|
Err(error) => GPoll::Final(Err(error)),
|
||||||
Err(error) => GPoll::Final(Err(error)),
|
});
|
||||||
});
|
match result {
|
||||||
match result {
|
GPoll::Final(value) => Ok(GPoll::Final(value?)),
|
||||||
GPoll::Final(value) => Ok(GPoll::Final(value?)),
|
GPoll::Partial(value) => Ok(GPoll::Partial(value?)),
|
||||||
GPoll::Partial(value) => Ok(GPoll::Partial(value?)),
|
GPoll::Fallback(boxed) => {
|
||||||
GPoll::Fallback(boxed) => {
|
let (value, error) = *boxed;
|
||||||
let (value, error) = *boxed;
|
Ok(GPoll::Fallback(Box::new((value?, error))))
|
||||||
Ok(GPoll::Fallback(Box::new((value?, error))))
|
|
||||||
}
|
|
||||||
GPoll::Pending => Ok(GPoll::Pending),
|
|
||||||
GPoll::Error(error) => Ok(GPoll::Error(error)),
|
|
||||||
}
|
}
|
||||||
})
|
GPoll::Pending => Ok(GPoll::Pending),
|
||||||
|
GPoll::Error(error) => Ok(GPoll::Error(error)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn eval_root<S, T>(arena: &mut Arena, runtime: &GraphRuntime<S>, call_argument: DynSlot, eval: impl FnOnce(&ContextImpl) -> GPoll<T>) -> GPoll<T> {
|
pub fn eval_root<S, T>(arena: &mut Arena, runtime: &GraphRuntime<S>, call_argument: DynSlot, eval: impl FnOnce(&ContextImpl) -> GPoll<T>) -> GPoll<T> {
|
||||||
@@ -264,23 +258,23 @@ pub struct BorrowTree {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BorrowTree {
|
impl BorrowTree {
|
||||||
pub async fn new(proto_network: ProtoNetwork, typing_context: &TypingContext) -> Result<BorrowTree, GraphErrors> {
|
pub fn new(proto_network: ProtoNetwork, typing_context: &TypingContext) -> Result<BorrowTree, GraphErrors> {
|
||||||
let mut nodes = BorrowTree::default();
|
let mut nodes = BorrowTree::default();
|
||||||
for (id, node) in proto_network.nodes {
|
for (id, node) in proto_network.nodes {
|
||||||
nodes.push_node(id, node, typing_context).await?
|
nodes.push_node(id, node, typing_context)?
|
||||||
}
|
}
|
||||||
Ok(nodes)
|
Ok(nodes)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pushes new nodes into the tree and return orphaned nodes
|
/// Pushes new nodes into the tree and return orphaned nodes
|
||||||
pub async fn update(&mut self, proto_network: ProtoNetwork, typing_context: &TypingContext) -> Result<(Vec<Path>, HashSet<NodeId>), GraphErrors> {
|
pub fn update(&mut self, proto_network: ProtoNetwork, typing_context: &TypingContext) -> Result<(Vec<Path>, HashSet<NodeId>), GraphErrors> {
|
||||||
let mut old_nodes: HashSet<_> = self.nodes.keys().copied().collect();
|
let mut old_nodes: HashSet<_> = self.nodes.keys().copied().collect();
|
||||||
let mut new_nodes: Vec<_> = Vec::new();
|
let mut new_nodes: Vec<_> = Vec::new();
|
||||||
// TODO: Problem: When a passthrough node is connected directly to an export the first input to the passthrough node is not added to the proto network, while the second input is. This means the primary input does not have a type.
|
// TODO: Problem: When a passthrough node is connected directly to an export the first input to the passthrough node is not added to the proto network, while the second input is. This means the primary input does not have a type.
|
||||||
for (id, node) in proto_network.nodes {
|
for (id, node) in proto_network.nodes {
|
||||||
if !self.nodes.contains_key(&id) {
|
if !self.nodes.contains_key(&id) {
|
||||||
new_nodes.push(node.original_location.path.clone().unwrap_or_default().into());
|
new_nodes.push(node.original_location.path.clone().unwrap_or_default().into());
|
||||||
self.push_node(id, node, typing_context).await?;
|
self.push_node(id, node, typing_context)?;
|
||||||
} else if self.update_source_map(id, typing_context, &node) {
|
} else if self.update_source_map(id, typing_context, &node) {
|
||||||
new_nodes.push(node.original_location.path.clone().unwrap_or_default().into());
|
new_nodes.push(node.original_location.path.clone().unwrap_or_default().into());
|
||||||
}
|
}
|
||||||
@@ -342,10 +336,10 @@ impl BorrowTree {
|
|||||||
/// use interpreted_executor::node_registry;
|
/// use interpreted_executor::node_registry;
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
/// async fn example() -> Result<(), GraphErrors> {
|
/// fn example() -> Result<(), GraphErrors> {
|
||||||
/// let (proto_network, node_id, proto_node) = ProtoNetwork::example();
|
/// let (proto_network, node_id, proto_node) = ProtoNetwork::example();
|
||||||
/// let typing_context = TypingContext::default();
|
/// let typing_context = TypingContext::default();
|
||||||
/// let mut borrow_tree = BorrowTree::new(proto_network, &typing_context).await?;
|
/// let mut borrow_tree = BorrowTree::new(proto_network, &typing_context)?;
|
||||||
///
|
///
|
||||||
/// // Assert that the node exists in the BorrowTree
|
/// // Assert that the node exists in the BorrowTree
|
||||||
/// assert!(borrow_tree.get(node_id).is_some(), "Node should exist before removal");
|
/// assert!(borrow_tree.get(node_id).is_some(), "Node should exist before removal");
|
||||||
@@ -442,7 +436,7 @@ impl BorrowTree {
|
|||||||
/// - `Nodes`: Constructs a node using other nodes as dependencies.
|
/// - `Nodes`: Constructs a node using other nodes as dependencies.
|
||||||
/// - Uses the constructor function from the `typing_context` for `Nodes` construction arguments.
|
/// - Uses the constructor function from the `typing_context` for `Nodes` construction arguments.
|
||||||
/// - Returns an error if no constructor is found for the given node ID.
|
/// - Returns an error if no constructor is found for the given node ID.
|
||||||
async fn push_node(&mut self, id: NodeId, proto_node: ProtoNode, typing_context: &TypingContext) -> Result<(), GraphErrors> {
|
fn push_node(&mut self, id: NodeId, proto_node: ProtoNode, typing_context: &TypingContext) -> Result<(), GraphErrors> {
|
||||||
self.update_source_map(id, typing_context, &proto_node);
|
self.update_source_map(id, typing_context, &proto_node);
|
||||||
let path = proto_node.original_location.path.clone().unwrap_or_default();
|
let path = proto_node.original_location.path.clone().unwrap_or_default();
|
||||||
|
|
||||||
@@ -534,8 +528,7 @@ mod test {
|
|||||||
let mut tree = BorrowTree::default();
|
let mut tree = BorrowTree::default();
|
||||||
let val_1_protonode = ProtoNode::value(ConstructionArgs::Value(TaggedValue::U32(2u32).into()), vec![]);
|
let val_1_protonode = ProtoNode::value(ConstructionArgs::Value(TaggedValue::U32(2u32).into()), vec![]);
|
||||||
let context = TypingContext::default();
|
let context = TypingContext::default();
|
||||||
let future = tree.push_node(NodeId(0), val_1_protonode, &context);
|
tree.push_node(NodeId(0), val_1_protonode, &context).unwrap();
|
||||||
futures::executor::block_on(future).unwrap();
|
|
||||||
let _node = tree.get(NodeId(0)).unwrap();
|
let _node = tree.get(NodeId(0)).unwrap();
|
||||||
|
|
||||||
let arena = Arena::new(64);
|
let arena = Arena::new(64);
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ pub mod util;
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use core_types::*;
|
use core_types::*;
|
||||||
use futures::executor::block_on;
|
|
||||||
use graphene_core::ops::passthrough;
|
use graphene_core::ops::passthrough;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -47,6 +46,6 @@ mod tests {
|
|||||||
let compiler = Compiler {};
|
let compiler = Compiler {};
|
||||||
let protograph = compiler.compile_single(network).expect("Graph should be generated");
|
let protograph = compiler.compile_single(network).expect("Graph should be generated");
|
||||||
|
|
||||||
let _exec = block_on(DynamicExecutor::new(protograph)).map(|_e| panic!("The network should not type check ")).unwrap_err();
|
let _exec = DynamicExecutor::new(protograph).map(|_e| panic!("The network should not type check ")).unwrap_err();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user