Some documentation

This commit is contained in:
Tony Garnock-Jones 2021-10-05 21:38:39 +02:00
parent f060740f82
commit e08a5a4bd9
1 changed files with 86 additions and 3 deletions

View File

@ -2,13 +2,37 @@
set -euo pipefail
# Set to an incoming TurnEvent by `ds_dispatch`.
#
ds_event=
# Counter for allocating handle IDs and OIDs. (We could have separate
# counters for each of these, but why bother?)
#
ds_handle=0
# Buffer of pending TurnEvents to be sent out. `ds_action` augments
# the buffer; `ds_flush` sends and resets it.
#
ds_buf=""
# These two map user-supplied names to previously-asserted handle IDs
# and previously-asserted target OIDs, respectively, for later use in
# `ds_retract`.
#
declare -A ds_handles
declare -A ds_handle_oids
declare -A ds_object_map
declare -A ds_retraction_handlers
# Maps local OIDs to callback code to execute when events arrive for
# that OID.
#
declare -A ds_object_map
# ds_project <term> <preserves-path>
#
# Applies the Preserves-Path expression to the given term, writing the
# result(s) to stdout, one per line.
#
ds_project() {
# cargo install preserves-tools
local input="$1"
@ -17,13 +41,27 @@ ds_project() {
echo "$input" | preserves-tool convert --indent=no --select "$selector" "$@"
}
# ds_connect_stdio <code>
#
# Uses stdin for input from our peer, and stdout to send output to our
# peer, connecting them to fds 5 and 6 respectively before evalutating
# `code` and entering a mainloop.
#
ds_connect_stdio() {
eval "$1"
exec 5<&0 6>&1
eval "$1"
ds_flush
ds_mainloop
}
# ds_connect <addr> <code>
#
# `addr` should match schema transportAddress.Tcp,
# transportAddress.Unix, or transportAddress.Stdio. Uses `nc` for the
# first two and `ds_connect_stdio` for the last. Causes `code` to be
# evaluated in a context where fds 5 and 6 are for input from and
# output to the peer, respectively, before entering a mainloop.
#
ds_connect() {
local addr=$1
case $(ds_project "$addr" ".^") in
@ -44,11 +82,20 @@ ds_connect() {
} 5< <(nc $nc_args <$f) 6>$f
}
# ds_send <data>
#
# Transmits `data` immediately to the peer via fd 6.
#
ds_send() {
echo "$@" >&6
# echo "SENDING: $@"
}
# ds_mainloop
#
# Repeatedly reads a line from the peer (fd 5) and dispatches it to a
# local object.
#
ds_mainloop() {
while read ds_packet
do
@ -61,11 +108,22 @@ ds_mainloop() {
done <&5
}
# ds_dispatch <localoid> <event>
#
# Sets `ds_event` to `event`. Then, looks up and executes local object
# code using `localoid`.
#
ds_dispatch() {
ds_event="$2"
eval "${ds_object_map[$1]}"
}
# ds_action <wireref> <event>
#
# `wireref` should be a sturdy.WireRef. If it's a `mine`, dispatches
# `event` locally via `ds_dispatch`; if it's a `yours`, adds `event`
# to `ds_buf` (for a subsequent `ds_flush` to actually transmit).
#
ds_action() {
case $(ds_project "$1" '.embedded . 0') in
0) ds_dispatch "$(ds_project "$1" '.embedded . 1')" "$2" ;;
@ -73,6 +131,10 @@ ds_action() {
esac
}
# ds_flush
#
# Transmits (and resets) `ds_buf` if it's non-empty.
#
ds_flush() {
if [ -n "$ds_buf" ]
then
@ -81,6 +143,12 @@ ds_flush() {
fi
}
# ds_assert <wireref> <term> [<localname>]
#
# Asserts `term` to `wireref`. If `localname` is supplied, records
# enough information to allow `localname` to be used with `ds_retract`
# later to retract the assertion.
#
ds_assert() {
local h="$ds_handle"
ds_handle=$(($ds_handle + 1))
@ -92,14 +160,29 @@ ds_assert() {
fi
}
# ds_retract <localname>
#
# Retracts a previously-asserted term using a `localname` supplied to
# `ds_assert`.
#
ds_retract() {
ds_action "${ds_handle_oids[$1]}" "<retract ${ds_handles[$1]}>"
}
# ds_message <wireref> <term>
#
# Sends `term` to `wireref`.
#
ds_message() {
ds_action "$1" "<message $2>"
}
# ds_object <varname> <code>
#
# Allocates a fresh local OID, and registers `code` to be called when
# an event arrives for it. Stores a `wireref` for the new OID in the
# local variable named `varname`.
#
ds_object() {
local oid="$ds_handle"
ds_handle=$(($ds_handle + 1))