docs: some initial groundwork #2

Merged
multisamplednight merged 26 commits from :initial-docs into main 2024-01-20 19:00:52 +00:00
3 changed files with 204 additions and 11 deletions
Showing only changes of commit b30cbb4d7b - Show all commits

View file

@ -67,10 +67,7 @@
nodes(
[Source],
[Graph IR],
[Optimizer],
[Compiler],
[VM Bytecode],
[VM],
[Runtime],
)
})

View file

@ -2,7 +2,73 @@
#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())
+ "|"
multisamplednight marked this conversation as resolved Outdated

I think we should remove this entire section from this document for now, since I'm working on this in a different document

I think we should remove this entire section from this document for now, since I'm working on this in a different document
+ 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
}
multisamplednight marked this conversation as resolved Outdated

I really dislike using the word execution here, as it's a very common trigger word. Do you have any alternative ideas?

I **really** dislike using the word `execution` here, as it's a very common trigger word. Do you have any alternative ideas?

Parsing? Evaluation? Interpretation?

Parsing? Evaluation? Interpretation?

Those are all individual phases of execution.

Those are all individual phases of execution.

Hm. Thinking about it, Evaluation seems generic enough. I'll use that then.

Hm. Thinking about it, `Evaluation` seems generic enough. I'll use that then.
#let terminate-recursion(it) = {
let clusters = it.text.clusters()
multisamplednight marked this conversation as resolved Outdated

This is fine, probably something we can work on further as the project progresses though and it gets more complex...

This is fine, probably something we can work on further as the project progresses though and it gets more complex...
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
multisamplednight marked this conversation as resolved Outdated

This is why I proposed using lists, dictionaries etc. in #4, to make this easier/cleaner

This is why I proposed using lists, dictionaries etc. in #4, to make this easier/cleaner
#outline(
indent: auto,
fill: line(
length: 100%,
stroke: (
cap: "round",
join: "round",
thickness: 0.5pt,
paint: luma(75%),
),
),
)
= Type data model
@ -10,7 +76,7 @@
- Color-aware
- It can handle colors and colorspaces for images
- ocio????
- 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 <input>
- 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 <pipeline>
- 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 <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 <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 <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

View file

@ -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 {