Order of metatable accesses

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Order of metatable accesses

Joseph C. Sible
Consider this Lua program:

local x = {
    a = setmetatable({}, {__newindex = function(t, k, v)
        print('setting a.' .. k)
    end}),
    b = setmetatable({}, {__newindex = function(t, k, v)
        print('setting b.' .. k)
    end}),
    c = setmetatable({}, {__index = function(t, k)
        print('getting c.' .. k)
    end}),
    d = setmetatable({}, {__index = function(t, k)
        print('getting d.' .. k)
    end})
}
setmetatable(_G, {__index = function(t, k)
    print('getting ' .. k)
    return x[k]
end})
a.foo, b.bar = c.baz, d.qux

When I run it, it prints this:

getting a
getting b
getting c
getting c.baz
getting d
getting d.qux
setting b.bar
setting a.foo

How much of the ordering of these metatable accesses is guaranteed? It
looks like it does all of the __index calls left-to-right and then all
of the __newindex calls right-to-left. But the only thing I see in the
manual is "The assignment statement first evaluates all its
expressions and only then the assignments are performed." Should the
manual make a stronger statement, or is what it says all that's
guaranteed and the other ordering I noticed just an implementation
detail?

Joseph C. Sible
Reply | Threaded
Open this post in threaded view
|

Re: Order of metatable accesses

Luiz Henrique de Figueiredo
> But the only thing I see in the
> manual is "The assignment statement first evaluates all its
> expressions and only then the assignments are performed." Should the
> manual make a stronger statement, or is what it says all that's
> guaranteed and the other ordering I noticed just an implementation
> detail?

Which other ordering? It works as advertised: if evaluates c.baz and
d.qux before assigning to b.bar and a.foo.
Oh, you mean the order of the assignments are performed? The manual
purposely avoids saying anything about this; it's just an
implementation detail.

You don't need a complicated example. Here is a simpler one:

% cat a
a,b=c,d
%luac -p -l  a
1 [1] GETTABUP 0 0 -3 ; _ENV "c"
2 [1] GETTABUP 1 0 -4 ; _ENV "d"
3 [1] SETTABUP 0 -2 1 ; _ENV "b"
4 [1] SETTABUP 0 -1 0 ; _ENV "a"

which reads: getblobal c, getglobal d, setglobal b, setglobal a.
Reply | Threaded
Open this post in threaded view
|

Re: Order of metatable accesses

Soni "They/Them" L.


On 2020-11-16 7:04 p.m., Luiz Henrique de Figueiredo wrote:

> > But the only thing I see in the
> > manual is "The assignment statement first evaluates all its
> > expressions and only then the assignments are performed." Should the
> > manual make a stronger statement, or is what it says all that's
> > guaranteed and the other ordering I noticed just an implementation
> > detail?
>
> Which other ordering? It works as advertised: if evaluates c.baz and
> d.qux before assigning to b.bar and a.foo.
> Oh, you mean the order of the assignments are performed? The manual
> purposely avoids saying anything about this; it's just an
> implementation detail.
>
> You don't need a complicated example. Here is a simpler one:
>
> % cat a
> a,b=c,d
> %luac -p -l  a
> 1 [1] GETTABUP 0 0 -3 ; _ENV "c"
> 2 [1] GETTABUP 1 0 -4 ; _ENV "d"
> 3 [1] SETTABUP 0 -2 1 ; _ENV "b"
> 4 [1] SETTABUP 0 -1 0 ; _ENV "a"
>
> which reads: getblobal c, getglobal d, setglobal b, setglobal a.

"hmm this looks like it'd cause issues with <close>"

$ luac -l -l -o /dev/null -
local a <close>, b <close> = c, d
luac: stdin:1: multiple to-be-closed variables in local list

well then, nvm :)
Reply | Threaded
Open this post in threaded view
|

Re: Order of metatable accesses

Dibyendu Majumdar
In reply to this post by Luiz Henrique de Figueiredo
On Mon, 16 Nov 2020 at 22:04, Luiz Henrique de Figueiredo
<[hidden email]> wrote:

>
> > But the only thing I see in the
> > manual is "The assignment statement first evaluates all its
> > expressions and only then the assignments are performed." Should the
> > manual make a stronger statement, or is what it says all that's
> > guaranteed and the other ordering I noticed just an implementation
> > detail?
>
> Which other ordering? It works as advertised: if evaluates c.baz and
> d.qux before assigning to b.bar and a.foo.
> Oh, you mean the order of the assignments are performed? The manual
> purposely avoids saying anything about this; it's just an
> implementation detail.
>

That's interesting. I thought there was a reason for right to left assignment.

I think the implementation is slightly more complex than the manual
states... if I recall correctly:

The LHS expressions are evaluated first but not resolved (because we
don't know if it is load or store on tables)
Then the RHS expressions are evaluated and values stored in temporaries?
Finally the LHS expressions are assigned values from the temporaries
(right to left).