chore: put semi human graph ir into its own module
This commit is contained in:
parent
961ca89a50
commit
e4d7a22372
2 changed files with 87 additions and 79 deletions
|
@ -4,6 +4,10 @@ use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
pub mod instruction;
|
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<K, V> = ahash::AHashMap<K, V>;
|
pub type Map<K, V> = ahash::AHashMap<K, V>;
|
||||||
pub type Set<V> = ahash::AHashSet<V>;
|
pub type Set<V> = ahash::AHashSet<V>;
|
||||||
|
|
||||||
|
@ -18,7 +22,7 @@ pub type Set<V> = ahash::AHashSet<V>;
|
||||||
///
|
///
|
||||||
/// Returns an error if the parsed source is not a valid human-readable graph IR.
|
/// Returns an error if the parsed source is not a valid human-readable graph IR.
|
||||||
pub fn from_ron(source: &str) -> ron::error::SpannedResult<GraphIr> {
|
pub fn from_ron(source: &str) -> ron::error::SpannedResult<GraphIr> {
|
||||||
let human_repr: SemiHumanGraphIr = ron::from_str(source)?;
|
let human_repr: semi_human::GraphIr = ron::from_str(source)?;
|
||||||
Ok(human_repr.into())
|
Ok(human_repr.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,81 +119,3 @@ pub mod id {
|
||||||
pub struct Span {
|
pub struct Span {
|
||||||
range: RangeInclusive<usize>,
|
range: RangeInclusive<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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<usize, instruction::Kind>,
|
|
||||||
/// See [`GraphIr::edges`]. RON wants you to type the set as a list.
|
|
||||||
edges: Map<SemiHumanSocket, Set<SemiHumanSocket>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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<SemiHumanSocket> 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<SemiHumanGraphIr> 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<SemiHumanSocket, Set<SemiHumanSocket>>,
|
|
||||||
) -> Map<id::Output, Set<id::Input>> {
|
|
||||||
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<SemiHumanSocket, Set<SemiHumanSocket>>,
|
|
||||||
) -> Map<id::Input, Set<id::Output>> {
|
|
||||||
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
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
82
crates/ir/src/semi_human.rs
Normal file
82
crates/ir/src/semi_human.rs
Normal file
|
@ -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<usize, instruction::Kind>,
|
||||||
|
/// See [`crate::GraphIr::edges`]. RON wants you to type the set as if it were a list.
|
||||||
|
pub(crate) edges: Map<Socket, Set<Socket>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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<Socket> 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<GraphIr> 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<Socket, Set<Socket>>) -> Map<id::Output, Set<id::Input>> {
|
||||||
|
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<Socket, Set<Socket>>) -> Map<id::Input, Set<id::Output>> {
|
||||||
|
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
|
||||||
|
})
|
||||||
|
}
|
Loading…
Reference in a new issue