Control flow
The DashaScript language allows you to represent the dialogue model in a natural way: Dasha's speech is described with nodes, and the interlocutor's answers are handled with transitions.
Here is an example of a dialogue model program where Dasha asks a question and says different phrases, depending on the interlocutor's answer:
start node cookieQuestion { do { #connectSafe(""); #sayText("Do you like cookies?"); wait *; } transitions { suggestCookie: goto suggestCookie on #messageSentiment("positive"); eatCookie: goto eatCookie on #messageSentiment("negative"); } } node suggestCookie { do { #sayText("Luckily, I have one for you."); exit; } } node eatCookie { do { #sayText("Then I'll eat it myself! Omnomnom."); exit; } }
The order of the program's execution is determined by the events occurring during the execution. The most common example of such an event is an interlocutor's phrase. In the above example, the program is executed in the following order:
- Execution starts in the start node
cookieQuestion
. - The
wait
operator puts Dasha into waiting for response mode. - For any received response, the
suggestCookie
andeatCookie
transition conditions are checked. - The transition is triggered once its condition equals
true
.
The interlocutor's answer defines which transition will be triggered. Here, answer "yes" will trigger the suggestCookie
transition, and the dialogue will proceed to the respective node. If the interlocutor's phrase triggers no transition, the phrase is considered processed, and Dasha will wait for the next phrase.
Events
You can switch Dasha to waiting mode in the do
section of the node using the wait
operator.
In waiting mode, Dasha listens for incoming events and reacts to them. Events are checked against the node's and the active digressions' conditions in the descending order of priorities. When the condition satisfied by the event found, the respective transition is triggered.
Events differ in types, so each transition contains a list of tags to determine the types of events triggering it. You can specify tags with the tags
keyword. The default transition's tag is ontext
.
Event types
Description | Tag |
End of conversation | onclosed |
Interlocutor's phrase is recognized | ontext (default value) |
Time step; emited roughly every 200 ms | ontick |
Note: don't rely on tick events being emitted every 200 ms as their period is subject to change.
Examples
The script below logs every time step and terminates when the connection is closed.
start node root { do { #connectSafe("myEndpoint"); wait *; } transitions { // Override default tag with "ontick". tickLogger: goto tickLogger on true tags: ontick; } } node tickLogger { do { // Expected output: "tick" on every tick. #log("tick"); wait *; } transitions { // Override default tag with "ontick". tickLogger: goto tickLogger on true tags: ontick; } } digression hangup { conditions { // Override default tag with "onclosed". on true tags: onclosed; } do { exit; } }
Executable section
The sections of a node containing custom code to be executed are called executable sections. From the executable section, you can access the conversation context, block context and node’s local data, as well as call built-in and external functions.
Note that you can not access conversation context inside block. If you need to assign something to conversation context variable, return the value from the block.
do
The do
section is executed when the dialogue begins processing the node.
start node myNode { do { #log("I'm executing do section"); exit; } }
onexit
The onexit
node section is defined right after transitions section and allows to specify actions to perform before exiting the node. You can define different actions for exiting through different transitions, for example:
/** * insert targetNode1, targetNode2, targetNode3 declarations */ node dedicatedOnexit { do { wait *; } transitions { a: goto targetNode1 on false; b: goto targetNode2 on false; c: goto targetNode3 on false; } onexit { // Executes when exiting through the transition "a". a: do { /* ... */ } // Executes when exiting through the transition "b" and "c". b: c: do { /* ... */ } } }
You can define special onexit
actions to be performed when exiting through the digression's transition:
node defaultDigressionOnexit { do { /* ... */ } transitions { /* ... */ } onexit { // Executes when exit by any digression. digression: do { /* ... */ } } }
You can also define onexit
actions to be executed when exiting through any transition with the default
keyword. Keep in mind, that the default
subsection won't be executed when the more specific subsection is defined.
node theNode { do { /* ... */ } transitions { a: goto a on false; b: goto b on false; c: goto c on false; } onexit: { default: do { /* ... */ } } }
Transition operators
wait
The wait <transitionList>
operator activates the listed transitions. Use *
to activate all available transitions.
Calling wait
before opening or after closing a connection may result in a not responding script. Any code placed after the wait
operator is discarded and won't be executed.
node myNode { do { wait {a}; // to activate transtion "а". wait {a, b}; // to activate transtions "а" and "b". wait *; // to activate transtions "а", "b" and "c". } transitions { a: goto a on #messageSentiment("positive"); b: goto b on #messageSentiment("negative"); c: goto c on #messageSentiment("neutral"); } }
Examples
/** * insert nodes "a", "b", "c" declaration */ start node myNode { do { // Activate "а" transition. wait { a }; // Activate "а" and "b" transition. wait { a, b }; // Activate all transitions: "a", "b" and "c". wait *; } transitions { a: goto a on #messageHasSentiment("positive"); b: goto b on #messageHasSentiment("positive"); c: goto c on #messageHasSentiment("positive"); } }
goto
The goto <transitionName>
operator instantly triggers a transition.
node myNode { do { goto targetNode; } transitions { targetNode: goto targetNode; } }