MAML

the Mega Awesome Microcontroller Language

MAML compiles select blocks of a Python program to bytecode and sends it to an Arduino for execution. The virtual machine running on the Arduino may be paused/resumed and its environment can be fully inspected and modified from Python as the program is running. This enables writing programs for Arduino that benefit from interactive development, friendly syntax, and close interoperability with the desktop.

The Python decorators @block(once) and @block(chain) are used to designate functions whose body will be compiled and sent to the Arduino for execution. The rest of the Python program runs as normal and may exit after sending the bytecode or keep running and provide an application that interacts with the Arduino. The bodies of these decorated functions contain a subset of the Python language with modified semantics.

Architecture


AST creation is done with python's built-in ast module. The provided ast is then transformed into a convenient form. At this stage some additional transformations are done such as detecting type declarations (The type declaration syntax is legal Python) and creating AST nodes for them.

The Arduino VM environment is partially tracked enabling the compiler to incrementally compile blocks and generate faster code. Code to be compiled and sent to the Arduino is organized into functions and blocks, in Python both are implemented with decorators. The decorator function will take the name of the function it decorates and use it to retrieve its body's previously compiled bytecode. A block object is then created to manipulate that block in python, this object helps mirror the state of the Arduino. When modifying blocks interactively, minor editor support may be needed to compile changed code before the decorated function is evaluated, this is needed because python does not provide access to a functions source code(only its bytecode).

Before sending, bytecode operands are first serialized. A modfied Arduino serial library is used that passes input bytes to a function where they are deserialized as they arrive. When the vm runs on the desktop, the bytecodes are communicated using a file instead and a signal is sent to the vm when more bytecode is available.

After bytecode is read into the Arduino and deserialized, it is immediately converted to threaded code, the operands are dispersed within this code. The virtual machine is typeless which allows it be benefit from greater speed (no type checks) and memory usage (no type tags). Internally, the codeblocks are organized into a 'blockchain' - a linked list of blocks. The blockchain is repeatedly evaluated in order. Blocks may be added, removed, or updated anytime from the Python program.

Here is an example that blinks an LED with delay proportional to a value read from a distance sensor.

This was a group final project for a languages and compilers course with Ian Gann and Michelle Ling.

The project repository is hosted here