Module:Arguments: Difference between revisions

    From Nonbinary Wiki
    m>Mr. Stradivarius
    (fix undefined next() behaviour bug by checking for metatable.donePairs in the __index metamethod; also, format the module so it fits into 80 characters)
    m>Mr. Stradivarius
    (memoize nils using a separate nilArgs table; this fixes a bug where nil values were being iterated over with pairs())
    Line 7: Line 7:


    local arguments = {}
    local arguments = {}
    local nilArg = {} -- Used for memoizing nil arguments in metaArgs.


    -- Generate four different tidyVal functions, so that we don't have to check the
    -- Generate four different tidyVal functions, so that we don't have to check the
    Line 76: Line 74:
    luaArgs = frame
    luaArgs = frame
    end
    end
     
    -- Set up the args and metaArgs tables. args will be the one accessed from
    -- Set the order of precedence of the argument tables. If the variables are
    -- functions, and metaArgs will hold the actual arguments. The metatable
    -- nil, nothing will be added to the table, which is how we avoid clashes
    -- connects the two together.
    -- between the frame/parent args and the Lua args.
    local args, metaArgs, metatable = {}, {}, {}
    local argTables = {fargs}
    setmetatable(args, metatable)
    argTables[#argTables + 1] = pargs
    argTables[#argTables + 1] = luaArgs


    --[[
    --[[
    Line 113: Line 112:
    end
    end
    end
    end
    --[[
    -- Set up the args, metaArgs and nilArgs tables. args will be the one
    -- accessed from functions, and metaArgs will hold the actual arguments. Nil
    -- arguments are memoized in nilArgs, and the metatable connects all of them
    -- together.
    --]]
    local args, metaArgs, nilArgs, metatable = {}, {}, {}, {}
    setmetatable(args, metatable)


    local function mergeArgs(iterator, tables)
    local function mergeArgs(iterator, tables)
    Line 124: Line 132:
    for _, t in ipairs(tables) do
    for _, t in ipairs(tables) do
    for key, val in iterator(t) do
    for key, val in iterator(t) do
    local metaArgsVal = metaArgs[key]
    if metaArgs[key] == nil then
    if metaArgsVal == nil or metaArgsVal == nilArg then
    local tidiedVal = tidyVal(key, val)
    local tidiedVal = tidyVal(key, val)
    if tidiedVal == nil then
    if tidiedVal == nil then
    metaArgs[key] = nilArg
    nilArgs[key] = true
    else
    else
    metaArgs[key] = tidiedVal
    metaArgs[key] = tidiedVal
    Line 136: Line 143:
    end
    end
    end
    end
    -- Set the order of precedence of the argument tables. If the variables are
    -- nil, nothing will be added to the table, which is how we avoid clashes
    -- between the frame/parent args and the Lua args.
    local argTables = {fargs}
    argTables[#argTables + 1] = pargs
    argTables[#argTables + 1] = luaArgs


    --[[
    --[[
    -- Define metatable behaviour. Arguments are memoized in the metaArgs table,
    -- Define metatable behaviour. Arguments are memoized in the metaArgs table,
    -- and are only fetched from the argument tables once. Nil arguments are
    -- and are only fetched from the argument tables once. Fetching arguments
    -- also memoized using the nilArg variable in order to increase performance.
    -- from the argument tables is the most resource-intensive step in this
    -- Also, we keep a record in the metatable of when pairs and ipairs have
    -- module, so we try and avoid it where possible. For this reason, nil
    -- been called, so we do not run pairs and ipairs on fargs and pargs more
    -- arguments are also memoized, in the nilArgs table. Also, we keep a record
    -- than once. We also do not run ipairs on fargs and pargs if pairs has
    -- in the metatable of when pairs and ipairs have been called, so we do not
    -- already been run, as all the arguments will already have been copied
    -- run pairs and ipairs on the argument tables more than once. We also do
    -- over.
    -- not run ipairs on fargs and pargs if pairs has already been run, as all
    -- the arguments will already have been copied over.
    --]]
    --]]


    metatable.__index = function (t, key)
    metatable.__index = function (t, key)
    --[[
    -- Fetches an argument when the args table is indexed. First we check
    -- to see if the value is memoized, and if not we try and fetch it from
    -- the argument tables. When we check memoization, we need to check
    -- metaArgs before nilArgs, as both can be non-nil at the same time.
    -- If the argument is not present in metaArgs, we also check whether
    -- pairs has been run yet. If pairs has already been run, we return nil.