All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.extendj.ast.Constraints Maven / Gradle / Ivy

There is a newer version: 8.1.2
Show newest version
package org.extendj.ast;

import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.ArrayList;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.zip.*;
import java.io.*;
import org.jastadd.util.PrettyPrintable;
import org.jastadd.util.PrettyPrinter;
import org.jastadd.util.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.IOException;
import java.util.Set;
import beaver.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
/**
 * @ast class
 * @aspect GenericMethodsInference
 * @declaredat /home/jesper/git/extendj/java5/frontend/GenericMethodsInference.jrag:164
 */
 class Constraints extends java.lang.Object {
  
    static class ConstraintSet {
      public Collection supertypeConstraints = new HashSet(4);
      public Collection subtypeConstraints = new HashSet(4);
      public Collection equaltypeConstraints = new HashSet(4);
      public TypeDecl typeArgument;
    }

  

    private Collection typeVariables;

  

    protected Map constraintsMap;

  

    public boolean rawAccess = false;

  

    public Constraints() {
      typeVariables = new ArrayList(4);
      constraintsMap = new HashMap();
    }

  

    public void addTypeVariable(TypeVariable T) {
      if (!typeVariables.contains(T)) {
        typeVariables.add(T);
        constraintsMap.put(T, new ConstraintSet());
      }
    }

  

    public boolean unresolvedTypeArguments() {
      for (TypeVariable T : typeVariables) {
        ConstraintSet set = constraintsMap.get(T);
        if (set.typeArgument == null) {
          return true;
        }
      }
      return false;
    }

  

    public String toString() {
      StringBuilder str = new StringBuilder();
      str.append("Current constraints: ");
      for (TypeVariable T : typeVariables) {
        ConstraintSet set = constraintsMap.get(T);
        for (TypeDecl U : set.supertypeConstraints) {
          str.append("  " + T.fullName() + " :> " + U.fullName());
        }
        for (TypeDecl U : set.subtypeConstraints) {
          str.append("  " + T.fullName() + " <: " + U.fullName());
        }
        for (TypeDecl U : set.equaltypeConstraints) {
          str.append("  " + T.fullName() + " = " + U.fullName());
        }
      }
      return str.toString();
    }

  


    public void resolveBounds() {
      for (TypeVariable T : typeVariables) {
        ConstraintSet set = constraintsMap.get(T);
        if (set.typeArgument == null) {
          set.typeArgument = T.getTypeBound(0).type();
        }
      }
    }

  

    public void resolveEqualityConstraints() {
      for (TypeVariable T : typeVariables) {
        ConstraintSet set = constraintsMap.get(T);
        for (TypeDecl U : set.equaltypeConstraints) {
          if (!typeVariables.contains(U)) {
            // Replace equality constraints for other type variables.
            replaceEqualityConstraints(T, U);
            set.equaltypeConstraints.clear();
            // Make U is the only equality constraint for T.
            set.equaltypeConstraints.add(U);
            set.typeArgument = U;
            break; // Continue on next type variable.
          } else if (T == U) {
            // Discard constraint.
          } else {
            replaceAllConstraints(T, U); // Rewrite all constraints involving T to use U instead.
            break; // Continue on next type variable.
          }
        }
        if (set.typeArgument == null && set.equaltypeConstraints.size() == 1
            && set.equaltypeConstraints.contains(T)) {
          set.typeArgument = T;
        }
      }
    }

  

    public void replaceEqualityConstraints(TypeDecl before, TypeDecl after) {
      for (TypeVariable T : typeVariables) {
        ConstraintSet set = constraintsMap.get(T);
        replaceConstraints(set.equaltypeConstraints, before, after);
      }
    }

  

    public void replaceAllConstraints(TypeDecl before, TypeDecl after) {
      for (TypeVariable T : typeVariables) {
        ConstraintSet set = constraintsMap.get(T);
        replaceConstraints(set.supertypeConstraints, before, after);
        replaceConstraints(set.subtypeConstraints, before, after);
        replaceConstraints(set.equaltypeConstraints, before, after);
      }
    }

  

    private void replaceConstraints(Collection constraints,
        TypeDecl before, TypeDecl after) {
      Collection newConstraints = new ArrayList();
      for (Iterator iter = constraints.iterator(); iter.hasNext(); ) {
        TypeDecl U = iter.next();
        if (U == before) { // TODO: fix parameterized type
          iter.remove();
          newConstraints.add(after);
        }
      }
      constraints.addAll(newConstraints);
    }

  

    public void resolveSubtypeConstraints() {
      for (TypeVariable T : typeVariables) {
        ConstraintSet set = constraintsMap.get(T);
        if (set.typeArgument == null && !set.subtypeConstraints.isEmpty()) {
          ArrayList bounds = new ArrayList();
          for (TypeDecl type : set.subtypeConstraints) {
            bounds.add(type);
          }
          set.typeArgument = GLBTypeFactory.glb(bounds);
        }
      }
    }

  

    public void resolveSupertypeConstraints() {
      for (TypeVariable T : typeVariables) {
        ConstraintSet set = constraintsMap.get(T);
        if (set.typeArgument == null && !set.supertypeConstraints.isEmpty()) {
          TypeDecl typeDecl = T.lookupLUBType(set.supertypeConstraints).lub();
          set.typeArgument = typeDecl;
        }
      }
    }

  

    public static Collection directSupertypes(TypeDecl t) {
      if (t instanceof ClassDecl) {
        ClassDecl type = (ClassDecl) t;
        Collection set = new HashSet();
        if (type.hasSuperclass()) {
          set.add(type.superclass());
        }
        for (int i = 0; i < type.getNumImplements(); i++) {
          set.add(type.getImplements(i).type());
        }
        return set;
      } else if (t instanceof InterfaceDecl) {
        InterfaceDecl type = (InterfaceDecl) t;
        Collection set = new HashSet();
        for (int i = 0; i < type.getNumSuperInterface(); i++) {
          set.add(type.getSuperInterface(i).type());
        }
        return set;
      } else if (t instanceof TypeVariable) {
        TypeVariable type = (TypeVariable) t;
        Collection set = new HashSet();
        for (int i = 0; i < type.getNumTypeBound(); i++) {
          set.add(type.getTypeBound(i).type());
        }
        return set;
      } else {
        throw new Error("Operation not supported for " + t.fullName() + ", " + t.getClass().getName());
      }
    }

  

    public static Collection parameterizedSupertypes(TypeDecl type) {
      Collection result = new HashSet();
      addParameterizedSupertypes(type, new HashSet(), result);
      return result;
    }

  

    public static void addParameterizedSupertypes(TypeDecl type, Collection processed,
        Collection result) {
      if (!processed.contains(type)) {
        processed.add(type);
        if (type.isParameterizedType()) {
          result.add((ParTypeDecl) type);
        }
        for (TypeDecl typeDecl : directSupertypes(type)) {
          addParameterizedSupertypes(typeDecl, processed, result);
        }
      }
    }

  

    public Collection typeArguments() {
      Collection list = new ArrayList(typeVariables.size());
      for (TypeVariable T : typeVariables) {
        ConstraintSet set = constraintsMap.get(T);
        list.add(set.typeArgument);
      }
      return list;
    }

  

    public void addSupertypeConstraint(TypeDecl T, TypeDecl A) {
      ConstraintSet set = constraintsMap.get(T);
      set.supertypeConstraints.add(A);
    }

  

    public void addSubtypeConstraint(TypeDecl T, TypeDecl A) {
      ConstraintSet set = constraintsMap.get(T);
      set.subtypeConstraints.add(A);
    }

  

    /**
     * T = A  : T and A are the same type.
     *
     * 

This assigns type A to the type variable T. * *

It could happen that T and A refer to the same object, if the generic * method call is recursive. It is important to still add the * constraint T = T even though it may seen redundant: one type variable * represents the type variable in the generic method call, and one type * variable represents a type in the context of the method call. Removing * a constraint T = T removes information from the type inference and * breaks existing tests. See the regression test generics/method_23p. */ public void addEqualConstraint(TypeDecl T, TypeDecl A) { ConstraintSet set = constraintsMap.get(T); set.equaltypeConstraints.add(A); } /** A << F : A is convertible to F by method invocation conversion. */ public void convertibleTo(TypeDecl A, TypeDecl F) { // If F does not involve a type parameter Tj then no constraint is implied on Tj. if (!F.involvesTypeParameters()) { return; } // If A is the type of null, no constraint is implied on Tj. if (A.isNull()) { return; } // If A is a primitive type, then A is converted to a reference type U via boxing conversion // and this algorithm is applied recursively to the constraint U << F. if (A.isUnboxedPrimitive()) { TypeDecl U = A.boxed(); convertibleTo(U, F); } else if (F instanceof TypeVariable) { // If F = Tj, then the constraint Tj :> A is implied. if (typeVariables.contains(F)) { addSupertypeConstraint(F, A); } } else if (F.isArrayDecl()) { // If F = U[], where the type U involves Tj, then if A is an array type V[] // or a type variable with an upper bound that is an array type V[], // where V is a reference type, this algorithm is applied recursively // to the constraint V << U. TypeDecl U = ((ArrayDecl) F).componentType(); if (!U.involvesTypeParameters()) { return; } if (A.isArrayDecl()) { TypeDecl V = ((ArrayDecl) A).componentType(); if (V.isReferenceType()) { convertibleTo(V, U); } } else if (A.isTypeVariable()) { TypeVariable t = (TypeVariable) A; for (int i = 0; i < t.getNumTypeBound(); i++) { TypeDecl typeBound = t.getTypeBound(i).type(); if (typeBound.isArrayDecl() && ((ArrayDecl) typeBound).componentType().isReferenceType()) { TypeDecl V = ((ArrayDecl) typeBound).componentType(); convertibleTo(V, U); } } } } else if (F instanceof ParTypeDecl && !F.isRawType()) { ParTypeDecl PF = (ParTypeDecl) F; for (ParTypeDecl PA : parameterizedSupertypes(A)) { if (PF.genericDecl() == PA.genericDecl()) { if (A.isRawType()) { rawAccess = true; } else { java.util.List pfArgs = PF.getParameterization().args; java.util.List paArgs = PA.getParameterization().args; for (int i = 0; i < pfArgs.size(); i++) { TypeDecl T = pfArgs.get(i); if (T.involvesTypeParameters()) { if (!T.isWildcard()) { TypeDecl U = T; TypeDecl V = paArgs.get(i); constraintEqual(V, U); } else if (T instanceof WildcardExtendsType) { TypeDecl U = ((WildcardExtendsType) T).getAccess().type(); TypeDecl S = paArgs.get(i); if (!S.isWildcard()) { TypeDecl V = S; convertibleTo(V, U); } else if (S instanceof WildcardExtendsType) { TypeDecl V = ((WildcardExtendsType) S).getAccess().type(); convertibleTo(V, U); } } else if (T instanceof WildcardSuperType) { TypeDecl U = ((WildcardSuperType) T).getAccess().type(); TypeDecl S = paArgs.get(i); if (!S.isWildcard()) { TypeDecl V = S; convertibleFrom(V, U); } else if (S instanceof WildcardSuperType) { TypeDecl V = ((WildcardSuperType) S).getAccess().type(); convertibleFrom(V, U); } } } } } } } } } /** A >> F : F is convertible to A by method invocation conversion. */ public void convertibleFrom(TypeDecl A, TypeDecl F) { // If F does not involve a type parameter Tj then no constraint is implied on Tj. if (!F.involvesTypeParameters()) { return; } else if (A.isNull()) { // If A is the type of null, no constraint is implied on Tj. return; } else if (F instanceof TypeVariable) { if (typeVariables.contains(F)) { addSubtypeConstraint(F, A); } } else if (F.isArrayDecl()) { TypeDecl U = ((ArrayDecl) F).componentType(); if (A.isArrayDecl()) { TypeDecl V = ((ArrayDecl) A).componentType(); convertibleFrom(V, U); } else if (A.isTypeVariable()) { TypeVariable t = (TypeVariable) A; for (int i = 0; i < t.getNumTypeBound(); i++) { TypeDecl typeBound = t.getTypeBound(i).type(); if (typeBound.isArrayDecl() && ((ArrayDecl) typeBound).componentType().isReferenceType()) { TypeDecl V = ((ArrayDecl) typeBound).componentType(); convertibleFrom(V, U); } } } } else if (F instanceof ParTypeDecl && !F.isRawType() && A instanceof ParTypeDecl && !A.isRawType()) { ParTypeDecl PF = (ParTypeDecl) F; ParTypeDecl PA = (ParTypeDecl) A; java.util.List pfArgs = PF.getParameterization().args; java.util.List paArgs = PA.getParameterization().args; TypeDecl G = PF.genericDecl(); TypeDecl H = PA.genericDecl(); for (int i = 0; i < pfArgs.size(); i++) { TypeDecl T = pfArgs.get(i); if (T.involvesTypeParameters()) { // If F has the form G<...,U,...> where U is a type expression that involves Tj. if (!T.isWildcard()) { TypeDecl U = T; if (G.instanceOf(H)) { if (H != G) { for (ParTypeDecl V : parameterizedSupertypes(F)) { if (!V.isRawType() && V.genericDecl() == H) { if (F.instanceOf((TypeDecl) V)) { convertibleFrom(A, (TypeDecl) V); } } } } else if (pfArgs.size() == paArgs.size()) { TypeDecl X = paArgs.get(i); if (!X.isWildcard()) { TypeDecl W = X; constraintEqual(W, U); } else if (X instanceof WildcardExtendsType) { TypeDecl W = ((WildcardExtendsType) X).getAccess().type(); convertibleFrom(W, U); } else if (X instanceof WildcardSuperType) { TypeDecl W = ((WildcardSuperType) X).getAccess().type(); convertibleTo(W, U); } } } } else if (T instanceof WildcardExtendsType) { TypeDecl U = ((WildcardExtendsType) T).getAccess().type(); if (G.instanceOf(H)) { if (H != G) { for (ParTypeDecl V : parameterizedSupertypes(F)) { if (!V.isRawType() && V.genericDecl() == H) { // Replace type argument Un with ? extends Un in V. ArrayList list = new ArrayList(); for (TypeDecl vArg : V.getParameterization().args) { list.add(vArg.asWildcardExtends()); } TypeDecl typeV = ((GenericTypeDecl) H).lookupParTypeDecl(list); convertibleFrom(A, typeV); } } } else if (pfArgs.size() == paArgs.size()) { TypeDecl X = paArgs.get(i); if (X instanceof WildcardExtendsType) { TypeDecl W = ((WildcardExtendsType) X).getAccess().type(); convertibleFrom(W, U); } } } } else if (T instanceof WildcardSuperType) { TypeDecl U = ((WildcardSuperType) T).getAccess().type(); if (G.instanceOf(H)) { if (H != G) { for (ParTypeDecl V : parameterizedSupertypes(F)) { if (!V.isRawType() && V.genericDecl() == H) { // Replace type argument Un with ? super Un in V. ArrayList list = new ArrayList(); for (TypeDecl vArg : V.getParameterization().args) { list.add(vArg.asWildcardExtends()); } TypeDecl typeV = ((GenericTypeDecl) H).lookupParTypeDecl(list); convertibleFrom(A, typeV); } } } else if (pfArgs.size() == paArgs.size()) { TypeDecl X = paArgs.get(i); if (X instanceof WildcardSuperType) { TypeDecl W = ((WildcardSuperType) X).getAccess().type(); convertibleTo(W, U); } } } } } } } else if (F.isRawType()) { rawAccess = true; } } public void constraintEqual(TypeDecl A, TypeDecl F) { // If F does not involve a type parameter Tj then no constraint is implied on Tj. if (!F.involvesTypeParameters()) { return; } else if (A.isNull()) { // If A is the type of null, no constraint is implied on Tj. return; } else if (F instanceof TypeVariable) { if (typeVariables.contains(F)) { addEqualConstraint(F, A); } } else if (F.isArrayDecl()) { TypeDecl U = ((ArrayDecl) F).componentType(); if (A.isArrayDecl()) { TypeDecl V = ((ArrayDecl) A).componentType(); constraintEqual(V, U); } else if (A.isTypeVariable()) { TypeVariable t = (TypeVariable) A; for (int i = 0; i < t.getNumTypeBound(); i++) { TypeDecl typeBound = t.getTypeBound(i).type(); if (typeBound.isArrayDecl() && ((ArrayDecl) typeBound).componentType().isReferenceType()) { TypeDecl V = ((ArrayDecl) typeBound).componentType(); constraintEqual(V, U); } } } } else if (F instanceof ParTypeDecl && !F.isRawType()) { if (A instanceof ParTypeDecl) { ParTypeDecl PF = (ParTypeDecl) F; ParTypeDecl PA = (ParTypeDecl) A; java.util.List pfArgs = PF.getParameterization().args; java.util.List paArgs = PA.getParameterization().args; if (PF.genericDecl() == PA.genericDecl()) { if (A.isRawType()) { rawAccess = true; } else for (int i = 0; i < pfArgs.size(); i++) { TypeDecl T = pfArgs.get(i); if (T.involvesTypeParameters()) { if (!T.isWildcard()) { TypeDecl U = T; TypeDecl V = paArgs.get(i); constraintEqual(V, U); } else if (T instanceof WildcardExtendsType) { TypeDecl U = ((WildcardExtendsType) T).getAccess().type(); TypeDecl S = paArgs.get(i); if (S instanceof WildcardExtendsType) { TypeDecl V = ((WildcardExtendsType) S).getAccess().type(); constraintEqual(V, U); } } else if (T instanceof WildcardSuperType) { TypeDecl U = ((WildcardSuperType) T).getAccess().type(); TypeDecl S = paArgs.get(i); if (S instanceof WildcardSuperType) { TypeDecl V = ((WildcardSuperType) S).getAccess().type(); constraintEqual(V, U); } } } } } } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy