feat: graph-ir (continueing #6) #10
14 changed files with 198 additions and 143 deletions
117
Cargo.lock
generated
117
Cargo.lock
generated
|
@ -8,6 +8,20 @@ version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ahash"
|
||||||
|
version = "0.8.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"getrandom",
|
||||||
|
"once_cell",
|
||||||
|
"serde",
|
||||||
|
"version_check",
|
||||||
|
"zerocopy",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstream"
|
name = "anstream"
|
||||||
version = "0.6.5"
|
version = "0.6.5"
|
||||||
|
@ -171,6 +185,15 @@ version = "0.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
|
checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cli"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"clap",
|
||||||
|
"executor",
|
||||||
|
"ir",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "color_quant"
|
name = "color_quant"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
@ -271,7 +294,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"image",
|
"image",
|
||||||
"rpl",
|
"ir",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -374,10 +397,13 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "ir"
|
||||||
version = "1.0.10"
|
version = "0.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
dependencies = [
|
||||||
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
|
"ahash",
|
||||||
|
"ron",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jpeg-decoder"
|
name = "jpeg-decoder"
|
||||||
|
@ -400,17 +426,6 @@ version = "0.2.152"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
|
checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "libredox"
|
|
||||||
version = "0.0.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 2.4.1",
|
|
||||||
"libc",
|
|
||||||
"redox_syscall",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
version = "0.4.11"
|
version = "0.4.11"
|
||||||
|
@ -462,34 +477,10 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num_threads"
|
name = "once_cell"
|
||||||
version = "0.1.6"
|
version = "1.19.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
|
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "option-ext"
|
|
||||||
version = "0.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "owo-colors"
|
|
||||||
version = "4.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "caff54706df99d2a78a5a4e3455ff45448d81ef1bb63c22cd14052ca0e993a3f"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pl-cli"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"clap",
|
|
||||||
"executor",
|
|
||||||
"rpl",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "png"
|
name = "png"
|
||||||
|
@ -589,20 +580,6 @@ dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rpl"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"ron",
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ryu"
|
|
||||||
version = "1.0.16"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scopeguard"
|
name = "scopeguard"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
|
@ -747,6 +724,12 @@ version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version_check"
|
||||||
|
version = "0.9.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.11.0+wasi-snapshot-preview1"
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
|
@ -892,10 +875,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "yansi"
|
name = "zerocopy"
|
||||||
version = "0.5.1"
|
version = "0.7.32"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
|
checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy-derive"
|
||||||
|
version = "0.7.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zune-inflate"
|
name = "zune-inflate"
|
||||||
|
|
|
@ -2,13 +2,13 @@
|
||||||
members = [
|
members = [
|
||||||
"crates/app",
|
"crates/app",
|
||||||
"crates/executor",
|
"crates/executor",
|
||||||
"crates/rpl"
|
"crates/ir",
|
||||||
|
"crates/cli",
|
||||||
]
|
]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
clap = { version = "4", features = [ "derive" ] }
|
clap = { version = "4", features = ["derive"] }
|
||||||
serde = { version = "1.0", features = [ "derive" ] }
|
|
||||||
|
|
||||||
# to enable all the lints below, this must be present in a workspace member's Cargo.toml:
|
# to enable all the lints below, this must be present in a workspace member's Cargo.toml:
|
||||||
# [lints]
|
# [lints]
|
||||||
|
|
|
@ -8,7 +8,7 @@ edition = "2021"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { workspace = true, features = [ "derive" ] }
|
clap = { workspace = true, features = [ "derive" ] }
|
||||||
image = "0.24"
|
image = "0.24"
|
||||||
rpl = { path = "../rpl" }
|
ir = { path = "../ir" }
|
||||||
|
|
||||||
[lints]
|
[lints]
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
pub mod read {
|
pub mod read {
|
||||||
use image::{io::Reader as ImageReader, DynamicImage};
|
use image::{io::Reader as ImageReader, DynamicImage};
|
||||||
use rpl::instructions::read::{Read, SourceType};
|
use ir::instruction::read::{Read, SourceType};
|
||||||
|
|
||||||
pub fn read(Read { source, .. }: Read) -> DynamicImage {
|
pub fn read(Read { source, .. }: Read) -> DynamicImage {
|
||||||
// TODO: actual error handling
|
// TODO: actual error handling
|
||||||
|
@ -15,7 +15,7 @@ pub mod read {
|
||||||
|
|
||||||
pub mod write {
|
pub mod write {
|
||||||
use image::{DynamicImage, ImageFormat};
|
use image::{DynamicImage, ImageFormat};
|
||||||
use rpl::instructions::write::{TargetFormat, TargetType, Write};
|
use ir::instruction::write::{TargetFormat, TargetType, Write};
|
||||||
|
|
||||||
pub fn write(Write { target, format }: Write, input_data: &DynamicImage) {
|
pub fn write(Write { target, format }: Write, input_data: &DynamicImage) {
|
||||||
input_data
|
input_data
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rpl::instructions::{Filter, Instruction};
|
use ir::instruction::{Filter, Kind};
|
||||||
|
|
||||||
use crate::value::Dynamic;
|
use crate::value::Dynamic;
|
||||||
mod instructions;
|
mod instructions;
|
||||||
|
@ -6,12 +6,12 @@ mod instructions;
|
||||||
pub struct Executor;
|
pub struct Executor;
|
||||||
|
|
||||||
impl crate::Executor for Executor {
|
impl crate::Executor for Executor {
|
||||||
fn execute(instruction: Instruction, input: Option<Dynamic>) -> Option<Dynamic> {
|
fn execute(instruction: Kind, input: Option<Dynamic>) -> Option<Dynamic> {
|
||||||
match instruction {
|
match instruction {
|
||||||
Instruction::Read(read_instruction) => {
|
Kind::Read(read_instruction) => {
|
||||||
Some(Dynamic::Image(instructions::read::read(read_instruction)))
|
Some(Dynamic::Image(instructions::read::read(read_instruction)))
|
||||||
}
|
}
|
||||||
Instruction::Write(write_instruction) => {
|
Kind::Write(write_instruction) => {
|
||||||
instructions::write::write(
|
instructions::write::write(
|
||||||
write_instruction,
|
write_instruction,
|
||||||
match input {
|
match input {
|
||||||
|
@ -21,10 +21,10 @@ impl crate::Executor for Executor {
|
||||||
);
|
);
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
Instruction::Math(_) => todo!(),
|
Kind::Math(_) => todo!(),
|
||||||
Instruction::Blend(_) => todo!(),
|
Kind::Blend(_) => todo!(),
|
||||||
Instruction::Noise(_) => todo!(),
|
Kind::Noise(_) => todo!(),
|
||||||
Instruction::Filter(filter_instruction) => match filter_instruction {
|
Kind::Filter(filter_instruction) => match filter_instruction {
|
||||||
Filter::Invert => Some(Dynamic::Image(instructions::filters::invert::invert(
|
Filter::Invert => Some(Dynamic::Image(instructions::filters::invert::invert(
|
||||||
match input {
|
match input {
|
||||||
Some(Dynamic::Image(img)) => img,
|
Some(Dynamic::Image(img)) => img,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rpl::instructions::Instruction;
|
use ir::instruction::Kind;
|
||||||
use value::Dynamic;
|
use value::Dynamic;
|
||||||
|
|
||||||
mod debug;
|
mod debug;
|
||||||
|
@ -17,10 +17,10 @@ pub enum Executors {
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Executor {
|
trait Executor {
|
||||||
fn execute(instruction: Instruction, input: Option<Dynamic>) -> Option<Dynamic>;
|
fn execute(instruction: Kind, input: Option<Dynamic>) -> Option<Dynamic>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute_all(instructions: Vec<Instruction>) {
|
pub fn execute_all(instructions: Vec<Kind>) {
|
||||||
let mut tmp = None;
|
let mut tmp = None;
|
||||||
|
|
||||||
for instruction in instructions {
|
for instruction in instructions {
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
[package]
|
[package]
|
||||||
name = "rpl"
|
name = "ir"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde = { workspace = true, features = [ "derive" ] }
|
ahash = { version = "0.8.7", features = ["serde"] }
|
||||||
ron = "0.8"
|
ron = "0.8"
|
||||||
|
serde = { version = "1.0.193", features = ["derive"] }
|
||||||
|
|
||||||
[lints]
|
[lints]
|
||||||
workspace = true
|
workspace = true
|
|
@ -3,8 +3,8 @@ use serde::{Deserialize, Serialize};
|
||||||
pub mod read;
|
pub mod read;
|
||||||
pub mod write;
|
pub mod write;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub enum Instruction {
|
pub enum Kind {
|
||||||
Read(read::Read),
|
Read(read::Read),
|
||||||
Write(write::Write),
|
Write(write::Write),
|
||||||
Math(Math),
|
Math(Math),
|
||||||
|
@ -13,7 +13,7 @@ pub enum Instruction {
|
||||||
Filter(Filter),
|
Filter(Filter),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub enum Math {
|
pub enum Math {
|
||||||
Add,
|
Add,
|
||||||
Subtract,
|
Subtract,
|
||||||
|
@ -21,7 +21,7 @@ pub enum Math {
|
||||||
Divide,
|
Divide,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub enum Blend {
|
pub enum Blend {
|
||||||
Normal,
|
Normal,
|
||||||
Multiply,
|
Multiply,
|
||||||
|
@ -34,14 +34,14 @@ pub enum Blend {
|
||||||
Lighten,
|
Lighten,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub enum Noise {
|
pub enum Noise {
|
||||||
Perlin,
|
Perlin,
|
||||||
Simplex,
|
Simplex,
|
||||||
Voronoi,
|
Voronoi,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub enum Filter {
|
pub enum Filter {
|
||||||
Invert,
|
Invert,
|
||||||
}
|
}
|
|
@ -1,18 +1,18 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct Read {
|
pub struct Read {
|
||||||
pub source: SourceType,
|
pub source: SourceType,
|
||||||
pub format: SourceFormat,
|
pub format: SourceFormat,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub enum SourceType {
|
pub enum SourceType {
|
||||||
File(PathBuf),
|
File(PathBuf),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub enum SourceFormat {
|
pub enum SourceFormat {
|
||||||
Jpeg,
|
Jpeg,
|
||||||
Png,
|
Png,
|
|
@ -1,18 +1,18 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct Write {
|
pub struct Write {
|
||||||
pub target: TargetType,
|
pub target: TargetType,
|
||||||
pub format: TargetFormat,
|
pub format: TargetFormat,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub enum TargetType {
|
pub enum TargetType {
|
||||||
File(PathBuf),
|
File(PathBuf),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub enum TargetFormat {
|
pub enum TargetFormat {
|
||||||
Jpeg,
|
Jpeg,
|
||||||
Png,
|
Png,
|
108
crates/ir/src/lib.rs
Normal file
108
crates/ir/src/lib.rs
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
use std::ops::RangeInclusive;
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
pub mod instruction;
|
||||||
|
|
||||||
|
pub type Map<K, V> = ahash::AHashMap<K, V>;
|
||||||
|
pub type Set<V> = ahash::AHashSet<V>;
|
||||||
|
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Returns an error if the parsed source is not a valid graph IR.
|
||||||
|
pub fn from_ron(source: &str) -> ron::error::SpannedResult<GraphIr> {
|
||||||
|
ron::from_str(source)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The toplevel representation of a whole pipeline.
|
||||||
|
///
|
||||||
|
/// Pipelines may not be fully linear. They may branch out and recombine later on.
|
||||||
|
/// As such, the representation for them which is currently used is a
|
||||||
|
/// [**D**irected **A**cyclic **G**raph](https://en.wikipedia.org/wiki/Directed_acyclic_graph)
|
||||||
|
/// .
|
||||||
|
///
|
||||||
|
/// For those who are already familiar with graphs, a DAG is one, except that:
|
||||||
|
///
|
||||||
|
/// - It is **directed**: Edges have a direction they point to.
|
||||||
|
/// In this case, edges point from the outputs of streamers to inputs of consumers.
|
||||||
|
/// - It is **acyclic**: Those directed edges may not form loops.
|
||||||
|
/// In other words, if one follows edges only in their direction, it must be impossible
|
||||||
|
/// to come back to an already visited node.
|
||||||
|
///
|
||||||
|
/// Here, if an edge points from _A_ to _B_ (`A --> B`),
|
||||||
|
/// then _A_ is called a **dependency** of _B_,
|
||||||
|
/// and _B_ is called a **dependent** of _A_.
|
||||||
|
///
|
||||||
|
/// The DAG also enables another neat operation:
|
||||||
|
/// [Topological sorting](https://en.wikipedia.org/wiki/Topological_sorting).
|
||||||
|
/// This allows to put the entire graph into a linear list,
|
||||||
|
/// where it's guaranteed that once a vertex is visited,
|
||||||
|
/// all dependencies of it will have been visited already as well.
|
||||||
|
///
|
||||||
|
/// The representation used here in specific is a bit more complicated,
|
||||||
|
/// since **instructions** directly aren't just connected to one another,
|
||||||
|
/// but their **sockets** are instead.
|
||||||
|
///
|
||||||
|
/// 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)]
|
||||||
|
pub struct GraphIr {
|
||||||
|
/// "Backbone" storage of all **instruction** IDs to
|
||||||
|
/// what **kind of instruction** they are.
|
||||||
|
instructions: Map<id::Instruction, instruction::Kind>,
|
||||||
|
|
||||||
|
/// How the data flows forward. **Dependencies** map to **dependents** here.
|
||||||
|
edges: Map<id::Output, Set<id::Input>>,
|
||||||
|
/// How the data flows backward. **Dependents** map to **dependencies** here.
|
||||||
|
rev_edges: Map<id::Input, Set<id::Output>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod id {
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::Span;
|
||||||
|
|
||||||
|
/// One specific instruction, and where it is found in code.
|
||||||
|
///
|
||||||
|
/// It does **not** contain what kind of instruction this is.
|
||||||
|
/// Refer to [`crate::instruction::Kind`] for this instead.
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, Deserialize, Serialize)]
|
||||||
|
pub struct Instruction(Span);
|
||||||
|
|
||||||
|
impl Instruction {
|
||||||
|
/// Where this instruction is written down.
|
||||||
|
pub fn span(&self) -> &Span {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// On an **instruction**, accepts incoming data.
|
||||||
|
///
|
||||||
|
/// An **instruction** cannot run if any of these are not connected.
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, Deserialize, Serialize)]
|
||||||
|
pub struct Input(Socket);
|
||||||
|
|
||||||
|
/// On an **instruction**, returns outgoing data to be fed to [`Input`]s.
|
||||||
|
///
|
||||||
|
/// In contrast to [`Input`]s, [`Output`]s may be used or unused.
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, Deserialize, Serialize)]
|
||||||
|
pub struct Output(Socket);
|
||||||
|
|
||||||
|
/// An unspecified socket on a specific **instruction**,
|
||||||
|
/// and where it is on that **instruction**.
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, Deserialize, Serialize)]
|
||||||
|
pub struct Socket {
|
||||||
|
pub belongs_to: Instruction,
|
||||||
|
pub index: SocketIdx,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Where a [`Socket`] is on an **instruction**.
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, Deserialize, Serialize)]
|
||||||
|
pub struct SocketIdx(pub u16);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, Deserialize, Serialize)]
|
||||||
|
pub struct Span {
|
||||||
|
range: RangeInclusive<usize>,
|
||||||
|
}
|
|
@ -1,51 +0,0 @@
|
||||||
use instructions::Instruction;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
pub mod instructions;
|
|
||||||
|
|
||||||
/// # Panics
|
|
||||||
///
|
|
||||||
/// Panics if deserialization fails. lol.
|
|
||||||
#[must_use]
|
|
||||||
pub fn from_ron(raw: &str) -> Rpl {
|
|
||||||
ron::from_str(raw).expect("come back later and handle me correctly")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
|
|
||||||
pub struct Rpl(pub Vec<Instruction>);
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use crate::instructions::{
|
|
||||||
read::{SourceFormat, SourceType},
|
|
||||||
write::{TargetFormat, TargetType},
|
|
||||||
Math,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_simple_deserialize() {
|
|
||||||
const TEST_DATA: &str = concat!(
|
|
||||||
"([",
|
|
||||||
"Read( (source: File(\"~/example/file.png\"), format: Png) ),",
|
|
||||||
"Math(Add),",
|
|
||||||
"Write(( target: File(\"~/example/out.jpg\"), format: Jpeg)),",
|
|
||||||
"])",
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
from_ron(TEST_DATA),
|
|
||||||
Rpl(vec![
|
|
||||||
Instruction::Read(instructions::read::Read {
|
|
||||||
source: SourceType::File("~/example/file.png".into()),
|
|
||||||
format: SourceFormat::Png
|
|
||||||
}),
|
|
||||||
Instruction::Math(Math::Add),
|
|
||||||
Instruction::Write(instructions::write::Write {
|
|
||||||
target: TargetType::File("~/example/out.jpg".into()),
|
|
||||||
format: TargetFormat::Jpeg
|
|
||||||
})
|
|
||||||
])
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -40,7 +40,7 @@
|
||||||
just nushell
|
just nushell
|
||||||
typst typst-lsp
|
typst typst-lsp
|
||||||
mold
|
mold
|
||||||
cargo-nextest
|
cargo-nextest cargo-watch
|
||||||
];
|
];
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|
Loading…
Reference in a new issue