Splot Automation Expressions

Pairing transforms are specified using Splot Automation Expressions, a specialized postfix (Reverse polish notation) language that is expressed as a string. The language was designed to be expressive yet simple to implement on highly-constrained devices.

For pairing transformations, the value being transformed is initially pushed onto the stack and the last value on the stack after evaluation is the output fo the expression.

The syntax is somewhat similar to forth, but unlike forth all numeric values are considered floating-point.

For example, the following transform would apply to source values before they are applied to the destination:

  • "2 ^" (or "DUP *")

If the pairing was bidirectional, then the reverse transform for the above expression would be:

  • "0.5 ^"

In this case we are raising x to the power of 0.5, which reverses raising it to the power of two from the forward transform.

This example was fairly simple, but much more complex transforms are possible. For example, the infix expression (cos(x/2 - 0.5) + 1)/2 would become "2 / 0.5 - COS 1 + 2 /". (Note that currently, the trigonometric operations use turns instead of radians)

In cases where an expression is used on an input, the previous input can be pushed on the stack using v_l. This allows for things like edge detection and determining the direction of a change. For convenience, the current input can also be pushed onto the stack using v.

The ability to handle arrays and dictionaries is also specified. For example, imagine that we have a color light and a text display. Our goal is to display the approximate correlated color temperature (CCT) of the light on the text display in Kelvin. However, in this example, the color light only gives us the CIE xy chromaticity coordinates in the form of an array with two floating point values. We can start by creating a pairing between the CIE xy coordinates and the text display value. To get the right transformation expression, we first have to have the infix expression:

  • CCT(x, y) = -449n³ + 3525n² - 6823.3n + 5520.33
  • where n = (x − 0.332)/(y - 0.1858)

By using the POP operation to remove the last item from an array on the stack and push that value onto the stack, we end up with the following expression:

POP 0.1858 -
SWAP POP 0.3320 -
SWAP DROP SWAP /
-449 3525 -6823.3 5520.33 POLY3

Arrays can be built by pushing values onto the stack and invoking one of the array creation operators:

  • [] Pushes an empty array onto the stack.
  • [1] Pops the last value off of the stack, puts it into an array, and pushes that array onto the stack.
  • [2] Pops the last two values off of the stack, puts them into an array, and pushes that array onto the stack.
  • [3] Pops the last three values off of the stack, puts them into an array, and pushes that array onto the stack.
  • [4] Pops the last four values off of the stack, puts them into an array, and pushes that array onto the stack.

Dictionaries (json "objects") can also be read and written. The following expression calculates the vector length for an input vector specified as {"x":12,"y":14}:

:x GET DUP * SWAP :y GET DUP * SWAP DROP + 0.5 ^

A dictionary can be created by putting it together value-by-value. For example, the following expression takes an input of "turns" and converts that to a vector:

{} OVER COS :x PUT OVER SIN :y PUT

If you wanted to do something similar with arrays, you have two options:

  • [] OVER COS PUSH OVER SIN PUSH
  • DUP COS SWAP SIN [2]