So, Reasoner.js would be a virtual device. Console also. Permanent and temporary memory also. This minimal set could be enriched by other devices like sound, vision, ... Note that every device has its input or output, or both.
In between of these devices, there would be a "coordinator". It would be a glue which mediates between devices, receiving messages from source devices and sending them to target devices. A coordinator could be also considered a kind of device.
There could be many coordinators, and each coordinator code would follow this pattern:
(
COORDINATE
(
CONDUCT
(
EVENTS
(RECEIVE (SOURCE ...) (DATA ...))
...
)
(
ACTIONS
(SEND (TARGET ...) (DATA ...))
...
)
)
...
)
The coordinator is a set of conductors that listens to device events and conducts related actions to devices.
The problem solved by coordinator is very important one: managing states. Managing states is needed when, for example, we want to change memory contents as inputs flow in. Code written in Reasoner.js is just a static conglomerate of referentially transparent functions, and if we would be solving states in Reasoner.js, we would have to deal with monads or other gimmicks I am not a big fan of. Other than that, it was also taken under consideration making a separate finite state machine for managing states. But it turned out we don't need anything else than the coordinator between devices which, internally, do or don't manage states.
So, when we want to receive a message from, say, console source, we listen from coordinator to console input event. Then, if we want to process the console input, we pair that event to an action of calling Reasoner.js target code, passing the console input as a parameter, and listening for a result message. The resulting message may raise a new event coupled with an action of sending the data to memory device. By the same event we may also want to write something back to console. To do that, we can put another action for it, next to the action of memorizing data. The whole cycle could repeat on every console input event. Maybe some other arbitrary device events could be also shown useful, like custom reminders, timers, attention requests, ...
With the coordinator I saved myself a bit of a trouble of writing a finite state machine which would be more complicated than implementing the coordinator listening and talking to different devices. It would be up to devices how to manage states. Less is better, right? Especially if there are no functionality trade offs.
[EDIT]
After some research, I discovered that what I'm planning to implement is exactly well known service oriented programming (
SOP) paradigm. Good to know. What I call "device", it is called "service" in SOP. I'll align my terminology with SOP terminology. Nevertheless, the process between receiving and sending messages in SOP reminds me very much of term rewriting. Actually it's exactly term rewriting if we are sending and receiving messages from and to the same coordinator/router. I plan to use here the same "variable" notion from reasoner.js, of course, but without nondeterminism.