/mbot-programming-language

πŸ€– is an Emoji-based programming language to control your mBot. Written in Haskell.

Primary LanguageHaskell

The πŸ€– Programming Language

A simple Emoji-based programming language to control a physical or simulated mBot.

While πŸ€– was not meant to be serious, it does work. This repository provides an interpreter for the language, written in Haskell. If you have a physical mBot, you can write programs and execute them on there. If not, we provide a simulator to mimick the mBot and its surroundings.

Example Programs

Police Car

This program makes the robot blink its LEDs like a police car.

πŸ”πŸ‘
   🚨 πŸ‘ˆ 100 0 0
   🚨 πŸ‘‰ 0 0 100
   😴 πŸ•‘
   🚨 πŸ‘ˆ 0 0 100
   🚨 πŸ‘‰ 100 0 0
   😴 πŸ•‘

In the infinite loop, we set the left LED to red and the right LED to blue. After that, we wait 400 milliseconds, swap the colors, wait once more and start over.

Obstacle Avoidance

This program makes the robot drive straight ahead and avoid any obstacles.

πŸ’­ And I would drive 500 miles..

dist βͺ 20

πŸ”πŸ‘
   ❓ πŸ“ > dist
      πŸ’¨  ⬆️
   ❗️
      πŸ’¨  ⬇️
      😴  πŸ•”
      πŸ’¨  ➑️
      😴  πŸ•‘

We continuously read the distance sensor (πŸ“) and compare it to the threshold dist. If the distance is greater than dist, we keep driving straight ahead. Otherwise, we back up for 800 ms and then turn right for 400 ms before we continue our way.

Follow The Line

This program makes the robot follow a black line on the floor.

prev βͺ πŸŒ‘

πŸ”πŸ‘
   new βͺ πŸ”­

   πŸ’­ Reuse the last line reading if there's no line in sight,
   πŸ’­ or save this reading if the we know the direction of the line
   ❓new == πŸŒ•
      new βͺ prev
   ⁉️ new  == πŸŒ“ || new  == πŸŒ—
      prev βͺ new

   ❓ new  == πŸŒ‘
      πŸ’¨ ⬆️
   ⁉️ new  == πŸŒ“
      πŸ’¨ ⬅️
   ⁉️ new  == πŸŒ—
      πŸ’¨ ➑️

We continuously read the line sensor (πŸ”­) and steer to follow the line. If no line is detected (πŸŒ•), we reuse the last detected value. If the line is detected on the left (πŸŒ“), we steer left and if the line is detected on the right (πŸŒ—), we steer right. If the line is directly underneath us (πŸŒ‘), we drive straight on.

Usage

To run a πŸ€–-program examples/line.txt on a physical mBot connected to your computer:

$ runhaskell src/Interpreter.hs examples/line.txt

To run a πŸ€–-program examples/line.txt on the built-in simulator:

$ runhaskell src/Simulator.hs examples/line.txt

Emulator

Syntax

The full syntax is described below in Extended Backus-Naur form. To make this easier to read, syntax elements of the EBNF itself have a light color, while non-terminal symbols are framed and symbols denoting whitespace have a blue background.

Syntax

Semantics

A πŸ€–-program is a StmtSeq, i.e. a sequence of one or more statements (Stmt) separated by newlines. Just like in Python, blocks are expressed by their indentation (the off-side rule). There are five types of statements:

Assignment (βͺ)

The value of the arithmetic expression (AExp) on the right of the assignment operator (βͺ) is assigned to the Identifier specified on the left hand side.

While (πŸ”)

This is a traditional while-loop. The body keeps being executed as long as the specified boolean expression (BExp) evaluates to πŸ‘.

If (❓)

This is a traditional if/else-if/else-statement. We first evaluate the boolean expression next to❓.

If this evaluates to πŸ‘, we execute the corresponding body. If this evaluates to πŸ‘Ž, we evaluate the ⁉️-conditions one-by-one and execute the body corresponding the the first condition evaluating to πŸ‘. If none of the boolean expressions evaluate to πŸ‘, the body of the❗️-branch is executed, if one is specified.

Skip (πŸ’­)

This is a comment. Any text to the right of the πŸ’­ is ignored.

Command

This is a command for the mBot (or the simulator) to execute. There are three types of command

Drive (πŸ’¨)

Start driving in the specified direction: forward (⬆️), backward, (⬇️), left (⬅️) or right (➑️).

Sleep (😴)

Sleep for the specified duration. You can pass in an arithmetic expression denoting the number of milliseconds to sleep, or use one of the built-in constants: 400 ms (πŸ•‘), 800 ms (πŸ•”), 1200 ms (πŸ•§), 1600 ms (πŸ•–) of 2 s (πŸ•™).

Light (🚨)

Sets the color of the specified LED to a specific color. The first argument denotes whether to set the left (πŸ‘ˆ) or right (πŸ‘‰) LED. The next three arguments are arithmetic expressions denoting the RGB value on a scale of 0 to 100.



In the description of statements above, we touched a few times on arithmetic and boolean expressions. Their semantics are explained below.

Arithmetic expressions

An arithmetic expression is an expression that evaluates to a whole number. Any decimal literal is a valid arithmetic expression. You can use all the traditional operators (+, -, * and /) to construct new arithmetic expressions. Furthermore, you can use one of the built-in constants: πŸŒ‘, πŸŒ“, πŸŒ— and πŸŒ• to denote 0, 1, 2 and 3 respectively. (Think about the binary representation of those numbers to see why this makes sense).

Another arithmetic expression is querying one of the built-in sensors. The distance sensor (πŸ“) returns the distance to the object in front of the mBot. The line sensor ( πŸ”­) returns the position of the line under the mBot. The value of this sensor is always between 0 and 3: πŸŒ‘ (line on both sides), πŸŒ“ (line on the left), πŸŒ— (line on the right) or πŸŒ• (no line detected).

Boolean expressions

A boolean expression is an expression that either evaluates to either true (πŸ‘) or false (πŸ‘Ž). We support OR (||) and AND (&&) to combine boolean expressions. The comparison of two arithmetic expressions (>, == and <) is also a valid boolean expression.