lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]



2016年2月14日 下午2:24,"Dirk Laurie" <dirk.laurie@gmail.com>写道:
>
> 2016-02-14 7:01 GMT+02:00 Derek Bailey <dbaileychess@gmail.com>:
> > If func(x) returns multiple values and you do
> >
> > return func(x), something_else()
> >
> > it is going to adjust the func(x) it to a single value.
> >
> > I am curious if this adjustment happens before or after the call to
> > "something_else". If it gets resolved before, the something_else can be a
> > proper tail call, otherwise it won't be a true tail call because the
> > arguments have to get adjusted and therefore the stack frame must be
> > preserved.
>
> For that sort of question, I don't bother reading manuals or  C source[1],
> I just use luac.
>
> $ luac -l -p -
> return func(x), something_else()
>
> main <stdin:0,0> (5 instructions at 0x1091780)
> 0+ params, 2 slots, 1 upvalue, 0 locals, 2 constants, 0 functions
>     1    [1]    GETTABUP     0 0 -1    ; _ENV "func"
>     2    [1]    GETTABUP     1 0 -2    ; _ENV "x"
>     3    [1]    CALL         0 2 2
>     4    [1]    GETTABUP     1 0 -3    ; _ENV "something_else"
>     5    [1]    CALL         1 1 0
>     6    [1]    RETURN       0 0
>     7    [1]    RETURN       0 1
>
> The adjustment of func(x) happens at the moment that the
> preparation for calling something_else() is made, when Slot 1
> is clobbered by GETTABUP 1 but Slot 0 stays intact. It's
> beautiful. The slot into which the function went is the one
> that keeps the single value. The stack is balanced with no
> need to know the number of return parameters.
>
> But that does not imply that you can have a tail call
> to something_else because one return value is on the
> stack below it. Even if func(x) returns nothing, there is nil.
> Tail call means that the return values of the called routine
> are precisely those of the tail-called routine.
>
> Compare with
>
> $ luac -l -p -
> return something_else(func(x))
>
> main <stdin:0,0> (7 instructions at 0x1c4d780)
> 0+ params, 3 slots, 1 upvalue, 0 locals, 3 constants, 0 functions
>     1    [1]    GETTABUP     0 0 -1    ; _ENV "something_else"
>     2    [1]    GETTABUP     1 0 -2    ; _ENV "func"
>     3    [1]    GETTABUP     2 0 -3    ; _ENV "x"
>     4    [1]    CALL         1 2 0
>     5    [1]    TAILCALL     0 0 0
>     6    [1]    RETURN       0 0
>     7    [1]    RETURN       0 1
>
> [1] Of course, you need to have read the comments in lopcodes.h
> at some stage!
>

The OP_TAILCALL doesn't use C field, so it's possible to make a patch to support this usage