# UPIL Language

The UPIL language was designed to allow both developers and non-developers to describe "scenarios", or high-level flows of interaction between a user and an application. UPIL has several high-level entities to allow you to interact with a user. UPIL also includes other concepts for describing high-level business-logic including conditional logic, loading data from external sources, and external actions.

# Entity Structure

Most entities have the following structure:

<Entity Name> <Optional Label>
  <Entity Contents>
/<Entity Name>
1
2
3

For example:

TEMPLATE myLabel
  "Message to user"
/TEMPLATE
1
2
3

EXTERNAL, RUN, and ACTION entities have a simpler structure:

EXTERNAL currentTemp
1
ACTION sendEmail
1
RUN main
1

TEMPLATE entites also have a simple version:

Text only:

TEMPLATE "Hi there"
1

Label only:

TEMPLATE overrideThis
1

# User-Interaction

User interaction is performed using three main entities: TEMPLATE, SELECT, and MULTI_SELECT. All three entities can save user input to a variable with the >>myVariable syntax. This allows the user input to be referenced and used later on in the scenario.

# Template

A TEMPLATE entity is for displaying text to a user. TEMPLATEs can also request a user's input.

TEMPLATE for greeting the user with the text "Hi there!":

TEMPLATE "Hi there!"
1

Example TEMPLATE with user input request saved to the variable name:



 


TEMPLATE
  "What is your name?"
  >>name
/TEMPLATE
1
2
3
4

# Selects

# SELECT

A SELECT is used to request the user to select a single choice from a list of choices. It requires the user input to be saved to a variable.

SELECT
 "Please choose your favorite color"
  -("Red", "red")
  -("Blue", "blue")
  -("Green", "green")
  >>color
/SELECT
1
2
3
4
5
6
7

# MULTI_SELECT

A MULTI_SELECT is similar to a SELECT, only it allows users to select more than one choice from a list

MULTI_SELECT
 "Please choose all of your favorite colors"
  -("Color red", "red")
  -("Color blue", "blue")
  -("Color green", "green")
  >>colors
/MULTI_SELECT
1
2
3
4
5
6
7

# Options

There are several ways to write options in a SELECT or MULTI_SELECT

# Default case
-("Color red", "red")
1

The default case presents the user with an option Color red, while saving red in the select's variable.

# Simplified case
- "Red"
1

The simplified version would use Red both for the option text, and the value saved in the select's variable.

# Value types

The value of an option can be a literal such as a string, number, or boolean:

String:

-("Color red", "red")
1

Number:

-("Five cars", 5)
1

Boolean:

-("Call taxi", true)
1

The value of an option can also come from a variable. This is specified by using a variable name without quotes. If the variable doesn't exist, then the UPIL engine will assume it should use the variable name as a string value.

Variable:

-("My car", usersCar)
1

Here is an example of using the above variable case:

## Resolves to ferrari
EXTERNAL usersCar

DIALOG main
SELECT
"Which car do you want?"
-("My car", usersCar)
-("Default", "honda accord") >>carSelection
/SELECT

TEMPLATE "Have fun driving a ${carSelection}"
/DIALOG

RUN main

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

If the value of the EXTERNAL was set to "ferrari", then when a user chooses the My car option, the variable carSelection will be set with the value of the variable usersCar which is "ferrari"

# Scenario Flow

UPIL scenarios have a simple structure. DIALOG, and RUN entities are two of the three entities that can exist at the top level of a document (EXTERNAL being the third).

DIALOG is a container for other entities. The UPIL engine runs entities from top to bottom inside of a DIALOG. However the order of DIALOG entities inside of a scenario doesn't matter. Instead, DIALOG to start a scenario at is specified by the scenario writer with the RUN command. After that, other DIALOG entities will only be used if they are referred to by embed ...dialogName calls.

# Dialog

A DIALOG is a container that most entities must be wrapped in. The UPIL Engine runs the steps of a scenario in the order that they appear in a DIALOG:


DIALOG main
TEMPLATE "I'm first"
TEMPLATE "I'm second"
TEMPLATE "I'm third"
/DIALOG
RUN main

1
2
3
4
5
6
7
8

A DIALOG can hold TEMPLATE, SELECT, MULTI_SELECT, IF/ELIF/ELSE, ACTION, and even other DIALOG entities.

# Dialog Embedding

Using the ...<dialogLabel> sytax, a DIALOG can embed another DIALOG inside of itself:



 












DIALOG main
  TEMPLATE "OK lets start!"
  ...getUserName
  TEMPLATE "Nice to meet you ${name}"
/DIALOG

DIALOG getUserName
  TEMPLATE
    "What is your name?"
    >>name
  /TEMPLATE
/DIALOG

RUN main
1
2
3
4
5
6
7
8
9
10
11
12
13
14

A DIALOG can be embedded in as many other DIALOGs as you want. The order of DIALOGs don't matter.

# Run

The RUN command specifies the DIALOG to start the scenario at.

The below two examples demonstrate how changing the RUN command changes which DIALOG is processed by the Engine:

Start at dialog A:

DIALOG B
  TEMPLATE
    "Hi from B"
  /TEMPLATE
/DIALOG

DIALOG A
TEMPLATE
"Hi from A"
/TEMPLATE
/DIALOG

RUN A

1
2
3
4
5
6
7
8
9
10
11
12
13
14

Start at dialog B:


DIALOG B
TEMPLATE
"Hi from B"
/TEMPLATE
/DIALOG

DIALOG A
TEMPLATE
"Hi from A"
/TEMPLATE
/DIALOG

RUN B

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# Scenario Logic

UPIL contains several features that can be used to conditionally hide or show parts of a scenario. This allows you to dynamically adjust a scenario to user-input and/or external data.

# Conditional logic

UPIL has boolean IF, ELIF, and ELSE entities. You can use conditional logic to make scenarios that respond dynamically to user-input and external data:










 

 

 

 








 



DIALOG main
  SELECT
    "Please choose your favorite color"
    -("Red", "red")
    -("Blue", "blue")
    -("Green", "green")
    -("Other", "other")
    >>color
  /SELECT
  IF color=="red"
    TEMPLATE "You must like roses!"
  ELIF color=="blue"
    TEMPLATE "You must like the ocean!"
  ELIF color=="green"
    TEMPLATE "You must like nature!"
  ELSE
    DIALOG
      TEMPLATE
        "Okay, what other color do you like?"
        >>otherColor
      /TEMPLATE
      TEMPLATE "I see. We'll have to think of a new witty response for when someone chooses '${otherColor}'!"
    /DIALOG
  /IF
/DIALOG

RUN main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# Boolean Expressions

UPIL allows you to use boolean expressions with IF/ELIF/ELSE conditional logic to hide/show parts of a scenario, or to choose which 'branch' to take.

# Boolean comparators

The following comparators can be used with mixes of variables and literals:

==, >, <, >=, <=

# Examples

currentTemp >= 25
True if the variable currentTemp is greater or equal to the number 25.

car == "toyota"
True if the variable car is equal to the string toyota

# Boolean operators

The following logical operators allow you to combine several boolean statements together:

AND, NOT, OR, ()

# Examples

Example using AND, OR, and ():
((currentTemp >= 25 AND hour > 100) OR hello == "GREAT") AND hi == "Something"

Using OR and NOT:
hour > 100 OR NOT (currentTemp >= 25)

# Application communication

UPIL includes three features to make it easy to communicate between a scenario and an application which utilizes UPIL: EXTERNAL and ACTION entities, and entity labels. These features allow a scenario writer to use high-level concepts, which a developer can then hook up to arbitrarily complex implementations. Ideally even after the implementation has been created, the scenario writer can freely update their scenario without having to rely on a developer to update the implementation.

# External

The EXTERNAL entity allows a scenario writer to request that the implementation prepare a variable with some data so that the scenario may make use of it.

Basic example:

 










EXTERNAL currentTime

DIALOG A
TEMPLATE
"The current time is ${currentTime}"
/TEMPLATE
/DIALOG

RUN A

1
2
3
4
5
6
7
8
9
10

This example registers a hook in the Engine that a developer must use to prepare data that a scenario requires. This example's implementation saves either 'cloudy', 'sunny', or 'rainy' to the weather variable before the scenario begins:

 
















EXTERNAL weather

DIALOG weatherExplanation
  TEMPLATE "The weather is currently ${weather}"
  IF weather=="cloudy"
    TEMPLATE "It's going to be cool all day"
  ELIF weather=="sunny"
    TEMPLATE "Pack your sunscreen it's going to be hot!"
  ELIF weather=="rainy"
    TEMPLATE "Looks like you're going to need an umbrella today!"
  ELSE
    TEMPLATE "I can't even explain this weather..."
  /IF
/DIALOG

RUN weatherExplanation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# Action

An ACTION allows scenario writers to request that a side-effect happens in the implementation. This can include saving data, sending messages such as emails or push notifications, or making calls to external services. Actions can be used to make a call with variables gathered by the script, and can save the result in a variable itself. An ACTION must be placed inside of a DIALOG. When the Engine reaches an ACTION in the scenario, it tells the implementation about it. The implementation can decide whether or not to delay the scenario until the ACTION is complete. An example usecase for an ACTION is sending an email or a push message at a specific point in the scenario.












 









DIALOG rainy
  TEMPLATE "Looks like you're going to need an umbrella today!"
  SELECT
    "Do you want me to call a taxi for you?"
    -("Yes", true)
    -("No", false)
    >>callTaxi
  /SELECT
  IF callTaxi==true
    DIALOG
      TEMPLATE "Okay, I'll get right on that!"
      ACTION callTaxi
    /DIALOG
  ELSE
    TEMPLATE "Drive safe!"
  /IF
/DIALOG

RUN rainy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
DIALOG rainy
  TEMPLATE
    "What word would you like to look up?"
    >>lookupWord
  /TEMPLATE
  ACTION lookupDefinition
    {
      lookupWord
    }
    >>wordDefinition
  /ACTION
  IF wordDefinition == null
    TEMPLATE "Sorry, I could not find a definition for '${lookupWord}'"
  ELSE
    TEMPLATE "The definition of ${lookupWord} is '${wordDefinition}'"
  /IF
/DIALOG

RUN rainy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# Labels

Labels are required in many cases, such as when using an ACTION entity or when referring to a DIALOG from a RUN entity. There are many cases however where optional labels are useful as well, for communicating with an underlying implementation.

Labels can be applied to a TEMPLATE, SELECT, or MULTI_SELECT entity in order to override the default behavior for a specific entity. For instance, instead of just showing text, an application may want to substitute in a complex widget such as a map, or a data table. By agreeing on a label name and overriding an entity when that name appears, scenario writers and developers can work together to create much more complex interactions than is possible with just exchanging text.

Here is an example where the implementation is waiting to override an entity with the label brandImage with an embedded image of their brand in addition to the text:



 







DIALOG welcome
  TEMPLATE "Welcome to our site!"
  TEMPLATE brandImage
    "I'll be guiding you through our options today"
  /TEMPLATE
/DIALOG

RUN welcome

1
2
3
4
5
6
7
8
9

# Variables

Variables are where user input and input from EXTERNAL entities are stored.

Example variable called name:



 


TEMPLATE
  "What is your name?"
  >>name
/TEMPLATE
1
2
3
4

All variables are stored in a global namespace. This means if a single variable name is used multiple times, it will be overwritten each time. This also means that if a DIALOG is called multiple times from different parts of a scenario, variables created inside of it will be overwritten each time they are set.

Example of variable someVariable being overwritten:




 



 



 







DIALOG varTest
  TEMPLATE 
    "What is your favorite color?"
    >>someVariable
  /TEMPLATE
  TEMPLATE 
    "What is your favorite fruit?"
    >>someVariable
  /TEMPLATE
  TEMPLATE 
    "What is your hobby?"
    >>someVariable
  /TEMPLATE
  TEMPLATE "The value of 'someVariable' is ${someVariable}"
/DIALOG

RUN varTest

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
```