cloned from http://code.matthewwild.co.uk/luatraverse/