public static object DeepCopy(RubyContext /*!*/ context, object obj) { using (IDisposable handle = _infiniteCopyTracker.TrackObject(obj)) { if (handle == null) { return(RubyExceptions.CreateArgumentError("unable to deep copy recursive structure")); } else { RubyContext ec = RubyUtils.GetExecutionContext(context); if (RubyUtils.IsRubyValueType(obj)) { return(obj); } object copy; // TODO: special case class objects: RubyClass classObject = obj as RubyClass; if (classObject != null) { copy = classObject.Duplicate(); } else { copy = RubySites.Allocate(context, ec.GetClassOf(obj)); } SymbolId[] names = ec.GetInstanceVariableNames(obj); RubyInstanceData newVars = (names.Length > 0) ? ec.GetInstanceData(copy) : null; foreach (SymbolId name in names) { object value; if (!ec.TryGetInstanceVariable(obj, name, out value)) { value = null; } else { value = DeepCopy(context, value); } newVars.SetInstanceVariable(name, value); } if (classObject == null) { // do any special copying needed for library types // TODO: we still need to implement copy semantics for .NET types in general IDuplicable duplicable = copy as IDuplicable; if (duplicable != null) { duplicable.InitializeFrom(obj); } } return(copy); } } }