Denver-Augusta-Harrisburg

Denver-Augusta-Harrisburg is a concurrent-message-passing programming
language.
Execution of a Denver-Augusta-Harrisburg program starts with the main
thread and the system thread. The main thread executes the main
routine with the system thread as its first argument and can spawn
more threads. A thread can send messages to and receive messages from
other threads, including itself. A message consists of a thread.
When receiving a message, the sender thread is also received.
Execution of the program ends when the main thread exits.
==Grammar==
 program = routine-definition*
 
 routine-definition = routine-identifier variable-identifier* body
 body = '{' statement* '}'
 
 statement = guard* (assignment-statement | break-statement |
 continue-statement | loop-statement | message-statement)
 assignment-statement = variable-identifier '<' (expression | spawn)
 break-statement = loop-identifier? 'break'
 continue-statement = loop-identifier? 'continue'
 loop-statement = loop-identifier? body
 message-statement = '[' message-statement-arm* ']'
 
 expression = variable-identifier | 'null' | 'self'
 guard = expression? ('=' | '!') expression
 spawn = '[' routine-identifier expression* ']'
 
 message-statement-arm = guard* (receive | send) body
 receive = variable-identifier variable-identifier '<' expression*
 send = expression '<' expression
 
 loop-identifier = identifier
 routine-identifier = identifier
 variable-identifier = identifier
Comments begin with == and extend to the end of the line.
Identifiers are uninterrupted sequences of non-space characters,
excluding =, !, [, ], {, }, <, and may not be
break, continue, null, or self. Space characters serve to
separate tokens and are otherwise ignored.
==Routines==
A routine is declared with its routine identifier, a list of
parameters, and a body. The routine identifier is also the loop
identifier of the body. The parameters must be distinct from each
other.
Routine identifiers must be unique within a program.
When a thread is spawned, it executes the routine it was spawned with
by executing the statements in its body in a loop. The thread exits
when the routine body is exited.
==Statements==
Every statement may have a guard list, where the statement is executed
only if each item in the guard list is satisfied. A guard list may be
empty.
If a guard is expression = expression, then the rest of the
statement is only executed if the two expressions evaluate to the same
thread.
If a guard is expression ! expression, then the rest of the
statement is only executed if the two expression evaluate to different
threads.
If a guard is = expression, then the rest of the statement is only
executed if the expression evaluates to a thread that has not exited.
It is not guaranteed that that thread has not exited when the rest of
the statement executes. The null thread is always considered to
have exited.
If a guard is ! expression, then the rest of the statement is only
executed if the expression evaluates to a thread that has exited.
===Assignment statement===
An assignment statement sets the variable to the value of the
expression. If the expression is a spawn expression, it spawns a new
thread and set the variable to the new thread. The new thread
executes the routine specified in the spawn expression, with its
parameters set to the arguments in the spawn expression.
Other than spawn expressions, expressions are a variable, null, or
self. A variable evaluates to the value the variable was last
assigned, either by an assignment statement or a receive arm of a message
statement, or the null thread if not previously assigned. null
evaluates to the null thread. self evaluates to the currently
executing thread.
===Break statement===
A break statement exits the specified, or, if not specified, innermost
enclosing loop statement or message statement or routine body.
===Continue statement===
A continue statement continues executing at the beginning of the
specified, or, if not specified, innermost enclosing loop statement or
message statement or routine body.
===Loop statement===
A loop statement specifies a list of statements that are executed in a
loop until exited. A loop can be exited by a break statement for the
loop or by a break or continue statement for an enclosing loop
statement, message statement or routine body.
===Message statement===
A message statement specifies a list of arms. An arm may have a guard
list, for which each item must be satisfied for the arm to be
active. An active arm attempts to send to a thread, receive from any
in a list of threads, or receive from any thread. If there are no
active arms, execution continues to the next statement. If there are
multiple active arms, execution is blocked until one or more active
arms can succeed. One of the arms that can succeed will succeed, and
its body will be executed, then, unless the body of the successful arm
exits the message statement, the message statement is executed again.
If execution is blocked because every active arm is attempting to send
to an exited thread or the null thread, or is attempting to receive
only from exited threads or the null thread, execution continues to
the next statement.
A send arm sends its right argument to its left argument.
A receive arm assigns the message received to the first variable on
the left and the sender to the second variable on the left. The first
variable and the second variable must not be the same variable. The
arguments on the right is a list of sender threads. If the list is
not empty, it can only receive from a thread in the list. If the list
is empty, it can receive from any thread.
If an arm has an = expression guard and another arm has a !
expression guard, and the expressions evaluate to the same thread,
at most one of the two arms will be active, depending on other
guards. If there are no other guards, exactly one of the two arms
will be active. If the arm with the = expression guard executes, it
is not guaranteed that the thread has not exited since the guard was
passed.
==Loop identifiers==
A loop identifier is associated with a routine, a loop statement, or a
message statement. break and continue statements may specify a
loop identifier to specify which loop statement or message statement
they apply to, or if they apply to the body of the routine.
The scope of the loop identifier is the body of its loop statement or
the bodies of every arm of its message statement.
The routine identifier is the loop identifier of the routine body and
its scope is the routine body.
A loop identifier must not duplicate any other loop identifier that is
in scope.
==Variables==
All variables are scoped to the routine in which it is used and,
except for the routine parameters, are initially set to null. The
routine parameters, listed after the routine identifier in the routine
declaration, are initially set to values specified as arguments in the
spawn expression. If there are fewer arguments provided in the spawn
expression than the number of routine parameters, the remaining
parameters are set to null.
==Threads==
A new thread is spawned when an assignment statement is executed with
a spawn expression. The variable on the left-hand side of the
assignment statement is assigned the new thread. The new thread
executes the routine specified by the routine identifier in the spawn
expression, and its parameters are set to the arguments specified in
the spawn expression. If there are more parameters than arguments,
the remaining parameters are set to null. If there are more
arguments than parameters, the remaining arguments are ignored.
There are also some special threads.
===Main thread===
The main thread is spawned when the program starts and executes the
main routine. If it has parameters, the first parameter is set to
the system thread. Any additional parameters are set to the null
thread.
===Null thread===
Uninitialized variables are set to the null thread, which never
sends messages and ignores any message it receives.
===System thread===
The system thread is passed as the first parameter to the main
routine in the main thread.
The system thread has a list of threads that provide various
services. Sending any item in the list to the system thread causes
the system thread to send the next item in the list to the sender.
The first item in the list is the system thread itself. Sending the
last element in the list or a thread not in the list to the system
thread causes the system thread to send the null thread to the
sender.
The list of threads contains the system thread, the input thread, and
the output thread.
===Input thread===
When anything is sent to the input thread, if the next bit of input is
1, the input thread sends the input thread to the sender. If the next
bit of input is 0, the input thread sends null to the sender. If
there is no more input, the input thread exits.
There is no guaranteed ordering if multiple threads send to the input
thread.
===Output thread===
The output thread never sends any messages. If it receives null, a
0 bit is output. If it receives anything else, a 1 bit is output.
There is no guaranteed ordering if multiple threads send to the output
thread.
==Examples==
===cat===
 main system {
 [in=null system < system {[in _ < system {break}]}]
 [out=null system < in {[out _ < system {break}]}]
 
 [state=null in < self {state < in}
 state=in b _ < in {state < out}
 state=out out < b {state < null}
 ]
 break
 }
===lock===
 lock locker {
 == send self to lock to acquire lock
 == send null to lock to release lock
 == send anything else to lock to query lock
 == lock always responds with lock holder or null if not held
 [msg sender < {
 [
 == acquire
 msg=sender locker=null sender < sender {locker < sender break}
 msg=sender locker!null sender < locker {break}
 
 == release
 msg=null locker=sender sender < null {locker < null break}
 msg=null locker!sender sender < locker {break}
 
 == query
 msg!sender msg!null sender < locker {break}
 ]
 }
 ]
 }
===list===
 cons car cdr {
 == send null to get car
 == send anything else to get cdr
 [sender=null op sender < {}
 sender!null op=null sender < car {break}
 sender!null op!null sender < cdr {break}
 ]
 sender < null
 }
===stack===
 stack nil {
 == send nil to stack to pop, empty stack returns nil
 == send anything else to push
 serve [
 msg sender < {
 msg=nil [
 list=null sender < nil {serve continue}
 list!null list < nil {
 [car _ < list {
 sent-car < null
 got-cdr < null
 [sent-car=null sender < car {sent-car < self}
 got-cdr=null list _ < list {got-cdr < self}
 ]
 serve continue
 }
 ]
 }
 ]
 msg!nil list < [cons msg list]
 }
 ]
 }
===tape===
 exited{break}
 
 tape ? + - {
 == send ? to read
 == send + to advance one element
 == send - to rewind one element
 == send anything else to write
 == unwritten elements default to null
 head < null
 nil < [exited] == use exited thread as a private constant
 fwd < [stack nil]
 bwd < [stack nil]
 serve [
 msg sender < {
 msg=? {[sender < head {serve continue}]}
 msg=+ {[bwd < head {[fwd < nil {[head _ < fwd {head=nil head < null serve continue}]}]}]}
 msg=- {[fwd < head {[bwd < nil {[head _ < bwd {head=nil head < null serve continue}]}]}]}
 msg!? msg!+ msg!- {head < msg}
 }
 ]
 }
==References==
* Implementation
Category:Languages
Category:Implemented
Category:2022