To create programming workflows and programming language aimed at expressing systems built with asynchronous components, I think you need two kinds of components
internally synchronous, reactive code components, and
recursive-grouping components.
Both of these are easy to build using data flow that doesn't bring unnecessary control flow baggage with it.
I call code components Leaf components. I call grouping components Container components.
To do the above, you, also, need to provide for components with multiple inputs and multiple outputs over time. Functions expect all inputs to arrive at once and all outputs to be returned at once. Functions only make it appear that multiple inputs are provided, but in hardware this is implemented as single inputs using the technique of destructuring. Likewise for outputs.
To allow programmers to freely design asynchronous systems, they must not be restricted in their choice of routing strategies. Functions use exactly one routing strategy - the callee must return a value(s) to the caller. Other routing strategies are lumped under the label “side effect”. The idea behind using functions in this way is to provide for “referential transparency”, i.e. a way to plug functions together and to replace functions with other functions with compatible signatures. There are other ways to achieve this same result, for example, in electronics this idea is called “pin for pin compatibility”. In electronics, ICs are little black boxes with well-defined APIs (their set of “pins”). The internals of ICs are encased in epoxy and plastic, making it hard to determine what is going on inside the ICs - only the outward-facing APIs (pins) matter. ICs with compatible sets of pins can replace one another. The APIs are specified in data books using not only value information, but, also, timing information.
Example Code
A simple example of building Leaf and Container components using an existing programming language (Python, in this example) can be found in the raw-pbp repo.
An example of moving to the next level and using diagrams instead of hand-rolling code is in the arith repo. More involved examples can be found in various repos, like the HTML-Larson repo.
The PBP kernel and t2t tools can be found in the pbp-dev repo. The kernel is actually written in a meta-VHLL that generates code in Python, Javascript and Common Lisp (other target languages should be easy, but I don’t have the time nor energy).
See Also
Email: ptcomputingsimplicity@gmail.com
References: https://guitarvydas.github.io/2024/01/06/References.html
Blog: guitarvydas.github.io
Videos: https://www.youtube.com/@programmingsimplicity2980
Discord: https://discord.gg/65YZUh6Jpq
Leanpub: [WIP] https://leanpub.com/u/paul-tarvydas
Twitter: @paul_tarvydas
Substack: paultarvydas.substack.com