From ca8cf0cc520c793f7c8e826bb20aa3dda8dc65fa Mon Sep 17 00:00:00 2001 From: MultisampledNight Date: Thu, 18 Jan 2024 21:54:41 +0100 Subject: [PATCH] chore: put semi human graph ir into its own module --- crates/ir/src/lib.rs | 84 +++---------------------------------- crates/ir/src/semi_human.rs | 82 ++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 79 deletions(-) create mode 100644 crates/ir/src/semi_human.rs diff --git a/crates/ir/src/lib.rs b/crates/ir/src/lib.rs index d2160af..034e6d2 100644 --- a/crates/ir/src/lib.rs +++ b/crates/ir/src/lib.rs @@ -4,6 +4,10 @@ use serde::{Deserialize, Serialize}; pub mod instruction; +// feel free to make this public if there's sufficient reason to do so +// otherwise, go use the GraphIr in the module this is written in directly instead!! +mod semi_human; + pub type Map = ahash::AHashMap; pub type Set = ahash::AHashSet; @@ -18,7 +22,7 @@ pub type Set = ahash::AHashSet; /// /// Returns an error if the parsed source is not a valid human-readable graph IR. pub fn from_ron(source: &str) -> ron::error::SpannedResult { - let human_repr: SemiHumanGraphIr = ron::from_str(source)?; + let human_repr: semi_human::GraphIr = ron::from_str(source)?; Ok(human_repr.into()) } @@ -115,81 +119,3 @@ pub mod id { pub struct Span { range: RangeInclusive, } - -// TODO: this desperately belongs into its own file, also id should get its own file -/// Semi-human-{read,writ}able [`GraphIr`] with far less useful types. -/// -/// **Do not use this if you want to programatically construct IR.** -/// Instead, directly use [`GraphIr`]. -#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] -pub struct SemiHumanGraphIr { - /// See [`GraphIr::instructions`], just that a simple number is used for the ID instead - /// of a proper span. - instructions: Map, - /// See [`GraphIr::edges`]. RON wants you to type the set as a list. - edges: Map>, -} - -#[derive(Clone, Debug, PartialEq, Eq, Hash, Deserialize, Serialize)] -pub struct SemiHumanSocket { - /// ID of the instruction this socket is on. - on: usize, - idx: u16, -} - -impl From for id::Socket { - fn from(source: SemiHumanSocket) -> Self { - Self { - belongs_to: (id::Instruction(Span { - range: source.on..=source.on, - })), - idx: id::SocketIdx(source.idx), - } - } -} - -impl From for GraphIr { - fn from(source: SemiHumanGraphIr) -> Self { - let edges = source.edges.clone(); - Self { - instructions: source - .instructions - .into_iter() - .map(|(id, kind)| (id::Instruction(Span { range: id..=id }), kind)) - .collect(), - edges: type_edges(source.edges), - // same as above, but also reverse the mapping - rev_edges: reverse_and_type_edges(edges), - } - } -} - -fn type_edges( - edges: Map>, -) -> Map> { - edges - .into_iter() - .map(|(output, inputs)| { - let output = id::Output(output.into()); - let inputs = inputs.into_iter().map(Into::into).map(id::Input).collect(); - (output, inputs) - }) - .collect() -} - -fn reverse_and_type_edges( - edges: Map>, -) -> Map> { - edges - .into_iter() - .fold(Map::new(), |mut rev_edges, (output, inputs)| { - let output = id::Output(output.into()); - - for input in inputs { - let input = id::Input(input.into()); - rev_edges.entry(input).or_default().insert(output.clone()); - } - - rev_edges - }) -} diff --git a/crates/ir/src/semi_human.rs b/crates/ir/src/semi_human.rs new file mode 100644 index 0000000..5d17646 --- /dev/null +++ b/crates/ir/src/semi_human.rs @@ -0,0 +1,82 @@ +//! The midterm solution for source representation, until we've got a nice source frontent. +//! +//! Sacrifices type expressivity for the sake of typability in [RON] files. +//! +//! [RON]: https://docs.rs/ron/latest/ron/ + +use serde::{Deserialize, Serialize}; + +use crate::{id, instruction, Map, Set, Span}; + +/// Semi-human-{read,writ}able [`crate::GraphIr`] with far less useful types. +/// +/// **Do not use this if you want to programatically construct IR.** +/// Instead, directly use [`crate::GraphIr`]. +#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] +pub struct GraphIr { + /// See [`crate::GraphIr::instructions`], just that a simple number is used for the ID instead + /// of a proper span. + pub(crate) instructions: Map, + /// See [`crate::GraphIr::edges`]. RON wants you to type the set as if it were a list. + pub(crate) edges: Map>, +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash, Deserialize, Serialize)] +pub struct Socket { + /// ID of the instruction this socket is on. + pub(crate) on: usize, + pub(crate) idx: u16, +} + +impl From for id::Socket { + fn from(source: Socket) -> Self { + Self { + belongs_to: (id::Instruction(Span { + range: source.on..=source.on, + })), + idx: id::SocketIdx(source.idx), + } + } +} + +impl From for crate::GraphIr { + fn from(source: GraphIr) -> Self { + let edges = source.edges.clone(); + Self { + instructions: source + .instructions + .into_iter() + .map(|(id, kind)| (id::Instruction(Span { range: id..=id }), kind)) + .collect(), + edges: type_edges(source.edges), + // same as above, but also reverse the mapping + rev_edges: reverse_and_type_edges(edges), + } + } +} + +fn type_edges(edges: Map>) -> Map> { + edges + .into_iter() + .map(|(output, inputs)| { + let output = id::Output(output.into()); + let inputs = inputs.into_iter().map(Into::into).map(id::Input).collect(); + (output, inputs) + }) + .collect() +} + +fn reverse_and_type_edges(edges: Map>) -> Map> { + edges + .into_iter() + .fold(Map::new(), |mut rev_edges, (output, inputs)| { + let output = id::Output(output.into()); + + for input in inputs { + let input = id::Input(input.into()); + rev_edges.entry(input).or_default().insert(output.clone()); + } + + rev_edges + }) +}