2024-01-19 11:07:09 +00:00
|
|
|
//! The midterm solution for source representation, until we've got a nice source frontend.
|
2024-01-18 20:54:41 +00:00
|
|
|
//!
|
|
|
|
//! Sacrifices type expressivity for the sake of typability in [RON] files.
|
|
|
|
//!
|
2024-01-18 21:24:03 +00:00
|
|
|
//! **If you want to construct a graph IR programmatically,
|
|
|
|
//! use [`crate::GraphIr`] directly instead,
|
|
|
|
//! as it gives you more control to specify where your instructions came from.**
|
|
|
|
//!
|
2024-01-18 20:54:41 +00:00
|
|
|
//! [RON]: https://docs.rs/ron/latest/ron/
|
|
|
|
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
2024-01-19 13:26:20 +00:00
|
|
|
use crate::{id, instruction, Map, Set};
|
2024-01-18 20:54:41 +00:00
|
|
|
|
|
|
|
/// 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
|
2024-01-19 13:26:20 +00:00
|
|
|
pub(crate) instructions: Map<u64, instruction::Kind>,
|
2024-01-18 23:45:01 +00:00
|
|
|
/// See [`crate::GraphIr::edges`], the forward edges.
|
|
|
|
/// RON wants you to type the set as if it were a list.
|
2024-01-18 20:54:41 +00:00
|
|
|
pub(crate) edges: Map<Socket, Set<Socket>>,
|
|
|
|
}
|
|
|
|
|
2024-01-18 23:45:01 +00:00
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)]
|
2024-01-18 20:54:41 +00:00
|
|
|
pub struct Socket {
|
|
|
|
/// ID of the instruction this socket is on.
|
2024-01-19 13:26:20 +00:00
|
|
|
pub(crate) on: u64,
|
2024-01-18 20:54:41 +00:00
|
|
|
pub(crate) idx: u16,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<Socket> for id::Socket {
|
|
|
|
fn from(source: Socket) -> Self {
|
|
|
|
Self {
|
2024-01-19 13:26:20 +00:00
|
|
|
belongs_to: id::Instruction(source.on),
|
2024-01-18 20:54:41 +00:00
|
|
|
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()
|
2024-01-19 13:26:20 +00:00
|
|
|
.map(|(id, kind)| (id::Instruction(id), kind))
|
2024-01-18 20:54:41 +00:00
|
|
|
.collect(),
|
|
|
|
edges: type_edges(source.edges),
|
|
|
|
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()
|
|
|
|
}
|
|
|
|
|
2024-01-18 23:45:01 +00:00
|
|
|
fn reverse_and_type_edges(edges: Map<Socket, Set<Socket>>) -> Map<id::Input, id::Output> {
|
2024-01-18 20:54:41 +00:00
|
|
|
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());
|
2024-01-18 23:45:01 +00:00
|
|
|
let previous = rev_edges.insert(input, output.clone());
|
|
|
|
if let Some(previous) = previous {
|
2024-01-21 20:08:27 +00:00
|
|
|
// TODO: handle this with a TryFrom impl
|
|
|
|
panic!("two or more outputs referred to the same input {previous:#?}");
|
2024-01-18 23:45:01 +00:00
|
|
|
}
|
2024-01-18 20:54:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
rev_edges
|
|
|
|
})
|
|
|
|
}
|