Fix bug in Duplicator. Previously when cloning an entire Program
a cloned Implementation.Proc would not be the same Procedure in
the TopLevelDeclarations.

The reason for this is that Procedure would be cloned twice, once
when visiting it from the TopLevelDeclarations and once when visiting
each Implementation of that Procedure's Implementation.Proc.

To fix this a Procedure is only duplicated once by caching it based
on reference value (this assumes the original Program has Procedure
and Implementation.Proc correctly resolved). This also assumes that
Procedure.Equals() and Procedure.GetHashCode() have not been overidden.