lua-users home
lua-l archive

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


On 2 July 2010 15:45, Mark Hamburg <mark@grubmah.com> wrote:
> Since LuaJIT doesn't do much to optimize ... and I suspect (but haven't confirmed) that it's also less performant for the main Lua distribution, it would be useful to have introspection support for finding out how many parameters a function takes plus whether or not it takes varargs. This could then be used in code generation logic to replace ... with an appropriate number of explicitly named parameters. For example, the following:
>
>        function concat( f, g )
>                return function( ... ) return f( g( ... ) ) end
>        end
>
> Can probably be more efficiently written in the case where g takes only one parameter as:
>
>        function concat1( f, g )
>                return function( x ) return f( g( x ) ) end
>        end
>
> With appropriate introspection we could detect this in the implementation of concat.
>
> This information all looks to be readily available, so it's mostly just a matter of specifying the API. I haven't figured out whether one should make a proposal for such things, provide a proposal with an implementation, or just wait to see how Roberto responds. ;-)
>
> (Slightly more difficult because I don't think the compiler tracks this would be tracking the number of return values. Again this could be useful for writing generic wrappers that tuned to their particular use cases.)
>

Someone asked for this a while back in IRC, but disappeared before I
finished writing a solution. It works only in stock 5.1 (not LuaJIT as
far as I know) and uses bytecode inspection, so while not the solution
you're after I guess it's still applicable to this thread.

function nparam(f)
        local chunk, err = string.dump(f);
        if not chunk then return chunk, err; end
        local int_size, sizet_size = chunk:sub(8, 9):byte(1,2);
        local namelen_bytes = chunk:sub(13, 13+sizet_size);
        if chunk:sub(7,7):byte() == 0 then
                namelen_bytes = namelen_bytes:reverse();
        end
        namelen_bytes = {namelen_bytes:byte(1, sizet_size)};
        local namelen = 0;
        for i=1,sizet_size do
                namelen = namelen + namelen_bytes[i]*256^(i-1);
        end
        local locals_pos = 14+(int_size*2)+sizet_size+namelen;
        local nparam, is_vararg = chunk:byte(locals_pos, locals_pos+1);
        return nparam, is_vararg ~= 0;
end

It returns firstly the number of parameters, and secondly either
true/false according to whether the function takes varargs.

Matthew