# The Context

Wasot is for humans and [tools](./tools.md) working together.
It is optimized for humans to write fast using blocks (see [data model](./wasot_and_xml.md)).
Tools act on different block types via [selectors](./selectors.md).
But sometimes, when a tool processes a block, it wants information from another tool processing another block.

## One tool wants to communicate with another tool

Let's say for example, we have this:

```wasot
.document User-Manual
.page 10

.idea 
This is my idea

.idea
This is another idea
```

Let's say we have a tool, exporting all ideas. It wants add a source-reference, to track where the idea came from.
For this, it needs information from other blocks.
We don't want nesting, as we want to keep things flat to make writing easy.
But how does the document-name and page-number get to the two idea-blocks?

The trick is to use a context, which is like a blackboard, every tool can put things on and get things of.

## Put it into the context

A wasot file is a tree, but also an event-log, representing a tree, in the example above, this would look something like this:

```wasot-log
block-started, type=document, inline-text=User Manual
block-finished
block-started, type=page, inline-text=10
block-finished
block-started, type=idea
text, This is my idea
block-finished
block-started, type=idea
text, This is another idea
block-finished
```

The wasot parser reads the wasot file and converts it into these [events](./architecture.md).
This event stream can then be changed by [transformers](./architecture.md), which consume events on one side and emit (maybe other) events on the
other side.

Such transformers can enable tools. A tool listens and acts upon a certain block type.
Such a tool could be a page-setter, which handles a page-block.
This tool would read the inline-text and add another event, which puts to the context.
The same with a tool looking for documents.
As a transformer manages them, the modified event log could look something like this:

```wasot-log
block-started, type=document, inline-text=User Manual
put-context, key=document-name, value=User Manual
block-finished
block-started, type=page, inline-text=10
put-context, key=current-page, value=10
block-finished
block-started, type=idea
text, This is my idea
block-finished
block-started, type=idea
text, This is another idea
block-finished
```

## So why not scoped variables?

Wasot documents are trees, like XML. [Wasot and XML are equivalent](./wasot_and_xml.md).
Thus there are natural scopes for variables. You define a variable in the current scope.
Later blocks can then access the variables of previous blocks and parent blocks.
Whenever a block is popped from the stack, the corresponding variable scope is as well.

Using this would be fine, but one level of abstraction above the event log, in which a wasot document is represented.
Wasot documents are a stream of events. Only when they are collected, they form a tree.
The same goes for variables. There are context-actions, put context, in the event log.
A consumer can decide himself what to do with them. Collect them in hierarchical scopes, discard them like the pretty printer does or something else entirely.
Staying one level below gives other modules the freedom to do their own stuff rather than dictating what to do.
We still allow for scoped variables, but don't force to do them using context-events.

Aside: Beside the freedom, variables are probably not the right metaphor anyway. Variables are, well, variable.
And they are temporary. We store them into the event log.
Variables are produced by emitters or tools and not visible in the wasot document code. Variables are!
A better metaphor would be a event store like in event sourcing. Each document is an event store database.

## Context and tools

A tool takes a sub-tree as a list of events and a context and produces a new sub-tree and upserts to the context:

![Diagram as image](./the_context__tools_and_context.png)

```plantuml
@startuml
' --- Layout Direction ---
left to right direction

' --- Element Definition ---
' Data inputs
rectangle "SubTree" as SubTree
rectangle "ContextElements" as ContextElements

' The central tool
rectangle "Tool"

' Data outputs
rectangle "NewSubTree" as NewSubTree
rectangle "ContextPutEvents" as ContextPutEvents

' --- Connections ---
SubTree --> Tool
ContextElements --> Tool
Tool --> NewSubTree
Tool --> ContextPutEvents

' --- Notes ---
note top of SubTree
  This can be just a list of events
end note

note bottom of ContextElements
  This can be a collected list
end note

note top of NewSubTree
  Probably also just a list of events
end note

@enduml
```

The subtree itself is just a subset of all events making up a wasot documents.

Note: You can see, that there are no declerations of context-elements in the code of a wasot documents.
These are done within the tools. But tools are optional and can change. Thus the variables-metaphor does not really work.

For the practical API, see [context and scoped variables](./context_and_scoped_variables.md).


## Put-Context upsert semantics

You can see in the diagram above, that the only operations required on the context are put and get. 
Putting into the context is an upsert operation. 
It is implemented by an append-only log, as the put-event will be just another entry in the wasot-file which is an event-log itself.
This makes the context immutable locally as nothing is overwritten, but still updateable. 
It is an immutable data-structure. If you want to get a value, you scan for your key from the back to the front.


## Duplicate entries

To make make the context an immutable datastructure, integrted with the event-log of a wasot-document.
This means, that there is no uniqueness constraint on the key of the 
It is fine to have duplicate entries in the put-context events. 
Somebody using the context can decide to scan the context-events from back to front, giving the illusion that you can overwrite stuff in the context.
Using this enables, that you get upsert semantics for free. Putting things in the context is just appending to the log.
The context-events in the log are just a subset of all events of the log of a wasot-document, thus the context integrates nicely with the architecture of wasot.

## What can be a value?

An element in a context is a key-value pair, where the key is a string, which does not have to be unique.
But what type does the value have? It has to be serializable as we write wasot files to disk. 
It also has to be human readable, as humans are first class citicenzs in all parts of the system.

As the world settled on JSON and it satisfies our other contraines, the values are encoded in a single-line JSON (as in one line of a JSONL-file).
After reading and in transit, the value is parsed in a easy and fast to access way, preventing continuing parsing, but it is alsways JSON serializable and 
serialized JSON when at rest.

Thus a context-entry looks like this in rust:

```rust
use serde::{Deserialize, Serialize};
use serde_json::Value;

#[derive(Serialize, Deserialize, Debug)]
pub struct ContextEntry {
    pub key: String,
    pub value: Value,
}
```

## Serialization

The `Value` represents one of the JSON-Types - `Object`, `Array`, `String`, `Number`, `Boolean`, `Null`.

Serialization to string works as expected

```rust
fn main() {
    // Create the different Value types
    let num_val: Value = json!(9.48);
    let str_val: Value = json!("Hello from Wildpoldsried!");
    let bool_val: Value = json!(true);
    let null_val: Value = json!(null);

    // Serialize each one to a string
    let num_str = serde_json::to_string(&num_val).unwrap();
    let str_str = serde_json::to_string(&str_val).unwrap();
    let bool_str = serde_json::to_string(&bool_val).unwrap();
    let null_str = serde_json::to_string(&null_val).unwrap();

    // Print the results
    println!("Value::Number serializes to: {}", num_str);
    println!("Value::String serializes to:  {}", str_str);
    println!("Value::Bool serializes to:    {}", bool_str);
    println!("Value::Null serializes to:     {}", null_str);
}
```

With the output:

```text
Value::Number serializes to: 9.48
Value::String serializes to:  "Hello from Wildpoldsried!"
Value::Bool serializes to:    true
Value::Null serializes to:     null
```

## In the event-log

Each entry in the event-log has exactly one key. If you want to emit more updates, you emit more events.

As there are only 2 operations, put and get, and only put is state-changing, there is only only one additional event type in wasot, `put-event`

With this, we arrive at the event-log introduced above:

```wasot-log
block-started, type=document, inline-text=User Manual
put-context, key=document-name, value=User Manual
block-finished
block-started, type=page, inline-text=10
put-context, key=current-page, value=10
block-finished
block-started, type=idea
text, This is my idea
block-finished
block-started, type=idea
text, This is another idea
block-finished
```