Open Mercerenies opened 3 years 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.
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.
Right now,
access-slot
is a special form. But it's pretty close to being a function. I suggest that, rather than havingfoo:bar
expand toas it currently does, we change it to
And that can get compiled via call magic into the same GDScript it would have before.
Pros:
access-slot
directly to do reflectionCons:
(foo:bar 1 2 3)
? Do we still special-case it, or do we provide the possibility to override the call syntax?Note: I have tested
setget
and it still triggers even if you use the direct[]
syntax. So havingaccess-slot
as a function which doesfoo["bar"]
internally but gets magicked away 99% of the time does not create any inconsistencies, as bothfoo["bar"]
andfoo.bar
call asetget
trigger if one exists.