Search in sources :

Example 1 with InferenceVariable

use of org.eclipse.n4js.ts.types.InferenceVariable in project n4js by eclipse.

the class BoundSet method combineInvVar.

/**
 * Case: first bound is an equality, while the second isn't: `α = S` and `β Φ T` with Φ either {@code <:} or
 * {@code :>}.
 */
private TypeConstraint combineInvVar(TypeBound boundS, TypeBound boundT) {
    final InferenceVariable alpha = boundS.left;
    final InferenceVariable beta = boundT.left;
    final TypeRef S = boundS.right;
    final TypeRef T = boundT.right;
    final Variance Phi = boundT.variance;
    if (alpha == beta) {
        // (1) `α = S` and `α Φ T` implies `S Φ T`
        return new TypeConstraint(S, T, Phi);
    }
    // both bounds have different inference variables, i.e. α != β
    if (alpha == T.getDeclaredType()) {
        // (2) `α = S` and `β Φ α` implies `β Φ S`
        return new TypeConstraint(typeRef(beta), S, Phi);
    }
    if (TypeUtils.isInferenceVariable(S)) {
        // first bound is of the form `α = γ` (with γ being another inference variable)
        final InferenceVariable gamma = (InferenceVariable) S.getDeclaredType();
        if (gamma == beta) {
            // (3) `α = β` and `β Φ T` implies `α Φ T`
            return new TypeConstraint(typeRef(alpha), T, Phi);
        }
        if (gamma == T.getDeclaredType()) {
            // (4) `α = γ` and `β Φ γ` implies `β Φ α`
            return new TypeConstraint(typeRef(beta), typeRef(alpha), Phi);
        }
    }
    // so, S is not an inference variable
    if (TypeUtils.isProper(S) && TypeUtils.getReferencedTypeVars(T).contains(alpha)) {
        // (5) `α = S` (where S is proper) and `β Φ T` implies `β Φ T[α:=U]`
        // returns T[α:=U]
        final TypeRef T_subst = substituteInferenceVariable(T, alpha, S);
        // performance tweak: avoid unnecessary growth of bounds
        removeBound(boundT);
        return new TypeConstraint(typeRef(beta), T_subst, Phi);
    }
    return null;
}
Also used : InferenceVariable(org.eclipse.n4js.ts.types.InferenceVariable) ParameterizedTypeRef(org.eclipse.n4js.ts.typeRefs.ParameterizedTypeRef) TypeRef(org.eclipse.n4js.ts.typeRefs.TypeRef) Variance(org.eclipse.n4js.ts.types.util.Variance)

Example 2 with InferenceVariable

use of org.eclipse.n4js.ts.types.InferenceVariable in project n4js by eclipse.

the class BoundSet method combineContraCo.

/**
 * Case: `α :> S` and `β <: T`.
 */
private TypeConstraint combineContraCo(TypeBound boundS, TypeBound boundT) {
    final InferenceVariable alpha = boundS.left;
    final InferenceVariable beta = boundT.left;
    final TypeRef S = boundS.right;
    final TypeRef T = boundT.right;
    if (alpha == beta) {
        // α :> S and α <: T implies S <: T
        return new TypeConstraint(S, T, CO);
    }
    // so, α and β are different
    if (TypeUtils.isInferenceVariable(S)) {
        final InferenceVariable gamma = (InferenceVariable) S.getDeclaredType();
        if (gamma == T.getDeclaredType()) {
            // α :> γ and β <: γ implies α :> β
            return new TypeConstraint(typeRef(alpha), typeRef(beta), CONTRA);
        }
    }
    return null;
}
Also used : InferenceVariable(org.eclipse.n4js.ts.types.InferenceVariable) ParameterizedTypeRef(org.eclipse.n4js.ts.typeRefs.ParameterizedTypeRef) TypeRef(org.eclipse.n4js.ts.typeRefs.TypeRef)

Example 3 with InferenceVariable

use of org.eclipse.n4js.ts.types.InferenceVariable in project n4js by eclipse.

the class InferenceContext method getSmallestVariableSet.

/**
 * Given a set <code>infVars</code> of inference variables of the receiving inference context, this method returns
 * the smallest, non-empty set S such that
 * <ul>
 * <li>all α &isin; S are uninstantiated inference variables of the receiving inference context,
 * <li>one of the elements in S is also in <code>infVars</code>: &exist; α &isin; S: α &isin; <code>infVars</code>,
 * <li>if an α &isin; S depends on the resolution of another variable β, then either β is instantiated or β &isin;
 * S,</li>
 * <li>there exists no non-empty proper subset of S with this property.</li>
 * </ul>
 * Returns <code>null</code> if no such set exists, e.g. because <code>infVars</code> was empty or did not contain
 * any uninstantiated inference variables.
 * <p>
 * The returned set, if non-null, is guaranteed to be non-empty.
 */
private Set<InferenceVariable> getSmallestVariableSet(Set<InferenceVariable> infVars) {
    Set<InferenceVariable> result = null;
    Set<InferenceVariable> deferred = null;
    int min = Integer.MAX_VALUE;
    for (InferenceVariable currentVariable : infVars) {
        if (!currentBounds.isInstantiated(currentVariable)) {
            // With the following code, we defer processing of β until α has been instantiated to A.
            if (currentBounds.isUnbounded(currentVariable)) {
                final boolean gotAtLeastOneDependantIV = infVars.stream().anyMatch(iv -> currentBounds.dependsOnResolutionOf(iv, currentVariable));
                if (gotAtLeastOneDependantIV) {
                    final boolean defer = infVars.stream().filter(iv -> currentBounds.dependsOnResolutionOf(iv, currentVariable)).allMatch(iv -> {
                        final List<TypeBound> bs = currentBounds.getBounds(iv).stream().filter(b -> !(b.left == iv && b.right.getDeclaredType() == currentVariable)).collect(Collectors.toList());
                        return !bs.isEmpty() && bs.stream().allMatch(b -> TypeUtils.isProper(b.right));
                    });
                    if (defer) {
                        if (deferred == null) {
                            deferred = new HashSet<>();
                        }
                        deferred.add(currentVariable);
                        continue;
                    }
                }
            }
            final Set<InferenceVariable> set = new LinkedHashSet<>();
            if (addDependencies(currentVariable, min, set)) {
                final int curr = set.size();
                if (curr == 1) {
                    // 'set' contains only currentVariable -> no need to remove deferred variables
                    return set;
                }
                if (curr < min) {
                    result = set;
                    min = curr;
                }
            }
        }
    }
    if ((result == null) || result.isEmpty()) {
        return null;
    }
    // deferred variables may have been added via #addDependencies() above, so remove them
    if (deferred != null) {
        // note: because deferred variables can only end up in 'result' via #addDependencies(), we can safely
        // remove all deferred variables and be sure that 'result' won't be empty afterwards
        result.removeAll(deferred);
    }
    return result;
}
Also used : Arrays(java.util.Arrays) TypeVariable(org.eclipse.n4js.ts.types.TypeVariable) RuleEnvironment(org.eclipse.xsemantics.runtime.RuleEnvironment) ContiguousSet(com.google.common.collect.ContiguousSet) Date(java.util.Date) SimpleDateFormat(java.text.SimpleDateFormat) ClosableMeasurement(org.eclipse.n4js.smith.ClosableMeasurement) Variance(org.eclipse.n4js.ts.types.util.Variance) CharDiscreteDomain(org.eclipse.n4js.utils.CharDiscreteDomain) TypeUtils(org.eclipse.n4js.ts.utils.TypeUtils) INV(org.eclipse.n4js.ts.types.util.Variance.INV) ParameterizedTypeRef(org.eclipse.n4js.ts.typeRefs.ParameterizedTypeRef) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) TypeSystemHelper(org.eclipse.n4js.typesystem.TypeSystemHelper) OperationCanceledException(org.eclipse.core.runtime.OperationCanceledException) RuleEnvironmentExtensions(org.eclipse.n4js.typesystem.RuleEnvironmentExtensions) Type(org.eclipse.n4js.ts.types.Type) CancelIndicator(org.eclipse.xtext.util.CancelIndicator) Optional(com.google.common.base.Optional) Map(java.util.Map) TypeRef(org.eclipse.n4js.ts.typeRefs.TypeRef) LinkedHashSet(java.util.LinkedHashSet) UnknownTypeRef(org.eclipse.n4js.ts.typeRefs.UnknownTypeRef) DataCollector(org.eclipse.n4js.smith.DataCollector) DataCollectors(org.eclipse.n4js.smith.DataCollectors) Iterator(java.util.Iterator) OperationCanceledManager(org.eclipse.xtext.service.OperationCanceledManager) Range(com.google.common.collect.Range) Set(java.util.Set) Collectors(java.util.stream.Collectors) Objects(java.util.Objects) Consumer(java.util.function.Consumer) List(java.util.List) Stream(java.util.stream.Stream) FunctionTypeExprOrRef(org.eclipse.n4js.ts.typeRefs.FunctionTypeExprOrRef) InferenceVariable(org.eclipse.n4js.ts.types.InferenceVariable) TypeArgument(org.eclipse.n4js.ts.typeRefs.TypeArgument) TypesFactory(org.eclipse.n4js.ts.types.TypesFactory) N4JSTypeSystem(org.eclipse.n4js.typesystem.N4JSTypeSystem) LinkedHashSet(java.util.LinkedHashSet) InferenceVariable(org.eclipse.n4js.ts.types.InferenceVariable)

Example 4 with InferenceVariable

use of org.eclipse.n4js.ts.types.InferenceVariable in project n4js by eclipse.

the class InferenceContext method resolve.

// ###############################################################################################################
// RESOLUTION
/**
 * Performs resolution of all inference variables of the receiving inference context. This might trigger further
 * reduction and incorporation steps.
 * <p>
 * If a solution is found, <code>true</code> is returned and {@link #currentBounds} will contain instantiations for
 * all inference variables. Otherwise, <code>false</code> is returned and {@link #currentBounds} will be in an
 * undefined state.
 */
private boolean resolve() {
    Set<InferenceVariable> currVariableSet;
    while ((currVariableSet = getSmallestVariableSet(inferenceVariables)) != null) {
        for (InferenceVariable currVariable : currVariableSet) {
            if (DEBUG) {
                log("======");
                log("trying to resolve inference variable: " + str(currVariable));
                log("based on this bound set:");
                Arrays.stream(currentBounds.getAllBounds()).forEachOrdered(b -> log("    " + b.toString()));
            }
            final TypeRef instantiation = chooseInstantiation(currVariable);
            if (instantiation == null) {
                if (DEBUG) {
                    log("NO INSTANTIATION found for inference variable: " + str(currVariable));
                }
                return false;
            } else {
                if (DEBUG) {
                    log("choosing instantiation " + str(currVariable) + " := " + str(instantiation));
                }
                instantiate(currVariable, instantiation);
            }
        }
        currentBounds.incorporate();
        if (isDoomed()) {
            return false;
        }
    }
    return true;
}
Also used : InferenceVariable(org.eclipse.n4js.ts.types.InferenceVariable) ParameterizedTypeRef(org.eclipse.n4js.ts.typeRefs.ParameterizedTypeRef) TypeRef(org.eclipse.n4js.ts.typeRefs.TypeRef) UnknownTypeRef(org.eclipse.n4js.ts.typeRefs.UnknownTypeRef)

Example 5 with InferenceVariable

use of org.eclipse.n4js.ts.types.InferenceVariable in project n4js by eclipse.

the class BoundSet method combineBothCoOrBothContra.

/**
 * Case: inequalities of same direction, i.e.
 * <ul>
 * <li>`α <: S` and `β <: T` or
 * <li>`α :> S` and `β :> T`.
 * </ul>
 */
private TypeConstraint combineBothCoOrBothContra(TypeBound boundS, TypeBound boundT) {
    final InferenceVariable alpha = boundS.left;
    final InferenceVariable beta = boundT.left;
    final TypeRef S = boundS.right;
    final TypeRef T = boundT.right;
    if (alpha == T.getDeclaredType()) {
        // α :> S and β :> α implies β :> S
        return new TypeConstraint(typeRef(beta), S, boundS.variance);
    }
    if (S.getDeclaredType() == beta) {
        // α :> β and β :> T implies α :> T
        return new TypeConstraint(typeRef(alpha), T, boundS.variance);
    }
    return null;
}
Also used : InferenceVariable(org.eclipse.n4js.ts.types.InferenceVariable) ParameterizedTypeRef(org.eclipse.n4js.ts.typeRefs.ParameterizedTypeRef) TypeRef(org.eclipse.n4js.ts.typeRefs.TypeRef)

Aggregations

InferenceVariable (org.eclipse.n4js.ts.types.InferenceVariable)9 ParameterizedTypeRef (org.eclipse.n4js.ts.typeRefs.ParameterizedTypeRef)7 TypeRef (org.eclipse.n4js.ts.typeRefs.TypeRef)7 TypeArgument (org.eclipse.n4js.ts.typeRefs.TypeArgument)3 RuleEnvironment (org.eclipse.xsemantics.runtime.RuleEnvironment)3 FunctionTypeExprOrRef (org.eclipse.n4js.ts.typeRefs.FunctionTypeExprOrRef)2 UnknownTypeRef (org.eclipse.n4js.ts.typeRefs.UnknownTypeRef)2 TypeVariable (org.eclipse.n4js.ts.types.TypeVariable)2 Variance (org.eclipse.n4js.ts.types.util.Variance)2 Optional (com.google.common.base.Optional)1 ContiguousSet (com.google.common.collect.ContiguousSet)1 Range (com.google.common.collect.Range)1 SimpleDateFormat (java.text.SimpleDateFormat)1 ArrayList (java.util.ArrayList)1 Arrays (java.util.Arrays)1 Date (java.util.Date)1 HashSet (java.util.HashSet)1 Iterator (java.util.Iterator)1 LinkedHashSet (java.util.LinkedHashSet)1 List (java.util.List)1