Mercerenies / gdlisp

Lisp on the Godot platform
GNU General Public License v3.0
141 stars 1 forks source link

`access-slot` could be a function #32

Open Mercerenies opened 3 years ago

Mercerenies commented 3 years ago

Right now, access-slot is a special form. But it's pretty close to being a function. I suggest that, rather than having foo:bar expand to

(access-slot foo bar)

as it currently does, we change it to

(access-slot foo 'bar)

And that can get compiled via call magic into the same GDScript it would have before.

Pros:

Cons:

Note: I have tested setget and it still triggers even if you use the direct [] syntax. So having access-slot as a function which does foo["bar"] internally but gets magicked away 99% of the time does not create any inconsistencies, as both foo["bar"] and foo.bar call a setget trigger if one exists.

Mercerenies commented 1 year ago

There's more complexity here than I thought. There is a branch implementing this feature, but several tests fail. The specific problem is copy-on-write data structures.

Currently, when we have something like

(set foo:bar baz)

We're smart enough to see that bar on foo is being modified, so we (pessimistically) assume foo is being mutated, setting its access type to RW. If we could ascertain for certain that foo was a reference or node type, then this wouldn't be necessary, but if foo is a copy-on-write (Cow) type like Vector2, then we have to consider this a write to the variable directly. And that's where the problem comes in. With the proposed fix to turn access-slot into a function, we have

(set foo:bar baz)

desugars to

(set-access-slot baz foo "bar")

and now we actually are passing foo as an argument to a function, which trips up Cow behavior and ends us up with two copies of the data. That is to say, ignoring call magic and other shenanigans, set-access-slot is actually, by Godot's rules, not a function, since a function would necessarily copy the data in a Cow argument and not mutate the original.

So where does that leave us? An argument could be made to forgo this adventure and just call access-slot a special form with special behavior. Or we could look into making set-access-slot a macro. I'm 80% sure that macros can trigger after (set ...) expands, and turning it into a macro would work, but at that point have we really gained anything?

Since there's added complexity, I'm deferring to 2.x.

Mercerenies commented 1 year ago

I'm 80% sure that macros can trigger after (set ...) expands

This is false, at least in the current version of the code. Could probably be fixed, but it is not true right now.