iowo/crates/ir/src/semi_human.rs

83 lines
2.6 KiB
Rust
Raw Normal View History

//! 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
})
}