예제 #1
0
 /** @see jaskell.compiler.JaskellVisitor#visit(ConstructorPattern) */
 public Object visit(ConstructorPattern a) {
   String cname = a.getConstructor().getName();
   /* retrieve parameter types of constructor */
   ConstructorDefinition ctor = (ConstructorDefinition) a.getConstructor().lookup(cname);
   if (ctor == null) throw new TypeError("Undefined constructor pattern  " + a);
   /* type of data constructed by constructor */
   TypeInstantiator ti = new TypeInstantiator(ctor.getDataType());
   Type rtype = ti.instance();
   Map map = ti.getMap();
   TypeSubstitution ts = new TypeSubstitution(map);
   Iterator ittypes = ctor.getParameters().iterator();
   /* retrieve type of patterns */
   Iterator it = a.getSubPatterns();
   while (it.hasNext()) {
     try {
       Pattern p = (Pattern) it.next();
       Type actual = TypeFactory.freshBinding();
       Type formal = ts.substitute((Type) ittypes.next());
       /* unify both types */
       p.setType(tu.unify(formal, actual, typeVariablesMap));
     } catch (NoSuchElementException nex) {
       throw new TypeError("Wrong number of arguments to pattern " + a);
     }
   }
   a.setType(rtype);
   return a.getType();
 }
  @Test
  public void parametrizedTypeType_methods_tests() {
    JavaSymbol.PackageJavaSymbol packageSymbol =
        new JavaSymbol.PackageJavaSymbol("org.foo.bar", null);
    JavaSymbol.TypeJavaSymbol typeSymbol =
        new JavaSymbol.TypeJavaSymbol(Flags.PUBLIC, "MyType", packageSymbol);
    JavaSymbol.TypeVariableJavaSymbol typeVariableSymbol =
        new JavaSymbol.TypeVariableJavaSymbol("E", typeSymbol);
    ClassJavaType classType = (ClassJavaType) typeSymbol.type;
    TypeVariableJavaType typeVariableType = (TypeVariableJavaType) typeVariableSymbol.type;
    TypeSubstitution typeSubstitution = new TypeSubstitution();
    typeSubstitution.add(typeVariableType, classType);

    ParametrizedTypeJavaType ptt = new ParametrizedTypeJavaType(typeSymbol, typeSubstitution);
    assertThat(ptt.substitution(typeVariableType)).isEqualTo(classType);
    assertThat(
            ptt.substitution(
                new TypeVariableJavaType(new JavaSymbol.TypeVariableJavaSymbol("F", typeSymbol))))
        .isNull();
    assertThat(ptt.typeParameters()).hasSize(1);
    assertThat(ptt.typeParameters()).contains(typeVariableType);

    ptt = new ParametrizedTypeJavaType(typeSymbol, null);
    assertThat(ptt.substitution(typeVariableType)).isNull();
    assertThat(ptt.typeParameters()).isEmpty();

    assertThat(ptt.isClass()).isTrue();
    assertThat(ptt.isParameterized()).isTrue();
    assertThat(ptt.rawType.isClass()).isTrue();
    assertThat(ptt.rawType.isParameterized()).isFalse();
  }
예제 #3
0
 private JavaType handleTypeArguments(
     List<JavaType> typeParams, JavaType type, JavaSymbol.MethodJavaSymbol methodSymbol) {
   if (!typeParams.isEmpty() && methodSymbol.typeVariableTypes.size() == typeParams.size()) {
     TypeSubstitution typeSubstitution = new TypeSubstitution();
     int i = 0;
     for (JavaType.TypeVariableJavaType typeVariableType : methodSymbol.typeVariableTypes) {
       typeSubstitution.add(typeVariableType, typeParams.get(i));
       i++;
     }
     return substituteTypeParameter(type, typeSubstitution);
   }
   return type;
 }
예제 #4
0
 /** @see jaskell.compiler.JaskellVisitor#visit(Application) */
 public Object visit(Application a) {
   try {
     /* get type of function */
     Expression fun = a.getFunction();
     /* get type deduced from arguments */
     LinkedList l = new LinkedList();
     Iterator it = a.getArgs().iterator();
     while (it.hasNext()) {
       Expression e = (Expression) it.next();
       l.add((Type) e.visit(this));
     }
     Type vt = TypeFactory.freshBinding();
     Type ft = Types.fun(l, vt);
     log.finer("TypeChecker => In application " + a + ", type is " + ft);
     /* apply substitution on both types */
     ft = subst.substitute(ft);
     /* try to unify function type and constructed types */
     Type t = (Type) fun.visit(this);
     log.finer("In application, function " + fun + " :: " + t);
     t = subst.substitute(t);
     log.finer("In application, trying to unify function type " + t + " with body " + ft);
     /*
      * TODO : problem with unification of constrained types
      */
     TypeApplication uni = (TypeApplication) tu.unify(t, ft, typeVariablesMap);
     /* sets type of functional expression - this allows
      * polymorphic functions to receive several types
      * in the same code */
     // fun.setType(uni);
     /* apply arguments type to compute return type */
     log.finer("Done unify application :" + uni);
     it = PrimitiveType.functionIterator(uni);
     Iterator it2 = l.iterator();
     TypeApplication ut = uni;
     while (it2.hasNext()) {
       /* type of argument */
       Type at = (Type) it2.next();
       ut = (TypeApplication) it.next();
       /* try unification */
       tu.unify(((TypeApplication) ut.getDomain()).getRange(), at, new HashMap(typeVariablesMap));
     }
     ft = subst.substitute(ft);
     fun.setType(ft);
     log.finer("Setting type of functional element [" + fun + "] to :" + ft);
     a.setType(ut.getRange());
     return ut.getRange();
   } catch (TypeError te) {
     if (te.getLineCol() == null) te.setLineCol(a.getTag("source"));
     throw te;
   }
 }
예제 #5
0
 @Nullable
 public TypeProjection substitute(@NotNull TypeProjection typeProjection) {
   TypeProjection substitutedTypeProjection = substituteWithoutApproximation(typeProjection);
   if (!substitution.approximateCapturedTypes()) {
     return substitutedTypeProjection;
   }
   return CapturedTypeApproximationKt.approximateCapturedTypesIfNecessary(
       substitutedTypeProjection);
 }
예제 #6
0
 @Override
 public void visitEnd() {
   if (!typeArguments.isEmpty()) {
     JavaSymbol.TypeJavaSymbol readSymbol = typeRead.symbol;
     readSymbol.complete();
     // Mismatch between type variable and type arguments means we are lacking some pieces of
     // bytecode to resolve substitution properly.
     if (typeArguments.size() == readSymbol.typeVariableTypes.size()) {
       TypeSubstitution substitution = new TypeSubstitution();
       int i = 0;
       for (JavaType typeArgument : typeArguments) {
         substitution.add(readSymbol.typeVariableTypes.get(i), typeArgument);
         i++;
       }
       typeRead = parametrizedTypeCache.getParametrizedTypeType(readSymbol, substitution);
     }
   }
 }
예제 #7
0
 private JavaType substituteTypeParameter(JavaType type, TypeSubstitution substitution) {
   JavaType substitutedType = substitution.substitutedType(type);
   if (substitutedType != null) {
     return substitutedType;
   }
   if (type instanceof JavaType.ParametrizedTypeJavaType) {
     JavaType.ParametrizedTypeJavaType ptt = (JavaType.ParametrizedTypeJavaType) type;
     TypeSubstitution newSubstitution = new TypeSubstitution();
     for (Map.Entry<JavaType.TypeVariableJavaType, JavaType> entry :
         ptt.typeSubstitution.substitutionEntries()) {
       newSubstitution.add(
           entry.getKey(), substituteTypeParameter(entry.getValue(), substitution));
     }
     return parametrizedTypeCache.getParametrizedTypeType(
         ptt.rawType.getSymbol(), newSubstitution);
   }
   return type;
 }
  @Test
  public void erasure_of_type_variable() {
    JavaSymbol.TypeJavaSymbol typeSymbol =
        new JavaSymbol.TypeJavaSymbol(
            Flags.PUBLIC, "MyType", new JavaSymbol.PackageJavaSymbol("org.foo.bar", null));
    TypeSubstitution typeSubstitution = new TypeSubstitution();
    typeSubstitution.add(
        (TypeVariableJavaType) new JavaSymbol.TypeVariableJavaSymbol("T", typeSymbol).type,
        typeSymbol.type);
    ParametrizedTypeJavaType parametrizedType =
        new ParametrizedTypeJavaType(typeSymbol, typeSubstitution);

    TypeVariableJavaType typeVariableType =
        (TypeVariableJavaType) new JavaSymbol.TypeVariableJavaSymbol("X", typeSymbol).type;
    typeVariableType.bounds = ImmutableList.<JavaType>of(parametrizedType);

    assertThat(typeVariableType.erasure()).isNotEqualTo(parametrizedType);
    assertThat(typeVariableType.erasure()).isEqualTo(parametrizedType.erasure());
  }
예제 #9
0
 /** @see jaskell.compiler.JaskellVisitor#visit(Abstraction) */
 public Object visit(Abstraction a) {
   try {
     Type t = a.getType();
     if (t != null) return subst.substitute(t);
     log.finest("Visiting abstraction : " + a);
     Expression body = a.getBody();
     /* duplicate bindings map to assign types to variables */
     pushContext(a.getBindings());
     /* create fresh type variables as type for each bound
      * variable */
     Iterator it = namesMap.values().iterator();
     LinkedList tl = new LinkedList();
     while (it.hasNext()) {
       LocalBinding name = (LocalBinding) it.next();
       Type vt = TypeFactory.freshBinding();
       name.setType(vt);
       tl.add(vt);
     }
     Type tv = TypeFactory.freshBinding();
     /* create type with all variables for function */
     Type ft = Types.fun(tl, tv);
     log.finer("In abstraction, setting type to " + ft);
     a.setType(ft);
     /* analyze body */
     Type bt = (Type) body.visit(this);
     /* unify return type of function with type of body */
     Type ret = tu.unify(PrimitiveType.getReturnType(ft), bt, typeVariablesMap);
     TyvarSubstitution tys = new TyvarSubstitution(typeVariablesMap);
     tys.visit(a);
     log.finer("Done abstraction, setting type from " + ft + " to " + a.getType());
     popContext();
     return a.getType();
   } catch (TypeError te) {
     if (te.getLineCol() == null) te.setLineCol(a.getTag("source"));
     throw te;
   }
 }
예제 #10
0
 public boolean isEmpty() {
   return substitution.isEmpty();
 }
예제 #11
0
  @NotNull
  private TypeProjection unsafeSubstitute(
      @NotNull TypeProjection originalProjection, int recursionDepth) throws SubstitutionException {
    assertRecursionDepth(recursionDepth, originalProjection, substitution);

    if (originalProjection.isStarProjection()) return originalProjection;

    // The type is within the substitution range, i.e. T or T?
    JetType type = originalProjection.getType();
    TypeProjection replacement = substitution.get(type);
    Variance originalProjectionKind = originalProjection.getProjectionKind();
    if (replacement == null
        && FlexibleTypesKt.isFlexible(type)
        && !TypeCapabilitiesKt.isCustomTypeVariable(type)) {
      Flexibility flexibility = FlexibleTypesKt.flexibility(type);
      TypeProjection substitutedLower =
          unsafeSubstitute(
              new TypeProjectionImpl(originalProjectionKind, flexibility.getLowerBound()),
              recursionDepth + 1);
      TypeProjection substitutedUpper =
          unsafeSubstitute(
              new TypeProjectionImpl(originalProjectionKind, flexibility.getUpperBound()),
              recursionDepth + 1);

      Variance substitutedProjectionKind = substitutedLower.getProjectionKind();
      assert (substitutedProjectionKind == substitutedUpper.getProjectionKind())
                  && originalProjectionKind == Variance.INVARIANT
              || originalProjectionKind == substitutedProjectionKind
          : "Unexpected substituted projection kind: "
              + substitutedProjectionKind
              + "; original: "
              + originalProjectionKind;

      JetType substitutedFlexibleType =
          DelegatingFlexibleType.create(
              substitutedLower.getType(),
              substitutedUpper.getType(),
              flexibility.getExtraCapabilities());
      return new TypeProjectionImpl(substitutedProjectionKind, substitutedFlexibleType);
    }

    if (KotlinBuiltIns.isNothing(type) || type.isError()) return originalProjection;

    if (replacement != null) {
      VarianceConflictType varianceConflict =
          conflictType(originalProjectionKind, replacement.getProjectionKind());

      // Captured type might be substituted in an opposite projection:
      // out 'Captured (in Int)' = out Int
      // in 'Captured (out Int)' = in Int
      boolean allowVarianceConflict = CapturedTypeConstructorKt.isCaptured(type);
      if (!allowVarianceConflict) {
        //noinspection EnumSwitchStatementWhichMissesCases
        switch (varianceConflict) {
          case OUT_IN_IN_POSITION:
            throw new SubstitutionException("Out-projection in in-position");
          case IN_IN_OUT_POSITION:
            // todo use the right type parameter variance and upper bound
            return new TypeProjectionImpl(
                Variance.OUT_VARIANCE, type.getConstructor().getBuiltIns().getNullableAnyType());
        }
      }
      JetType substitutedType;
      CustomTypeVariable typeVariable = TypeCapabilitiesKt.getCustomTypeVariable(type);
      if (replacement.isStarProjection()) {
        return replacement;
      } else if (typeVariable != null) {
        substitutedType = typeVariable.substitutionResult(replacement.getType());
      } else {
        // this is a simple type T or T?: if it's T, we should just take replacement, if T? - we
        // make replacement nullable
        substitutedType =
            TypeUtils.makeNullableIfNeeded(replacement.getType(), type.isMarkedNullable());
      }

      // substitutionType.annotations = replacement.annotations ++ type.annotations
      if (!type.getAnnotations().isEmpty()) {
        Annotations typeAnnotations = filterOutUnsafeVariance(type.getAnnotations());
        substitutedType =
            TypeUtilsKt.replaceAnnotations(
                substitutedType,
                new CompositeAnnotations(substitutedType.getAnnotations(), typeAnnotations));
      }

      Variance resultingProjectionKind =
          varianceConflict == VarianceConflictType.NO_CONFLICT
              ? combine(originalProjectionKind, replacement.getProjectionKind())
              : originalProjectionKind;
      return new TypeProjectionImpl(resultingProjectionKind, substitutedType);
    }
    // The type is not within the substitution range, i.e. Foo, Bar<T> etc.
    return substituteCompoundType(originalProjection, recursionDepth);
  }