Have you taken a look at Data::Denter? Although the output format is not evalable (it has to be "undented"), I believe it handles circular references. I'm not sure if it deals with all the cases mentioned here, but it would be a good idea to make sure you're not reinventing a reinvented wheel :-)