chore: rename executor -> evaluator and integrate into app
This commit is contained in:
parent
de9ca81b65
commit
3c529c3a1a
16 changed files with 229 additions and 115 deletions
|
@ -56,7 +56,7 @@ pub fn from_ron(source: &str) -> ron::error::SpannedResult<GraphIr> {
|
|||
/// So the vertices of the DAG are the **sockets**
|
||||
/// (which are either [`id::Input`] or [`id::Output`] depending on the direction),
|
||||
/// and each **socket** in turn belongs to an **instruction**.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
|
||||
pub struct GraphIr {
|
||||
/// "Backbone" storage of all **instruction** IDs to
|
||||
/// what **kind of instruction** they are.
|
||||
|
@ -123,13 +123,13 @@ impl GraphIr {
|
|||
/// to actually have multiple [`GraphIr`]s at one point in time.
|
||||
/// Open an issue if that poses a problem for you.
|
||||
#[must_use]
|
||||
pub fn resolve<'ir>(&'ir self, subject: &id::Instruction) -> Option<Instruction<'ir>> {
|
||||
pub fn resolve<'ir>(&'ir self, subject: &id::Instruction) -> Option<InstructionRef<'ir>> {
|
||||
let (id, kind) = self.instructions.get_key_value(subject)?;
|
||||
|
||||
let input_sources = self.input_sources(subject)?.collect();
|
||||
let output_targets = self.output_targets(subject)?.collect();
|
||||
|
||||
Some(Instruction {
|
||||
Some(InstructionRef {
|
||||
id,
|
||||
kind,
|
||||
input_sources,
|
||||
|
@ -141,7 +141,7 @@ impl GraphIr {
|
|||
///
|
||||
/// The same caveats as for [`GraphIr::resolve`] apply.
|
||||
#[must_use]
|
||||
pub fn owner_of_input<'ir>(&'ir self, input: &id::Input) -> Option<Instruction<'ir>> {
|
||||
pub fn owner_of_input<'ir>(&'ir self, input: &id::Input) -> Option<InstructionRef<'ir>> {
|
||||
self.resolve(&input.socket().belongs_to)
|
||||
}
|
||||
|
||||
|
@ -149,7 +149,7 @@ impl GraphIr {
|
|||
///
|
||||
/// The same caveats as for [`GraphIr::resolve`] apply.
|
||||
#[must_use]
|
||||
pub fn owner_of_output<'ir>(&'ir self, output: &id::Output) -> Option<Instruction<'ir>> {
|
||||
pub fn owner_of_output<'ir>(&'ir self, output: &id::Output) -> Option<InstructionRef<'ir>> {
|
||||
self.resolve(&output.socket().belongs_to)
|
||||
}
|
||||
|
||||
|
@ -163,7 +163,7 @@ impl GraphIr {
|
|||
#[must_use]
|
||||
// yes, this function could probably return an iterator and be lazy
|
||||
// no, not today
|
||||
pub fn topological_sort(&self) -> Vec<Instruction> {
|
||||
pub fn topological_sort(&self) -> Vec<InstructionRef> {
|
||||
// count how many incoming edges each vertex has
|
||||
let mut nonzero_input_counts: Map<_, NonZeroUsize> =
|
||||
self.rev_edges
|
||||
|
@ -240,18 +240,58 @@ impl GraphIr {
|
|||
}
|
||||
}
|
||||
|
||||
/// A full instruction in context, with its inputs and outputs.
|
||||
/// Constructs an [`id::Socket`] a bit more tersely.
|
||||
fn socket(id: &id::Instruction, idx: u16) -> id::Socket {
|
||||
id::Socket {
|
||||
belongs_to: id.clone(),
|
||||
idx: id::SocketIdx(idx),
|
||||
}
|
||||
}
|
||||
|
||||
/// A full instruction bundeled in context, with its inputs and outputs.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Instruction<'ir> {
|
||||
pub struct Instruction {
|
||||
pub id: id::Instruction,
|
||||
pub kind: instruction::Kind,
|
||||
|
||||
// can't have these two public since then a user might corrupt their length
|
||||
input_sources: Vec<Option<id::Output>>,
|
||||
output_targets: Vec<Set<id::Input>>,
|
||||
}
|
||||
|
||||
impl Instruction {
|
||||
/// Where this instruction gets its inputs from.
|
||||
///
|
||||
/// [`None`] means that this input is unfilled,
|
||||
/// and must be filled before the instruction can be ran.
|
||||
#[must_use]
|
||||
pub fn input_sources(&self) -> &[Option<id::Output>] {
|
||||
&self.input_sources
|
||||
}
|
||||
|
||||
/// To whom outputs are sent.
|
||||
#[must_use]
|
||||
pub fn output_targets(&self) -> &[Set<id::Input>] {
|
||||
&self.output_targets
|
||||
}
|
||||
}
|
||||
|
||||
/// [`Instruction`], but every single field is borrowed instead.
|
||||
/// See its docs.
|
||||
///
|
||||
/// Use the [`From`] impl to handily convert into an [`Instruction`].
|
||||
/// The other way around is unlikely to be wanted — since you already have an [`Instruction`],
|
||||
/// chances are you just want to take a reference (`&`) of it.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct InstructionRef<'ir> {
|
||||
pub id: &'ir id::Instruction,
|
||||
pub kind: &'ir instruction::Kind,
|
||||
|
||||
// can't have these two public since then a user might corrupt their length
|
||||
input_sources: Vec<Option<&'ir id::Output>>,
|
||||
output_targets: Vec<Option<&'ir Set<id::Input>>>,
|
||||
}
|
||||
|
||||
impl<'ir> Instruction<'ir> {
|
||||
impl<'ir> InstructionRef<'ir> {
|
||||
/// Where this instruction gets its inputs from.
|
||||
///
|
||||
/// [`None`] means that this input is unfilled,
|
||||
|
@ -268,10 +308,23 @@ impl<'ir> Instruction<'ir> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Constructs an [`id::Socket`] a bit more tersely.
|
||||
fn socket(id: &id::Instruction, idx: u16) -> id::Socket {
|
||||
id::Socket {
|
||||
belongs_to: id.clone(),
|
||||
idx: id::SocketIdx(idx),
|
||||
// would love to use ToOwned but Rust has no specialization yet
|
||||
// and it'd hurt a blanket impl of ToOwned otherwise
|
||||
impl From<InstructionRef<'_>> for Instruction {
|
||||
fn from(source: InstructionRef<'_>) -> Self {
|
||||
Self {
|
||||
id: source.id.clone(),
|
||||
kind: source.kind.clone(),
|
||||
input_sources: source
|
||||
.input_sources
|
||||
.into_iter()
|
||||
.map(Option::<&_>::cloned)
|
||||
.collect(),
|
||||
output_targets: source
|
||||
.output_targets
|
||||
.into_iter()
|
||||
.map(|outputs| outputs.map(Clone::clone).unwrap_or_default())
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue