4 ms·
I've worked extensively with functional programming on tiny microcontrollers like the Arduino. I created a research language called Juniper[1], which is a Haske
by calebh 8y ago
I've worked extensively with functional programming on tiny microcontrollers like the Arduino. I created a research language called Juniper[1], which is a Haskell/F#-like language targeting the Arduino.
As you mentioned, the memory size and the program size are the biggest two constraints. There's no space for a garbage collector, and everything has to be allocated on the stack. It turns out that it is possible to make the entire thing stack-free. The two biggest hurdles are function closures, arrays, and recursive data types.
Function closures are typically allocated on the heap since it's possible to return functions from other functions. The solution is to include the closure as part of the function type, which means that they can then be allocated on the stack. Arrays are a bit more tricky to allocate on the stack. My solution is to statically size arrays with type level natural numbers, which means that the sizes are known at compile time.
Recursive datatypes are a problem that I have not dealt with yet. In most Arduino projects recursive datatypes are not really used, so I just don't allow them. It might be possible to use type level natural numbers to put a bound on recursion depth. Another idea I had was to use run-timed size datatypes. For example, let's say you have a function F1 which calls F2. The frame pointers for their corresponding frames are at S1 and S2. When F2 returns a value of size N, the solution is to copy the value to a scratch space, return to F1, decrement the frame pointer, and then copy the value back into the stack frame. I'm not sure if this is really suitable for embedded systems since it's a lot of code/machinery which takes up precious program space.
Rust is a great language which can work around these issues due to its linear types. I'm looking forward to using Rust once it starts to support the Arduino microcontrollers.
[1]: http://www.juniper-lang.org/ http://www.juniper-lang.org/
- naasking 8y agoVery cool! Hadn't heard of Juniper before. Do you use something like regions to group and inline memory allocations?
- calebh 8y agoIn the next version of Juniper everything will be moved over to purely stack based allocation. Currently only function closures and refs are allocated on the heap. The refs are only created once when the program initializes itself, so that isn't an issue. The closures will become part of the function type. The FRP model works very well for the Arduino platform since you're essentially modelling a data-flow from input to output devices. Currently the compilation target is C++, which means that the Juniper compiler doesn't have a ton of control over the final assembly code.
- naasking 8y ago> The closures will become part of the function type. Can you elaborate? Do you mean something like closures and function pointers will be distinguished, with closures essentially being something like an existential package paired with a function pointer? ie. ∃'x.'x * 'a -> 'b