Signals
Paradigm(s) | imperative, event-driven |
---|---|
Designed by | User:stkptr |
Appeared in | 2025 |
Dimensions | one-dimensional |
Computational class | Turing complete |
Reference implementation | Unimplemented |
Signals is a programming language inspired by the observer pattern (Wikipedia). Signals has two objects: signals, and listeners. Signal objects can have arbitrarily many listeners connected, including arbitrarily many of the same listener. Signals can be dispatched/emitted/fired, which causes connected listeners to execute.
Syntax
Programs are made up of signal and listener definitions. Comments can occur at the end of any line, and start with #
.
signal signal_name # define a signal # define a listener listener listener_name { ... }
Names of signals and listeners are global and cannot clash. Listener definitions cannot nest, and consist of a number of statements. Statements connect, disconnect, and fire signals.
Connect a listener and signal, causing the listener to execute when the signal fires (the order of the arguments doesn't matter):
connect listener_name and signal_name connect signal_name and listener_name
Disconnect a listener and signal, disconnecting all occurrences:
disconnect listener_name and signal_name disconnect signal_name and listener_name
Clear all connected listeners from a signal:
clear signal_name
Remove a listener from the listener list of every signal:
clear listener_name
Fire a signal, causing the listeners to execute:
emit signal_name
Every program has an implicit toplevel connect init and on_init
followed by emit init
, so programs must contain a listener named on_init
in order to have anything happen.
Programs execute until the halt
signal is fired, or the execution reaches the end of the on_init
listener.
Extensions
A simple I/O extension:
signal print_h # prints the ASCII character 'h' listener on_print_h { emit out_0 emit out_1 emit out_1 emit out_0 emit out_1 emit out_0 emit out_0 emit out_0 } # simple cat listener on_in_1 { emit out_1 } listener on_in_0 { emit out_0 } listener on_init { # print 'h' connect print_h and on_print_h emit print_h # begin cat program connect in_1 and on_in_1 connect in_0 and on_in_0 }
With this IO extension there are 4 signals added:
out_0
: push a 0 bit to the output when emittedout_1
: push a 1 bit to the output when emittedin_0
: emits when a 0 bit is pushed to the inputin_1
: emits when a 1 bit is pushed to the input
The in signals work as interrupts. When the signals are emitted, the execution of the program is paused, and connected listeners are executed until they all reach the end of their definitions, then the program resumes where it was.
The input and outputs are handled as queue buffers. The output queue will typically output to the final destination as soon as 8 bits have been output. The input queue will fire its signals as soon as it receives bits, firing them one at a time as interrupts.
Computational class
The language is Turing complete. Proof forthcoming.
Variants
A variant where disconnecting a listener only disconnects at most one would also be Turing complete, and would be easier to implement counter machines in. A variant where signals can only have at most one of each listener connected would be in the class of finite state automata, since there would be a finite amount of state that could be stored at a given time.
In other languages
- GDScript has an esoteric subset which is similar to Signals, but listeners can only be connected to a signal at most once