68 lines
3.0 KiB
Plaintext
68 lines
3.0 KiB
Plaintext
|
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 <i>like</i> 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:
|
||
|
|
||
|
<code class="codeblock">struct Object {<br>
|
||
|
Type type;<br>
|
||
|
union {<br>
|
||
|
...<br>
|
||
|
};<br>
|
||
|
Object *forward;<br>
|
||
|
}</code>
|
||
|
|
||
|
<h2>The Tag</h2>
|
||
|
|
||
|
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!
|
||
|
|
||
|
<h2>The Union</h2>
|
||
|
|
||
|
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!
|
||
|
|
||
|
<h2>C</h2>
|
||
|
|
||
|
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
|
||
|
|
||
|
2020-09-01
|