    import ceylon.language.meta.model {
        ClassModel
    }

    "A partially reconstructed instance:
     Holds state for reconstructing an instance which is built up
     progressively by calls to the [[DeserializationContext]]."
    abstract class Partial(id) {

        "The id"// It's an object rather than an id to save space: we require a lot of partials!
        shared Object id;

        "The class, if we know it yet"
        shared variable ClassModel<>? clazz = null;

        "The containing instance (a partial for it, or the instance itself).
         null if this partial is not a member or we don't know the container yet."
        shared variable Anything container = null;

        "The (partially initialized) instance, if it has been [[instantiated|instantiate]], or null."
        shared variable Anything instance_ = null;

        "The state, mapping references to the
         **id** of the corresponding value in the [[DeserializationContext]].
         nullified by a successful call to [[initialize]]."
        //The Value type is not Id to save space
        shared variable NativeMap<ReachableReference, Object>? state = NativeMap<ReachableReference, Object>();

        "Add some state."
        shared void addState(ReachableReference attrOrIndex, Object partialOrComplete) {
            assert(exists s=state);
            s.put(attrOrIndex, partialOrComplete);
        }
        //shared formal void addState(String|Integer attrOrIndex, Object partialOrComplete);

        "Creates (but does not initialize) the [[instance_]] using backend-specific reflection.
         After normal completion of this method instance_ will be non-null."
        throws(`class DeserializationException`,
            "* the class of the instance has already been specified
             * instance is a member instance and the container has not been specified")
        shared formal void instantiate();

        "Initializes the [[instance_]] using backend-specific reflection.
         After normal completion of this method state will be null."
        throws(`class DeserializationException`,
            "the partial contains insufficient state")
        shared formal void initialize<Id>(DeserializationContextImpl<Id> context)
                given Id satisfies Object;

        "Whether the partial has been instantiated"
        shared Boolean instantiated => instance_ exists;
        "Whether the partial has been initialized"
        shared Boolean initialized => !state exists;
        "Whether the partial is for an instance of a member class"
        shared Boolean member => container exists;

        "Gets the fully initialized instance, or throws"
        shared Anything instance() {
            assert(instantiated && initialized);
            return instance_;
        }

        "The ids of the instances that this instance refers to"
        shared {Object*} refersTo {
            if (exists s=state) {
                return s.items;
            } else {
                return [];
            }
        }
    }