What is it with pointers?

Listen, if I had to pick a language to write a decent program in, I'd want to use something like Rust. It behaves in more or less all the sane ways I want a language to behave. Python's nice and quick for Python-y stuff, and Javascript is Javascript, etc. But for some reason, I just like C.

I've written something of an implementation of Lisp for my Pebble smartwatch, which I named PebbLisp. I'd love to have written it in Rust, to get some more practice with it, but it was a real pain in the tookus to get compiling for the watch, and I gave up. So, C.

I'll never act like C is a perfect language. Many, many, stupid memory leaks could've been avoided with something smarter. For some reason, though, it's just fun to work with. PebbLisp involves some dancing about with pointers, and includes a homegrown tagged-union setup. There are parts that are probably very ugly to more practiced eyes, and correcting unexpected behavior is a nightmare, but coding it leaves me downright giggly sometimes.

The Object struct in PebbLisp has three parts:

struct Object {
    Type type;
    union {
        ...
    };
    Object *forward;
}

The Tag

The first part is the Type of the Object. This is just an enumeration with all the possible types that a PebbLisp object can be. It's the tag of our tagged union. Already I like it far more than is warranted. One number is a front for every possible type? Incredible!

The Union

The second part is, of course, the union itself. I've cut it out here, but there are members of the union for integers, pointers to strings, function pointers, etc. Unions are also something I treasure. The famous issue with unions is trying to keep track of what state any given union is actually in, and god help you should it ever be interpreted incorrectly. That's why it's fun, though. Coding a consistent way to access a union feels like cracking open the secret door of programming.

The Pointer

Finally, Object *forward: something that traditionally might be named cdr (which I had to look up, because I'm really not enough of a Lisp guy). In Lisp, everything is a list. An object with forward == NULL is a list of length 1. An object that points to another object is a list of length 1 + listLength(forward), aka itself plus the rest of the list.

So much code in PebbLisp is dedicated to making sure that this value is never incorrect, duplicate, or useless. A cloneObject() function exists largely because copies of individual objects can't keep this address. I'd love to use our friendly neighborhood assignment operator: =, but C doesn't allow operator overloading. But cloneObject() was fun to write, somehow!

C

Anyway, this has already run too long. Point is, C doesn't care what you do with data. And for some reason, it's fun to redo decades of other people's work in a project no one asked for. I highly recommend it.

#100DaysToOffload