local trace = function(...)
--	print(string.format( ... ) )
end

--------------------------------------------------------------------------------

-- pops items from the locals list whose scope ends before pc
local function pop( stack, names, pc )
	for i = #stack, 1, -1 do
		local var = stack[ i ]
		if var.endpc < pc then
			-- pop items that are now out of scope
			names[ var.varname ] = names[ var.varname ] - 1
			stack[ i ] = nil
		else
			break
		end
	end
end

--------------------------------------------------------------------------------

-- returns true if the given name is already in use
local function bumpname( names, name )
	-- enhancement: retain info beyond the count so shadow hit can include
	-- the line number of the shadowed local and the shadowing local
	names[ name ] = ( names[ name ] or 0 ) + 1
	
	return names[ name ] > 1
end

--------------------------------------------------------------------------------

-- returns true if this local is shadowing another one
local function push( stack, names, newvar )
	pop( stack, names, newvar.startpc )
	stack[ #stack + 1 ] = newvar
	
	return bumpname( names, newvar.varname )
end

--------------------------------------------------------------------------------

-- recursively descend through function tree and find shadow locals, where
-- "shadow" refers to a local with the same name as a previously defined
-- local (or upvalue) in an overlapping scope
local function findShadowLocals( ignore, fd, results )
	results = results or { }

	local stack = { }
	local names = { }
	for _, loc in ipairs( fd.locals ) do
		if not ignore[ loc.varname ] then
			if push( stack, names, loc ) then
				trace( "SHADOW: ", loc.varname, loc.startpc, loc.endpc )

				local line = fd.lines[ loc.startpc ] or fd.lineDefined
				
				table.insert( results, { line = line, name = loc.varname, kind = "shadow"  } )
			end
		end
	
		trace( loc.varname, loc.startpc, loc.endpc )
	end
	trace( string.rep( '-', 80 ) )

	for _, subf in ipairs( fd.constants.functions ) do
		findShadowLocals( ignore, subf, results )
	end
	
	return results
end

return findShadowLocals
