-- this tool logs types that pass in and out of functions to generate automatic
-- function signatures. These will often be dumb and redundant but that's okay!
-- these should be used as a starting point, like much autogenerated knowledge.
--

local db = {}

local function pack(...)
	return {n=select('#', ...), ...}
end

local function save_table(def, tbl)
	def.fields = def.fields or {}
	local fields = def.fields
	for k, v in pairs(tbl) do
		local t = type(v)
		fields[k] = fields[k] or {n=0}
		fields[k].n = fields[k].n + 1
		if t == "table" then
			fields[k].table = fields[k].table or {fields={}}
			save_table(fields[k].table, v)
		else
			fields[k][t] = (fields[k][t] or 0) + 1
		end
	end
end

local observe = {}
function observe.wrapfn(fn, key)
	key = key or fn
	return function(...)
		db[key] = db[key] or {call={n=0}, ret={n=0}}
		local call = db[key].call
		local ret  = db[key].ret
		call.n = call.n + 1
		for i=1, select('#', ...) do
			local t = type(select(i, ...))
			call[i] = call[i] or {n=0}
			call[i].n = call[i].n + 1
			if t == "table" then
				call[i][t] = call[i][t] or {}
				save_table(call[i].table, select(i, ...))
			else
				call[i][t] = (call[i][t] or 0) + 1
			end
		end
		local r = pack(fn(...))
		ret.n = ret.n + 1
		for i=1, r.n do
			local t = type(r[i])
			ret[i] = ret[i] or {n=0}
			ret[i].n = ret[i].n + 1
			if t == "table" then
				ret[i][t] = ret[i][t] or {}
				save_table(ret[i].table, r[i])
			else
				ret[i][t] = (ret[i][t] or 0) + 1
			end
		end
		return unpack(r, 1, r.n)
	end
end

function observe.save(fname)
	io.stderr:write(require'inspect'(db).."\n")
end

function observe.reset()
	db = {}
end
return observe
