
PunyForth: Forth inspired programming language for the ESP8266 - dentrado
https://github.com/zeroflag/punyforth
======
progman
I'm reminded of my good old Forth times (6502 on Commodore PET), and I'm glad
that Forth gets the increasing attention which it actually deserves.

I don't know if there is any other programming environment at all where you
can have a extensible programming language, editor, compiler, interpreter,
debugger, libs, and interactive shell in a few KB.

~~~
shakna
As much as I like Forth, it isn't the only player in the restricted memory
arena. Several models of the Commodore PET came with 32kb of RAM, and 18kb of
ROM. Here are some that reflect similar requirements.

uLisp [0], 2kb of RAM, and 32kb to store the interpreter in. You can write
programs at the REPL, and burn them into the EEPROM.

TinyBASIC [1], since dead, is a port of the version of BASIC that used to run
on the Altair 8800, which was an even more constrained system than most PETs!
Altair BASIC could run on 4kb of RAM.

Python-On-A-Chip [2], is a subset of Python. At a guess, from the supported
platforms, it can run on around 2kb of RAM.

iArduino [3], is a C interpreter that can run in 2kb of RAM.

MicroPython is looking to come to the ESP8266 [4], which is much, much bigger
at 512kb. Which basically makes it the fattest of these, and impossible to run
on something like the PET.

Bitlash is a completely new language [5], and can run on 2kb of RAM, and takes
up surprisingly little storage space.

All of these languages offer at least a REPL, as well as compatibility with a
wide range of libraries, and most have at least traceback and exception
support.

This is not to say Forth is a bad choice! It works great in tiny memory, with
better support for a full language specification than many other languages.

But not everyone wants a Forth... And there are plenty of choices out there.

[0] [http://www.ulisp.com/](http://www.ulisp.com/)

[1] [http://hackaday.com/2011/08/28/basic-programming-on-an-
ardui...](http://hackaday.com/2011/08/28/basic-programming-on-an-arduino/)

[2] [https://github.com/jsnyder/python-on-a-
chip](https://github.com/jsnyder/python-on-a-chip)

[3]
[http://n.mtng.org/ele/arduino/iarduino.html](http://n.mtng.org/ele/arduino/iarduino.html)

[4]
[https://github.com/micropython/micropython/tree/master/esp82...](https://github.com/micropython/micropython/tree/master/esp8266)

[5]
[https://github.com/billroy/bitlash/wiki](https://github.com/billroy/bitlash/wiki)

~~~
progman
Yes, there are plenty of options. However, most of those options lack
something while Forth is all-inclusive. All your options have no compiler
while Forth compiles to threaded code which is pretty fast, about 1/10 the
speed of assembler according to my experience. Your options have a linear
space consumption while Forth code compiles "logarithmic" due to its
extensible vocabulary. That means, if you have an 8K system (like on my former
PET-2001) you need 4K for a convenient basic Forth for instance, while you can
put a lot more stuff in the other 4K, due to the threaded code.

~~~
shakna
Well, TinyBASIC was available as both an interpreter, but more often, as a
compiler.

Though it was a primitive compiler compared to today, due to the size of the
language, it easily fit within 2-3kb, which on your 8kb system, would leave
5kb or more for program memory.

In fact, some TinyBASIC systems had a virtual machine and JIT compiler in 120
instructions, or around 2kb, as early as 1964.

Though BASIC is slower than Forth, or was in those days, the main benefit is
instant availability. BASIC syntax was the jumping on point for more than a
few programmers, myself included, because of it's simplicity.

------
tines
This is fantastic! Forth's simplicity is a great fit for exploratory
programming on resource-constrained systems, and I'm a fan of anything
homoiconic.

Maybe one day I'll get my dream of having a forth or lisp with the type system
of haskell.

~~~
jstimpfle
Aren't these conflicting ideas? To me a big advantage of dynamic type systems
is that specifying behaviour and specifying what parts of the behaviour are
statically computed are separate tasks.

~~~
thurn
Yes. For example, the powerful "transducers" concept from Clojure essentially
cannot be represented in the Haskell type system.

~~~
eru
Here's an attempt: [http://hypirion.com/musings/haskell-
transducers](http://hypirion.com/musings/haskell-transducers)

------
reikonomusha
This is great work. I was expecting a toy Forth, but this one is pretty
serious. I was happy to see quotations, immediate words, and Factor-style
combinators.

------
afeezaziz
I am wondering why the team from mbed has not made an attempt to make ESP8266
compliant with mbed. Yes, I understand that the architecture is totally
different but just that I like mbed so much so that I want to see it used in
more hardware.

~~~
jakobdabo
The "team from mbed" is employed by ARM.

------
jakobdabo
Great work indeed. Does it support the new ESP32 processors?

~~~
aseipp
The ESP32 also uses an Xtensa, the LX6, which should have the same basic
instruction encoding, etc (and I think they both use FreeRTOS, as well, but I
only have an ESP32). Probably shouldn't be too hard. You can also stuff more
functionality into it, too.[1]

[1] Related: I can't actually even _find_ the documentation on what's
precisely changed between the LX6 (ESP32) and the LX106 (ESP8266), other than
the basics on the datasheets - I don't know of any documentation on e.g. any
different architectural details. Maybe you have to ask Espressif. Or Cadence.
Anyone have any idea?

~~~
jakobdabo
Their datasheets only mention the PIN definitions and electrical
characteristics of the microcontrollers. Try to get the information from the
reference manual[0]. Also there are these books[1][2] by Neil Kolban.

[0]
[https://www.espressif.com/sites/default/files/documentation/...](https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf)

[1] [https://leanpub.com/ESP8266_ESP32](https://leanpub.com/ESP8266_ESP32)

[2] [https://leanpub.com/kolban-ESP32](https://leanpub.com/kolban-ESP32)

edit:

More information about the differences: [http://www.cnx-
software.com/2016/03/25/esp8266-and-esp32-dif...](http://www.cnx-
software.com/2016/03/25/esp8266-and-esp32-differences-in-one-single-table/)

~~~
aseipp
The ESP32 datasheet is really woefully inadequate for this part; it mostly
describes the chip, but I guess what I'm really looking for is things like "A
description of the ISA itself", i.e. the "LX6 datasheet", so to speak. So I
want something like the the actual instruction encoding, instruction listing,
etc for the LX6 series and what it supports precisely.

------
StavrosK
Why can't we get Rust for the ESP8266? :( I really dislike C, I'd love a
higher-level language. As great as MicroPython is, the interpreter needs too
much RAM, and I think Rust would be a great alternative.

~~~
dbcurtis
Isnt there an axpetimental Rust backend for ARM Cortex? ISTR seeing it
discussed here.

~~~
masklinn
Rust has Tier 2 support[0] for ARMv6 to ARMv8 and Tier 3 support[1], so there
are experimental limited[2] backends for the various Cortex in Tier 3.

 _However_ the ESP8266 is built around Tensilica's Xtensa, not ARM's Cortex.
There currently is no support whatsoever for Xtensa in LLVM (let alone in
Rust).

Current microcontroller work is on MSP430[3] with work being planned for Amtel
AVR[4] since the AVR branch was merged into LLVM in November 2016. Xtensa is
quite literally nowhere[5].

[0] guaranteed to build & binaries provided but tests are not automatically
run

[1] supported in the codebase but no guarantees that it even builds

[2] only Core, no standard library

[3] [https://github.com/rust-embedded/rfcs/issues/20](https://github.com/rust-
embedded/rfcs/issues/20)

[4] [https://github.com/rust-embedded/rfcs/issues/3](https://github.com/rust-
embedded/rfcs/issues/3)

[5] [https://github.com/rust-embedded/rfcs/issues/2](https://github.com/rust-
embedded/rfcs/issues/2)

~~~
dbcurtis
>However the ESP8266 is built around Tensilica's Xtensa, not ARM's Cortex.

 _DOH!_

I have to say, though, that having the AVR code generator merged is very cool.
At one time I was a big user of avr-gcc and remember when the AVR LLVM effort
was just getting started. I haven't been following it, though.

One of the annoyances with gcc is that the optimizer kept wanting to use code
motion to relocate the interrupt disable instruction to the beginning of the
function it was found in. The only way to keep the optimizer from doing that
would have been to make the instruction depend on all of RAM, which would
effectively disable optimization for any function that disabled interrupts. So
coding critical sections required a bit of jiggery-pokery to keep the
optimizer from breaking your code. I hope the LLVM back-end found a way around
that.

