Solving the Shortcut Dilemma

Pointers are always a pain. I have found the only safe ways to work with them that both avoids memory leaks and segfaults. Unfortunately, there are some things lost that even ruin some expectations in Copper.

Consider the following code:

some.address.a.b = { super.c = 10 }
d.e ~ a.b
d.e:

What is the value stored in “some.address.a.c”? If you guessed 10, you’d be wrong. It’s empty function. The number 10 is stored in “d.c”. While this behavior is perfectly fine on its own and has its uses, it does beg us to wonder how we could refer specifically to “a” from within the function “b”. On the one hand, we could try to create a cyclic loop of reference (which is harmless in Copper):

some.address.a.b.a ~ some.address.a

However, this can be a bit tedious after awhile. You could shorten it somewhat like this:

a ~ some.address.a
a.b.a ~ a

This is the fastest way to create the loop of reference, and it works fine. However, what if we have to refer to the variable by name? Second, what if we want to pass the pointer to something other function and call it from there? The issue arises primarily with the system function “member”. Consider the following, building on the above example:

m ~ member(a, "b")
m:

Calling “m” results in the variable “super” being created in the scope of “m” and containing a member “c” with the value of 10. We would rather that it cause “a.c” to store 10. So how do we set the “super” variable to the original source? If we can’t set it, then it becomes useless here, and an enormous amount of work lies ahead involving saving a fragile chain of pointers. Needless to say, that would be a mess.

I considered a number of alternatives, including saving and calling variable addresses directly – something I might do anyways. However, for this particular problem, a very simple solution exists: a system function that sets the super variable for us. This has the extra advantage of being general purpose since it doesn’t care where the variable comes from. Let’s give it a short name no one is ever likely to use as a variable name: “xwsv” or “execute with super variable”. I’ve never read a variable named “xwsv”, so I think it’s safe to assume it’ll rarely conflict with a user’s choice in variable names. Three letter names are more of a problem.

How it works is pretty simple: Pass in two addresses: one that should be the super and one that is meant to be called.

xwsv( a.b, c.d )

Thus, the member call problem is solved like so:

m ~ member(a, "b")
xwsv(a, m)

It might even be more convenient if either of the arguments could be a address name, but – aside from the issue of this slowing down the code – leaves us wondering whether the string would refer to a global address, a local address, both, or a member address. Having it access variables in the conventional way would be expected, but at that point, it might be better to have a function that finds a function from a string. We’ll call this “avbn” (“access variable by name”) or “avvn” (“access variable via name”).

v ~ avvn("a.b.c")
v:

This can then be used in tandem with the super-setter function:

rv ~ avvn("a.b")
xwsv(rv, member(rv, "c"))

Problem solved. Wait a second! What about passing arguments? Those can be passed along too!

xwsv(rv, member(rv, "c"), arg1, arg2)

The implementation of “xwsv” was fairly easy since it reused a quite a bit of well-tested existing code. Duplicate code is a small price to pay for a much-needed feature.
Consequently, whenever you need to pass along a pointer, you can use a simple structure that stores both the super and the variable being called:

SPtr = [
	_super, _caller,
	call = {
		ret( xwsv(super._super, super._caller) )
	}
] {
	this._super ~ _super
	this._caller ~ _caller
}

Usage:

ptr = SPtr(a b)
ptr.call: # Calls a.b #

Now isn’t that easy?

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s