diff --git a/docs/design/graphics.typ b/docs/design/graphics.typ
index cf5f7e0..5e0ef4c 100644
--- a/docs/design/graphics.typ
+++ b/docs/design/graphics.typ
@@ -67,10 +67,7 @@
nodes(
[Source],
[Graph IR],
- [Optimizer],
- [Compiler],
- [VM Bytecode],
- [VM],
+ [Runtime],
)
})
diff --git a/docs/design/iowo-design.typ b/docs/design/iowo-design.typ
index 5c02cee..4d8e8d8 100644
--- a/docs/design/iowo-design.typ
+++ b/docs/design/iowo-design.typ
@@ -2,15 +2,81 @@
#import "graphics.typ"
#show: conf.with(title: [iOwO design], subtitle: [don't worry, we're just dreaming])
-#show ">": graphics.arrow()
+
+// highlight important terms in bold
+#let expand(it) = {
+ ("("
+ + upper(it.first())
+ + "|"
+ + it.first()
+ + ")"
+ + it.clusters().slice(1).join()
+ + "s?")
+}
+#let singlify(it) = {
+ it = lower(it)
+ if it.ends-with("s") {
+ it = it.slice(0, -1)
+ }
+ it
+}
+#let terminate-recursion(it) = {
+ let clusters = it.text.clusters()
+ clusters.insert(1, "\u{FEFF}")
+ clusters.join()
+}
+// TODO: could make this just look over headings in section "Execution stages" tbh
+#let terms = (
+ "source",
+ "graph IR",
+ "runtime",
+
+ "optimizer",
+ "scheduler",
+ "VM",
+
+ "command",
+ "pipeline",
+ "input", "argument", "consumer",
+ "output", "streamer",
+ "modifier",
+)
+#let terms-trigger = regex(terms.map(expand).join("|"))
+#show raw: it => {
+ // avoid making terms in codeblocks bold
+ show terms-trigger: terminate-recursion
+ it
+}
+#show terms-trigger: strong
+
+// color codeblocks
+// haskell hl seems to work ok for this
+#show raw.where(lang: "iowo", block: true): it => {
+ raw(it.text, lang: "haskell", block: true)
+}
+
+// actual content lol
+
+#outline(
+ indent: auto,
+ fill: line(
+ length: 100%,
+ stroke: (
+ cap: "round",
+ join: "round",
+ thickness: 0.5pt,
+ paint: luma(75%),
+ ),
+ ),
+)
= Type data model
== Requirements
- Color-aware
- - It can handle colors and colorspaces for images
- - ocio????
+ - It can handle colors and colorspaces for images
+ - OpenColorIO?
- number/number type support
- custom types (structs/enums)
- algebraic enums
@@ -20,12 +86,130 @@
#graphics.stages-overview
-== Source > Graph IR
+== Source
-== Graph IR > VM Bytecode
+Functional and pipeline-based.
+However, in contrast to classic shell commands,
+commands can have multiple outputs and multiple inputs.
+
+=== Commands
+
+The foundation of actually "doing" something.
+
+- Can have any, even infinite, amount of inputs and outputs.
+ - Their amounts may or may not be equal.
+- Inputs and outputs must have their types explicitly declared.
+- An command with
+ - at least one output is called a streamer.
+ - at least one input is called a consumer.
+ - _both_ at least one input and at least one output is _both_ a streamer and a consumer, and culminatively called a modifier.
+- May also contain spaces in its name.
+
+==== Inputs
+
+- Based on position.
+- Inputs can be provided both through the pipeline and ad-hoc.
+- Ad-hoc inputs are called arguments.
+- So all of these are equivalent:
+
+```iowo
+1 | add 2
+add 1 2
+[ 1 2 ] | add
+```
+
+==== Outputs
+
+- Also based on position.
+
+=== Pipelines
+
+- Exchange data between streamers and consumers.
+
+==== Simple forwarding
+
+In the simplest case, where inputs map to outputs bijectively#footnote[one to one], pipelines are just pipes and forward unchanged:
+
+```iowo
+open owo.png | invert | save owo.png
+```
+
+==== Splitting
+
+To handle each output of a streamer individually, they can be _split_:
+
+```iowo
+mask
+|> invert -- would invert the unmasked part
+|> show -- would show the masked part
+```
+
+==== Combination
+
+To throw multiple streamers into the inputs of a consumer, they can be _combined_:
+
+```iowo
+open base.png >|
+open stencil.png >|
+mask
+```
+
+However, since lists are automatically spliced into inputs, this is equivalent to the above:
+
+```iowo
+[
+ open base.png,
+ open stencil.png,
+]
+| mask
+```
+
+=== Comments
+
+Done with any of `--` or `//`.
+
+=== Data types
+
+==== Lists
+
+- Signified by `[]` braces.
+- If thrown into a pipeline, it automatically works like a streamer.
+- Can be delimited by commas.
+ - Must be delimited by commas if a contained streamer takes an input.
+- May have a trailing comma.
+- Outputs of streamers are spliced into the contained list.
+ - In effect, they are automatically flattened.
+
+== Graph IR
=== Optimizer
-=== Compiler
+Merges and simplifies commands in the graph IR.
-== VM Bytecode > VM
+== Runtime
+
+=== Scheduler
+
+Looks at the graph IR and decides when the VM should execute what.
+
+=== VM
+
+= Open questions
+
+- @input
+ - At which position are arguments injected into command inputs?
+ - How could that be controlled if set to e.g. the end by default?
+ - Not all inputs are order-independent, e.g. `div`
+ - Should inputs and outputs really be positional?
+ - Could make more complex commands hard to read
+ - But keyworded could also make code very noisy
+ - Maybe a middle ground, such that at most 1 input is allowed to be positional?
+- @pipeline
+ - We need some way to reshuffle and reorder outputs and inputs in a pipeline
+- @splitting
+ - How would one split different outputs into a list?
+- Should outputs that are not thrown into a consumer be automatically displayed in some kind of debug view?
+ - Or should that be done instead using a debug `show` command or the like?
+- Should consumers be called sinks instead?
+ - Shorter
+ - More ambiguous if only looking at the first char though
diff --git a/docs/template.typ b/docs/template.typ
index a688b07..5bdf52a 100644
--- a/docs/template.typ
+++ b/docs/template.typ
@@ -15,6 +15,7 @@
) = {
set page(
numbering: "1 / 1",
+ margin: 3.25cm,
header: locate(loc => {
datetime.today().display()
@@ -29,6 +30,17 @@
set heading(numbering: "A.1")
show heading: it => text(..fonts.heading, it)
+ show raw.where(block: true): box.with(
+ fill: luma(95%),
+ inset: 1.25em,
+ radius: 0.75em,
+ width: 45em,
+ )
+ show raw.where(block: false): box.with(
+ fill: luma(95%),
+ outset: 0.25em,
+ radius: 0.25em,
+ )
// document title
if title != none {