Profile cover photo
Profile photo
Robert Krzaczek
257 followers
257 followers
About
Robert's posts

Namespaces for a #Forth environment.

I've been developing a bunch of vocabularies in ANS Forth that run on the host side of a tethered Forth system. The vocabularies are large enough that there is inevitable overlap between them. Now, in practice, reusing words for different purposes in different contexts isn't so bad in a Forth system (it might surprise you that it all works out in the end), but we ought to do better.

While I've complained about other parts of ANS Forth, the support for wordlists is really exceptional. It's too easy to cook up things like this, implementing all kinds of namespacey mechanisms.

Anyway, what I wanted was private dictionaries in which you could pick and choose words to be aliased into other dictionaries. Lisp people will recognize this as a mix of packages, export/import, and similar functionality. C++ folks will be thinking of namespaces here. What I'll describe here is a little different from those concepts, but similar enough that I've successfully developed an entire system around just a few words. It's written using ANS Forth wordlists, so there should be little problems on a modern Forth system.

with: foo ... ;with
In this, foo is added to the wordlist search order. It doesn't affect which wordlist new definitions appear in. These can be nested.

defining: foo ... ;defining
A new wordlist foo is created, and any new definitions in the ellipsis are placed into it. foo is also added to the search order.

foo alias: bar goo ... ;alias
Typically used within a defining block of a private wordlist, the words listed at the ellipsis (bar, goo) are aliased into the foo wordlist.

That's it, that's all I needed. So, how are these used in practice? Imagine you're writing a library for something, and that most of the library shouldn't be exposed to the caller; you know, like most libraries. :-) So, a few words in the library should be made available. You'll have two wordlists in this case. We can name them anything we want, so I'll choose lib as the wordlist with the words meant for public consumption, and (lib) to hold the actual implementation of the library.

defining: (lib)
...
: foo ... ;
: bar ... ;
: baz ... ;
...
lib alias: foo bar ;alias
;defining

In that, we're defining everything in a wordlist named (lib) and exporting two of those words, foo and bar, into a wordlist named lib. Then, client code can simply do this:

with: lib with: otherlib
...
;with ;with

Simple as that. Along the way, I also wrote an alternative to alias: that let's you tag an individual word definition, similar to the way you can tag words as immediate in ANS Forth. We'd define a word named, say, to-lib and just tag a definition after its semi-colon. This example here does the same as the previous example; I just prefer the syntax of the explicit aliases, rather than a per-word tagging.

defining: (lib)
...
: foo ... ; to-lib
: bar ... ; to-lib
: baz ... ;
;defining

You aren't limited to this kind of structure, either. For example, in developing the application ATF, I simply aliased all the public words of my libraries into a wordlist named atf, rather than fussing with (lib) and lib all over the place. Then, my main app code already has the public words from the different libraries already provided. It's all stylistic differences, but I really enjoy the flexibility I already have with such a minimal set of definitions. Like I said, ANS might have missed on some aspects of the system, but the wordlist stuff is great and easy to hack on.

For some months, I was/am developing a small project of my own, the main focus being a handheld medical device with certain capabilities (anyone who knows about my cardiac event in 2016 can probably make some good guesses here).

I chose to develop in a #Forth environment because I anticipated very limited resources in the device (small processor, battery power, and so on). Nothing else can get you quite the density of functionality that you can achieve with Forth systems; it really excels when resources are limited.

From there, I looked around, and decided to develop my own tethered Forth system. That is, it's actually two Forth systems. One written in ANS Forth that runs on a host system of some sort, and a second bespoke Forth system running on the target hardware. The two communicate simply enough, the host can call routines on the target (hence, the "tethered" nature of the system), and manipulate both flash, ram, and eeprom memory on the target "live", and so on. It's a fantastic approach to incremental interactive development on limited hardware.

The Forth systems for #Atmel processors didn't really suit me. Don't get me wrong, things like amforth are remarkable in their functionality and quality! Beautifully so! But, for my purposes, they dedicate too many resources to implementing the ANS Forth standard; I feel that while the standards are useful at high levels, when you drop down to bare metal, it's best to have a purpose-built dedicated system. So, I implemented my own target Forth from the host system. For the host, I chose gforth: it's free, performant, runs in a number of environments, and I have a lot of respect for its primary developers, Ertl and Paysan.

From there, I wrote an Atmel assember in Forth. That was pretty easy, as anyone who has implements assemblers in Forth will tell you. After that, to check my work and get a better look at other people's free software, I wrote a disassembler. Once that was done, I re-implemented the assembler from scratch, using all the insights I gained from disassembling other people's code ("Now, why does that work?"). It wasn't long before I had a single pass assembler that supports labels, references, and even structured assembly (if/else/then, begin/until, things like that, at the assembler level).

I have an AVR Dragon that I was writing some support for, when I decided to write some support for different file formats. Loading and saving Tektronix and Intel hex files, I might even add Motorola S-Records at some point. I decided I didn't really like the ANS Forth standard for file I/O (who does?), so then I wrote something fairly similar to a STDIO system, but Forth flavored. :-)

Along the way, everything I've developed can be easily separated from the whole system. There aren't a ton of interdependencies to manage, except where it really did make sense or make the system easier to write.

The point is, implementing a full system from scratch, rather than just little programs here and there, has taken me down some interesting roads in Forth development. I'm going to share some of the simpler parts of what I've created here in future posts. Along the way, I hope to explain not just what I've done, but why I did it, what went into the decisions, and so on.

I have to say. A tethered Forth setup, while not so common these days, was a fantastic experience. Squeezing crazy amounts of functionality out of a tiny little uC like an Atmel 328P felt good. For comparison, I look at the code generated sometimes by GCC compiling someone's C++ for an Arduino library. I understand that it works, and that it was easy for the developer, but I don't like how much space gets wasted in those environments, and for people with limited flash memory, I think there's a real use for bespoke (non-ANS) Forth systems in that arena.

Post has attachment
https://www.kickstarter.com/projects/1283576192/shriekback-live

I just learned about this... holy amazeballs.

WHY IS THIS HAPPENING NOW? If it happened when I had a proper job, I'd be throwing mad cash at this Kickstarter. But, no, it has to happen -- with only a 30 day window, no less! -- while I'm living off savings and trying to launch a new business. ARGH Argh argh...

Still, I'll find some money to scrape up for them... I hope you do, too.

Post has attachment
My new baby.
(Okay, old baby. New to me.)
happy dance

Update: Crap. This unit might be DOA. :-(
Photo

Chuck Tingle is either John Scalzi or Zoë Quinn. Probably. I think. Dammit, I was certain when I started that sentence...

Post has attachment
I switched #VPN providers a while back, and can't be happier today. Just wanted to tip my hat to AirVPN https://airvpn.org/

They compare very favorably with other providers, beating the snot out of my old provider. In retrospect, I didn't realize what I was missing. If you're looking for a provider, check them out.

FWIW, I use them 24/7 on my laptop (Win 10) no matter where I am, even when on friendly networks. I rarely have a moment where I notice it (outside the usual location-sensitive services). I've been with them about a month now.

Nothing else to add, just sharing a good experience.

So, the first order of business is cleaning up some of those old circles I used to rely on, when I used G+ so much. So much devolution... ugh. I have to imagine, though, the tinfoil industry is doing well these days.

In light of this second (third?) exodus from LiveJournal, I think I have two main options.

1. Continue as I was going. Use G+ for project and other technical posts with my identity, and use LJ as my semi-anonymous almost-private journal/blog/diary/whatever.

2. Drop LJ (and my permanent account) once and for all, use G+ for everything, and simulate a journal via a community (implying invite-only access).

Hmm...

Just something else from ATF (the Tethered #Forth environment for #AVR processors) that wasn't in the first version, but appears in this rewrite.

require atf/atmega328 require atf/attiny85

target atmega328 constant tom
target attiny85 constant jerry

tom flash with: targetwords

r12 PORTB OUT,

;with

jerry flash with: targetwords
r6 PORTB OUT,
;with

Super simple-but-fun hacks. Even though PORTB is a simple constant, the value assembled into the OUT instruction varies as different targets are used. Also, the assembler knows the difference between port and register addresses, so there's none of this PORTB and (PORTB) nonsense that you see new users fight with. Constants are rendered in the appropriate context; this is true for both the assembler and the disassembler.

So, yes... I left Facebook almost two months ago. Fresh air...

I'm restarting here, and over on LiveJournal as well. G+ will be for technical posts, and LiveJournal will be more diary-oriented things. In other words, G+ is definitely for public consumption, while LJ is just more personal junk that I need to write down, not necessarily for other people to read.
Wait while more posts are being loaded