Jade and ad hoc data: progress

The Meet Jade and Ad hoc structure articles introduced a dataflow approach in software for – but not limited to – embedded microcontrollers. And I’ve been making substantial progress with this, lately.

The big picture#

The idea is simple: apps are built using modules which send messages to other modules.

  • Every module receives messages on its inlet(s) and sends messages to its outlet(s).
  • By defining a set of wires, each outlet can be connected to the inlets of other modules.
  • Each message send blocks until it has been processed by all its recipient(s).
  • Message sends do not return results (there might be no recipient, or more than one).
  • Modules don’t know how they’re wired up: they receive messages and send them as needed.
  • Jade is based on C++, each module is a C++ object.

Terminology#

In Jade, a module is called a gadget. Incoming messages will call the gadget’s trigger() method. Every gadget can send messages by calling its emit() method.

A new gadget can be created by wiring existing gadgets together: this is called a circuit. Circuits also have inlets and outlets, and are essentially indistinguishable from C++ gadgets.

Messages#

Jade messages are lightweight ad hoc data structures. And they are ephemeral: created on-the-fly when a gadget calls emit() and cleaned up when that gadget returns from its trigger() call. This matches the “call tree” structure implicit in Jade’s processing and forwarding of all message sends.

A simple serialisation mechanism has been implemented: this turns structured messages into byte arrays (and back). Gadgets can store these in the heap for later or save them to persistent storage.

Serialised messages can also be sent to other Jade-aware devices or hosts. There is a simple mux.py script which can be used as pub-sub switchboard for messages up to 250 bytes.

Building apps#

One way to develop an app with Jade is to build it up from existing gadgets and circuits, and then replace any parts which need specific functionality (or extra performance) with C++ versions. This will need a decent set of general-purpose base gadgets and circuits to become practical.

The core of Jade is platform-independent: it works on embedded µCs as well as “native” host machines. This opens up another avenue for embedded development: create dummy gadgets for hardware-specific functionality and develop most of the logic on a desktop or laptop computer.

Jade apps consist of a mix of code and data: C++ gadgets need to be compiled and uploaded as firmware, including all runtime libraries they depend on. But the circuit definitions, i.e. gadget setup and wiring, are data: they could be sent over a serial port to fully define the actual application. If kept in RAM, they can be re-sent as needed, leading to much quicker development cycles. At some point the “final” app will need to be stored in flash memory as well, so that it becomes a “turnkey” setup.

So what’s the point?#

The main goal of Jade, is to add scripting-like flexibility to top-down development, while keeping compiled C++ performance in bottom-up development.

The Jade core is a single jade.h header (1800 lines as of March 2026). Message send overhead is just a few data structure traversals to turn emit() method calls into trigger() method calls. There’s no virtual machine (yet?).

The missing piece#

The task of “wiring together an app from existing pieces” is still a bit tedious, because there is currently no graphical editor like the software implementations after which Jade is modeled: Pure-data and Max/MSP.

The other glaring limitation is that Jade is still under massive development: calling this “alpha-grade” software would be presumptuous. There are no docs, there is only … some source code.