Search in sources :

Example 1 with Entry

use of ceylon.language.Entry in project ceylon by eclipse.

the class PartialImpl method initializeObject.

protected <Id> void initializeObject(TypeDescriptor $reified$Id, DeserializationContextImpl<Id> context, Serializable instance) {
    NativeMap<ReachableReference, Id> state = (NativeMap<ReachableReference, Id>) getState();
    // TODO If it were a map of java.lang.String we'd avoid pointless extra boxing
    java.util.Collection<ReachableReference> reachables = instance.$references$();
    int numLate = 0;
    for (ReachableReference r : reachables) {
        if (r instanceof Member && ((Member) r).getAttribute().getLate()) {
            numLate++;
        } else if (r instanceof Outer) {
            numLate++;
        }
    }
    if (state.getSize() < reachables.size() - numLate) {
        HashSet<ReachableReference> missingNames = new HashSet<ReachableReference>();
        java.util.Iterator<ReachableReference> it = reachables.iterator();
        while (it.hasNext()) {
            missingNames.add(it.next());
        }
        ceylon.language.Iterator<? extends ReachableReference> it2 = state.getKeys().iterator();
        Object next;
        while (((next = it2.next()) instanceof ReachableReference)) {
            missingNames.remove(next);
        }
        throw insufficiantState(missingNames);
    }
    for (ReachableReference reference : reachables) {
        if (reference instanceof Member) {
            Member member = (Member) reference;
            if (member.getAttribute().getLate() && !state.contains(member) || state.get(member) == uninitializedLateValue_.get_()) {
                continue;
            }
            TypeDescriptor.Class classTypeDescriptor = getClassTypeDescriptor();
            Entry<TypeDescriptor.Class, String> cacheKey = new Entry<TypeDescriptor.Class, String>(TypeDescriptor.klass(TypeDescriptor.Class.class), String.$TypeDescriptor$, classTypeDescriptor, String.instance(member.getAttribute().getQualifiedName()));
            Type memberType = (Type) context.getMemberTypeCache().get(cacheKey);
            if (memberType == null) {
                Type pt = Metamodel.getModuleManager().getCachedType(classTypeDescriptor);
                while (!pt.getDeclaration().getQualifiedNameString().equals(((ClassDeclaration) member.getAttribute().getContainer()).getQualifiedName())) {
                    pt = pt.getExtendedType();
                }
                FunctionOrValue attributeDeclaration = (FunctionOrValue) ((TypeDeclaration) pt.getDeclaration()).getMember(member.getAttribute().getName(), null, false);
                TypedReference attributeType = pt.getTypedMember(attributeDeclaration, Collections.<Type>emptyList(), true);
                memberType = attributeType.getType();
                context.getMemberTypeCache().put(cacheKey, memberType);
            }
            Object referredInstance = getReferredInstance(context, state, member);
            if (referredInstance instanceof Tuple) {
                // Because tuples are special wrt reified types...
                Id referredId = state.get(member);
                Object r = context.leakInstance(referredId);
                if (r instanceof PartialImpl) {
                    ((PartialImpl) r).initialize($reified$Id, context);
                }
            }
            Type instanceType = Metamodel.getModuleManager().getCachedType(Metamodel.getTypeDescriptor(referredInstance));
            if (!instanceType.isSubtypeOf(memberType)) {
                throw notAssignable(member, memberType, instanceType);
            }
            instance.$set$(member, referredInstance);
        // the JVM will check the assignability, but we need to
        // check assignability at the ceylon level, so we need to know
        // / type of the attribute an the type that we're assigning.
        // XXX this check is really expensive!
        // we should cache the attribute type on the context
        // when can we avoid this check.
        // XXX we can cache MethodHandle setters on the context!
        } else if (reference instanceof Outer) {
            // instantiating member classes
            continue;
        } else {
            throw new AssertionError("unexpected ReachableReference " + reference);
        }
    }
}
Also used : TypedReference(org.eclipse.ceylon.model.typechecker.model.TypedReference) String(ceylon.language.String) Entry(ceylon.language.Entry) AssertionError(ceylon.language.AssertionError) HashSet(java.util.HashSet) Type(org.eclipse.ceylon.model.typechecker.model.Type) ReifiedType(org.eclipse.ceylon.compiler.java.runtime.model.ReifiedType) ClassDeclaration(ceylon.language.meta.declaration.ClassDeclaration) TypeDescriptor(org.eclipse.ceylon.compiler.java.runtime.model.TypeDescriptor) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) Tuple(ceylon.language.Tuple)

Aggregations

AssertionError (ceylon.language.AssertionError)1 Entry (ceylon.language.Entry)1 String (ceylon.language.String)1 Tuple (ceylon.language.Tuple)1 ClassDeclaration (ceylon.language.meta.declaration.ClassDeclaration)1 HashSet (java.util.HashSet)1 ReifiedType (org.eclipse.ceylon.compiler.java.runtime.model.ReifiedType)1 TypeDescriptor (org.eclipse.ceylon.compiler.java.runtime.model.TypeDescriptor)1 FunctionOrValue (org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)1 Type (org.eclipse.ceylon.model.typechecker.model.Type)1 TypedReference (org.eclipse.ceylon.model.typechecker.model.TypedReference)1