2024-01-02 04:03:29 +00:00
#import "../template.typ": conf
2024-01-10 22:21:33 +00:00
#import "util/graphics.typ"
2024-01-10 20:10:05 +00:00
#import graphics: arrow
2024-01-02 04:03:29 +00:00
2024-01-10 20:22:29 +00:00
#show: conf.with(
title: [iOwO design],
subtitle: [don't worry, we're just dreaming],
2024-01-09 09:21:57 +00:00
)
2024-01-02 04:03:29 +00:00
= Type data model
== Requirements
- Color-aware
2024-01-09 09:21:57 +00:00
- It can handle colors and colorspaces for images
- OpenColorIO?
2024-01-02 04:03:29 +00:00
- number/number type support
- custom types (structs/enums)
- algebraic enums
- traits (`Numeric`...)
= Execution stages
#graphics.stages-overview
2024-01-11 10:51:03 +00:00
iOwO operates in stages.
This has a number of benefits and implications:
2024-01-10 20:10:05 +00:00
- One can just work on one aspect of the stages without having to know about the rest.
- Bugs are easier to trace down to one stage.
- Stages are also replacable, pluggable and usable somewhere else.
2024-01-11 10:51:03 +00:00
- For example,
one could write a Just-In-Time compiler as a new executor to replace the runtime stage,
while preserving the source #arrow() graph IR step.
2024-01-10 20:10:05 +00:00
However, this also makes the architecture somewhat more complicated. So here we try our best to describe how each stage looks like. If you have any feedback, feel free to drop it on #link("https://forge.katzen.cafe/katzen-cafe/iowo/issues")[the issues in the repository]!
2024-01-09 10:58:42 +00:00
== Source <source>
```iowo
open base.png >|
open stencil.png >|
mask
2024-01-10 20:22:29 +00:00
|> show
2024-01-09 10:58:42 +00:00
|> (invert | show)
```
2024-01-09 09:21:57 +00:00
Functional and pipeline-based.
However, in contrast to classic shell commands,
2024-01-11 10:51:03 +00:00
functions can have multiple outputs and multiple inputs.
2024-01-09 09:21:57 +00:00
2024-01-11 10:51:03 +00:00
=== Functions
`open`, `invert`, `mask`, `show` and friends.
2024-01-09 09:21:57 +00:00
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.
2024-01-11 10:51:03 +00:00
- An function with
2024-01-09 09:21:57 +00:00
- at least one output is called a streamer.
- at least one input is called a consumer.
2024-01-11 10:51:03 +00:00
- _both_ at least one input and at least one output is _both_ a streamer and a consumer,
and culminatively called a modifier.
2024-01-09 09:21:57 +00:00
- 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
2024-01-10 20:42:52 +00:00
add 1 2 -- all inputs as arguments
[ 1 2 ] | add -- all inputs through the pipeline
1 | add 2 -- one input through the pipeline, one as argument
2024-01-09 09:21:57 +00:00
```
==== Outputs
- Also based on position.
=== Pipelines <pipeline>
- Exchange data between streamers and consumers.
==== Simple forwarding
2024-01-11 10:51:03 +00:00
In the simplest case,
where inputs map to outputs bijectively#footnote[one to one],
pipelines are just pipes and forward unchanged:
2024-01-02 04:03:29 +00:00
2024-01-09 09:21:57 +00:00
```iowo
open owo.png | invert | save owo.png
```
==== Splitting <splitting>
To handle each output of a streamer individually, they can be _split_:
```iowo
mask
|> show -- would show the masked part
2024-01-10 20:10:05 +00:00
|> invert -- would invert the unmasked part
2024-01-09 09:21:57 +00:00
```
==== Combination <combination>
2024-01-11 10:51:03 +00:00
To throw multiple streamers into the inputs of a consumer,
they can be _combined_:
2024-01-09 09:21:57 +00:00
```iowo
open base.png >|
open stencil.png >|
mask
```
2024-01-11 10:51:03 +00:00
However, since lists are automatically spliced into inputs,
this is equivalent to the above:
2024-01-09 09:21:57 +00:00
```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.
2024-01-09 11:42:51 +00:00
== Graph IR
2024-01-09 10:58:42 +00:00
2024-01-10 20:10:05 +00:00
#graphics.graph-example
2024-01-09 11:42:51 +00:00
The parsed representation of the source, and also what the runtime operates on.
2024-01-09 10:58:42 +00:00
2024-01-09 11:42:51 +00:00
In a way, this is the AST, except that it's not a tree.
2024-01-02 04:03:29 +00:00
2024-01-11 10:51:03 +00:00
It is represented in iOwO using adjacencies, where essentially
the vertices#footnote[Nodes or functions in this case.]
and their edges#footnote[Connections or pipes in this case.]
are stored separately.
2024-01-10 20:10:05 +00:00
2024-01-02 04:03:29 +00:00
=== Optimizer
2024-01-11 10:51:03 +00:00
Merges and simplifies functions in the graph IR.
== Runtime <runtime>
2024-01-09 09:21:57 +00:00
2024-01-11 10:51:03 +00:00
Runs through all functions in the graph IR.
It does not have any significantly other representation,
and despite its name there's _no_ bytecode involved.
2024-01-09 09:21:57 +00:00
2024-01-11 10:51:03 +00:00
Different runtimes are called executors.
Executors operate on instructions instead of functions.
2024-01-10 20:10:05 +00:00
2024-01-09 09:21:57 +00:00
=== Scheduler
Looks at the graph IR and decides when the VM should execute what.
=== VM <vm>
= Open questions
2024-01-02 04:03:29 +00:00
2024-01-09 09:21:57 +00:00
- @input
2024-01-11 10:51:03 +00:00
- At which position are arguments injected into function inputs?
2024-01-09 09:21:57 +00:00
- 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?
2024-01-11 10:51:03 +00:00
- Could make more complex functions hard to read
2024-01-09 09:21:57 +00:00
- 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?
2024-01-11 10:51:03 +00:00
- @runtime
- What is the difference between an instruction and a function?
- 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` function or the like?
2024-01-09 09:21:57 +00:00
- Should consumers be called sinks instead?
- Shorter
- More ambiguous if only looking at the first char though