/* * This file is part of the X10 project (http://x10-lang.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.opensource.org/licenses/eclipse-1.0.php * * This file was originally derived from the Polyglot extensible compiler framework. * * (C) Copyright 2000-2007 Polyglot project group, Cornell University * (C) Copyright IBM Corporation 2007-2012. */ package polyglot.types; import java.lang.reflect.Modifier; import java.util.*; import polyglot.ast.Binary; import polyglot.frontend.*; import polyglot.main.Report; import polyglot.main.Reporter; import polyglot.types.reflect.ClassFile; import polyglot.types.reflect.ClassFileLazyClassInitializer; import polyglot.util.*; import x10.constraint.XField; import x10.constraint.XFormula; import x10.constraint.XLit; import x10.constraint.XTerm; import x10.constraint.XVar; import x10.types.constraints.XTypeLit; import x10.errors.Errors; import x10.types.AsyncDef; import x10.types.AsyncDef_c; import x10.types.AtDef; import x10.types.AtDef_c; import x10.types.ClosureDef; import x10.types.ClosureDef_c; import x10.types.ClosureInstance; import x10.types.ClosureInstance_c; import x10.types.ClosureType; import x10.types.ConstrainedType; import x10.types.FunctionType; import x10.types.MacroType; import x10.types.MethodInstance_c; import x10.types.ParameterType; import x10.types.ThisDef; import x10.types.ThisDef_c; import x10.types.ThisInstance; import x10.types.ThisInstance_c; import x10.types.TypeDefMatcher; import x10.types.TypeParamSubst; import x10.types.X10ConstructorInstance_c; import x10.types.X10FieldDef_c; import x10.types.X10FieldInstance_c; import x10.types.X10LocalDef_c; import x10.types.X10LocalInstance_c; import x10.types.X10MethodDef_c; import x10.types.VoidType; import x10.types.X10ClassDef_c; import x10.types.X10ClassDef; import x10.types.X10ClassType; import x10.types.X10ConstructorDef; import x10.types.X10ConstructorDef_c; import x10.types.X10ConstructorInstance; import x10.types.X10Def; import x10.types.X10FieldDef; import x10.types.X10FieldInstance; import x10.types.MethodInstance; import x10.types.X10InitializerDef; import x10.types.X10InitializerDef_c; import x10.types.X10LocalDef; import x10.types.X10LocalInstance; import x10.types.X10MethodDef; import x10.types.X10ParsedClassType; import x10.types.X10ParsedClassType_c; import x10.types.X10TypeEnv; import x10.types.X10TypeEnv_c; import x10.types.XTypeTranslator; import x10.types.X10ProcedureInstance; import x10.types.constraints.CConstraint; import x10.types.constraints.CField; import x10.types.constraints.CLocal; import x10.types.constraints.ConstraintManager; import x10.types.constraints.SubtypeConstraint; import x10.types.constraints.TypeConstraint; import x10.types.constraints.xnative.CNativeLocal; import x10.types.matcher.*; import x10.util.ClosureSynthesizer; import x10.util.CollectionFactory; import x10.X10CompilerOptions; /** * A TypeSystem implementation for X10 adapted from the Polyglot implementation of the Java type system. * * @author Christian Grothoff * @author Christoph von Praun * @author vj */ public class TypeSystem_c implements TypeSystem { private static volatile int counter = 0; protected SystemResolver systemResolver; protected TopLevelResolver loadedResolver; protected final ExtensionInfo extInfo; protected final Reporter reporter; private final Throwable creator; private final int creationTime; public TypeSystem_c(ExtensionInfo extInfo) { this.extInfo = extInfo; this.creator = new Throwable().fillInStackTrace(); this.creationTime = counter++; this.reporter = extInfo.getOptions().reporter; EMPTY_CONTEXT = emptyContext(); if (reporter.should_report("TypeSystem", 1)) reporter.report(1, "Creating " + getClass() + " at " + creationTime); } /** * Initializes the type system and its internal constants (which depend on * the resolver). */ public void initialize(TopLevelResolver loadedResolver) { if (reporter.should_report(Reporter.types, 1)) reporter.report(1, "Initializing " + getClass().getName()); // The loaded class resolver. This resolver automatically loads types // from class files and from source files not mentioned on the command // line. this.loadedResolver = loadedResolver; // The system class resolver. The class resolver contains a map from // fully qualified names to instances of Named. A pass over a // compilation unit looks up classes first in its // import table and then in the system resolver. this.systemResolver = new SystemResolver(loadedResolver, extInfo); initEnums(); initTypes(); } protected void initEnums() { // Ensure the enums in the type system are initialized and interned // before any deserialization occurs. // Just force the static initializers of ClassType and PrimitiveType // to run. Object o; o = ClassDef.TOP_LEVEL; } public enum Bound { UPPER, LOWER, EQUAL } public static enum Kind { NEITHER, EITHER, OBJECT, STRUCT, INTERFACE } protected void initTypes() { // FIXME: don't do this when rewriting a type system! // Prime the resolver cache so that we don't need to check // later if these are loaded. // We cache the most commonly used ones in fields. /* DISABLED CACHING OF COMMON CLASSES; CAUSES PROBLEMS IF COMPILING CORE CLASSES (e.g. java.lang package). TODO: Longer term fix. Maybe a flag to tell if we are compiling core classes? XXX Object(); Class(); String(); Throwable(); systemResolver.find("java.lang.Error"); systemResolver.find("java.lang.Exception"); systemResolver.find("java.lang.RuntimeException"); systemResolver.find("java.lang.Cloneable"); systemResolver.find("java.io.Serializable"); systemResolver.find("java.lang.NullPointerException"); systemResolver.find("java.lang.ClassCastException"); systemResolver.find("java.lang.ArrayIndexOutOfBoundsException"); systemResolver.find("java.lang.ArrayStoreException"); systemResolver.find("java.lang.ArithmeticException"); */ } /** Return the language extension this type system is for. */ public ExtensionInfo extensionInfo() { return extInfo; } public SystemResolver systemResolver() { return systemResolver; } public static class FilteringMatcher<T, U extends T> extends BaseMatcher<U> { private Matcher<T> matcher; private Class<U> filter; public FilteringMatcher(Matcher<T> matcher, Class<U> filter) { this.matcher = matcher; this.filter = filter; } @SuppressWarnings("unchecked") // Casting to a generic type argument public U instantiate(U matched) throws SemanticException { if (filter.isInstance(matched)) { T result = matcher.instantiate(matched); if (filter.isInstance(result)) { return (U) result; } } return null; } public java.lang.Object key() { return matcher.key(); } public Name name() { return matcher.name(); } public java.lang.String signature() { return matcher.signature(); } } /** * Return the system resolver. This used to return a different resolver. * enclosed in the system resolver. * @deprecated */ public CachingResolver parsedResolver() { return systemResolver; } public TopLevelResolver loadedResolver() { return loadedResolver; } public ClassFileLazyClassInitializer classFileLazyClassInitializer(ClassFile clazz) { return new ClassFileLazyClassInitializer(clazz, this); } public ImportTable importTable(String sourceName, Ref<? extends Package> pkg) { assert_(pkg); return new ImportTable(this, pkg, sourceName); } public ImportTable importTable(Ref<? extends Package> pkg) { assert_(pkg); return new ImportTable(this, pkg); } /** * Returns true if the package named <code>name</code> exists. */ public boolean packageExists(QName name) { return systemResolver.packageExists(name); } protected void assert_(Collection<?> l) { for (Iterator<?> i = l.iterator(); i.hasNext(); ) { Object o = i.next(); if (o instanceof TypeObject) { assert_((TypeObject) o); } else if (o instanceof Ref<?>) { assert_((Ref<?>) o); } } } protected void assert_(Ref<?> ref) { } private static void printTypeSystem(java.io.PrintStream out, TypeSystem_c ts) { out.print(ts); if (ts == null) return; out.print("(" + ts.creationTime + "): "); ts.creator.printStackTrace(out); } protected void assert_(TypeObject o) { if (o != null && o.typeSystem() != this) { TypeSystem_c ots = (TypeSystem_c) o.typeSystem(); System.err.print("we are "); printTypeSystem(System.err, this); System.err.print(" but " + o + " ("+o.getClass()+")" + " is from "); printTypeSystem(System.err, ots); throw new InternalCompilerError("we are " + this + " but " + o + " ("+o.getClass()+")" + " is from " + ots); } } public String wrapperTypeString(Type t) { assert_(t); if (t.isBoolean()) return "java.lang.Boolean"; if (t.isChar()) return "java.lang.Character"; if (t.isByte()) return "java.lang.Byte"; if (t.isShort()) return "java.lang.Short"; if (t.isInt()) return "java.lang.Integer"; if (t.isLong()) return "java.lang.Long"; if (t.isFloat()) return "java.lang.Float"; if (t.isDouble()) return "java.lang.Double"; if (t.isVoid()) return "java.lang.Void"; throw new InternalCompilerError("Unrecognized primitive type " + t); } /** @deprecated */ public Resolver packageContextResolver(Resolver cr, Package p) { return packageContextResolver(p); } public AccessControlResolver createPackageContextResolver(Package p) { assert_(p); return new PackageContextResolver(this, p); } public Resolver packageContextResolver(Package p, ClassDef accessor, Context context) { if (accessor == null) { return p.resolver(); } else { return new AccessControlWrapperResolver(createPackageContextResolver(p), context); } } public Resolver packageContextResolver(Package p) { assert_(p); return packageContextResolver(p, null, emptyContext()); } public Resolver classContextResolver(final Type type, Context context) { assert_(type); if (context == null) { if (type instanceof ClassType) { return ((ClassType) type).resolver(); } return new Resolver() { public List<Type> find(Matcher<Type> matcher) throws SemanticException { throw new NoClassException(matcher.name().toString(), type); } }; } else { return new AccessControlWrapperResolver(createClassContextResolver(type), context); } } public Resolver classContextResolver(Type type) { return classContextResolver(type, emptyContext()); } public AccessControlResolver createClassContextResolver(Type type) { assert_(type); return new ClassContextResolver(this, type); } public List<LocalDef> dummyLocalDefs(List<Ref<? extends Type>> types) { List<LocalDef> list = new ArrayList<LocalDef>(); for (int i = 0; i < types.size(); i++) { LocalDef ld = localDef(Position.COMPILER_GENERATED, Flags.FINAL, types.get(i), Name.make("a" + (i + 1))); ld.setNotConstant(); list.add(ld); } return list; } public X10ConstructorDef defaultConstructor(Position pos, Position errorPos, Ref<? extends ClassType> container) { assert_(container); // access for the default constructor is determined by the // access of the containing class. See the JLS, 2nd Ed., 8.8.7. Flags access = Flags.NONE; Flags flags = container.get().flags(); if (flags.isPrivate()) { access = access.Private(); } if (flags.isProtected()) { access = access.Protected(); } if (flags.isPublic()) { access = access.Public(); } return constructorDef(pos, errorPos, container, access, Collections.<Ref<? extends Type>>emptyList(), Collections.<Ref<? extends Type>>emptyList() ); } public X10ConstructorDef constructorDef(Position pos, Position errorPos, Ref<? extends ClassType> container, Flags flags, List<Ref<? extends Type>> argTypes, List<Ref<? extends Type>> throwsTypes) { return constructorDef(pos, errorPos, container, flags, argTypes, throwsTypes, null); } public X10ConstructorDef constructorDef(Position pos, Position errorPos, Ref<? extends ClassType> container, Flags flags, List<Ref<? extends Type>> argTypes, List<Ref<? extends Type>> throwsTypes, Ref<? extends Type> offerType) { assert_(container); assert_(argTypes); ThisDef thisDef = ((X10ClassType) Types.get(container)).x10Def().thisDef(); return constructorDef(pos, errorPos, container, flags, Types.ref(Types.get(container)), argTypes, throwsTypes, thisDef, dummyLocalDefs(argTypes), null, null, offerType); } public X10ConstructorDef constructorDef(Position pos, Position errorPos, Ref<? extends ContainerType> container, Flags flags, Ref<? extends Type> returnType, List<Ref<? extends Type>> argTypes, List<Ref<? extends Type>> throwsTypes, ThisDef thisDef, List<LocalDef> formalNames, Ref<CConstraint> guard, Ref<TypeConstraint> typeGuard, Ref<? extends Type> offerType) { assert_(container); assert_(argTypes); return new X10ConstructorDef_c(this, pos, errorPos, container, flags, returnType, argTypes, throwsTypes, thisDef, formalNames, guard, typeGuard, offerType); } public X10InitializerDef initializerDef(Position pos, Ref<? extends ClassType> container, Flags flags) { // String fullNameWithThis = "<init>#this"; XVar thisVar = ConstraintManager.getConstraintSystem().makeThis(); // XTerms.makeLocal(thisName); return initializerDef(pos, container, flags, thisVar); } public X10InitializerDef initializerDef(Position pos, Ref<? extends ClassType> container, Flags flags, XVar thisVar) { assert_(container); return new X10InitializerDef_c(this, pos, container, flags, thisVar); } public X10FieldDef fieldDef(Position pos, Ref<? extends ContainerType> container, Flags flags, Ref<? extends Type> type, Name name) { assert_(container); assert_(type); ThisDef thisDef = ((X10ClassType) Types.get(container)).x10Def().thisDef(); return fieldDef(pos, container, flags, type, name, thisDef); } public X10FieldDef fieldDef(Position pos, Ref<? extends ContainerType> container, Flags flags, Ref<? extends Type> type, Name name, ThisDef thisDef) { assert_(container); assert_(type); return new X10FieldDef_c(this, pos, container, flags, type, name, thisDef); } public X10MethodDef methodDef(Position pos, Position errorPos, Ref<? extends ContainerType> container, Flags flags, Ref<? extends Type> returnType, Name name, List<Ref<? extends Type>> argTypes, List<Ref<? extends Type>> throwsTypes) { return methodDef(pos, errorPos, container, flags, returnType, name, argTypes, throwsTypes, null); } public X10MethodDef methodDef(Position pos, Position errorPos, Ref<? extends ContainerType> container, Flags flags, Ref<? extends Type> returnType, Name name, List<Ref<? extends Type>> argTypes, List<Ref<? extends Type>> throwsTypes, Ref<? extends Type> offerType) { ThisDef thisDef = ((X10ClassType) Types.get(container)).x10Def().thisDef(); assert (!name.toString().contains(AtDef.DUMMY_AT_ASYNC)); // set up null thisVar for method def's, so the outer contexts are searched for thisVar. return methodDef(pos, errorPos, container, flags, returnType, name, Collections.<ParameterType>emptyList(), argTypes, throwsTypes, thisDef, dummyLocalDefs(argTypes), null, null, offerType, null); } public X10MethodDef methodDef(Position pos, Position errorPos, Ref<? extends ContainerType> container, Flags flags, Ref<? extends Type> returnType, Name name, List<ParameterType> typeParams, List<Ref<? extends Type>> argTypes, List<Ref<? extends Type>> throwsTypes, ThisDef thisDef, List<LocalDef> formalNames, Ref<CConstraint> guard, Ref<TypeConstraint> typeGuard, Ref<? extends Type> offerType, Ref<XTerm> body) { assert_(container); assert_(returnType); assert_(typeParams); assert_(argTypes); return new X10MethodDef_c(this, pos, errorPos, container, flags, returnType, name, typeParams, argTypes, throwsTypes, thisDef, formalNames, guard, typeGuard, offerType, body); } public ClassDef classDefOf(Type t) { t = Types.baseType(t); if (t instanceof ClassType) return ((ClassType) t).def(); return null; } /** * Returns true iff child and ancestor are object types and child descends * from or equals ancestor. **/ public boolean descendsFrom(ClassDef child, ClassDef ancestor) { if (child == ancestor) return true; ClassDef a = classDefOf(Any()); if (ancestor == a) return true; if (child == a) return false; Type sup = Types.get(child.superType()); if (sup != null && classDefOf(sup) != null) { if (descendsFrom(classDefOf(sup), ancestor)) { return true; } } // Next check interfaces. for (Ref<? extends Type> parentType : child.interfaces()) { Type t = Types.get(parentType); if (t != null && classDefOf(t) != null) { if (descendsFrom(classDefOf(t), ancestor)) { return true; } } } return false; } /** * Requires: all type arguments are canonical. ToType is not a NullType. * * Returns true iff a cast from fromType to toType is valid; in other * words, some non-null members of fromType are also members of toType. **/ public boolean isCastValid(Type fromType, Type toType, Context context) { assert_(fromType); assert_(toType); return env(context).isCastValid(fromType, toType); } /** * Requires: all type arguments are canonical. * * Returns true iff an implicit cast from fromType to toType is valid; * in other words, every member of fromType is member of toType. * * Returns true iff child and ancestor are non-primitive * types, and a variable of type child may be legally assigned * to a variable of type ancestor. * */ public boolean isImplicitCastValid(Type fromType, Type toType, Context context) { assert_(fromType); assert_(toType); return env(context).isImplicitCastValid(fromType, toType); } /** * Returns true iff type1 and type2 represent the same type object. */ public boolean equals(TypeObject type1, TypeObject type2) { assert_(type1); assert_(type2); if (type1 == type2) return true; if (type1 == null || type2 == null) return false; return type1.equalsImpl(type2); } public final void equals(Type type1, Type type2) { assert false; } public final void equals(Type type1, TypeObject type2) { assert false; } public final void equals(TypeObject type1, Type type2) { assert false; } public boolean equalsStruct(Type l, Type r) { // if (l instanceof ParameterType && r instanceof ParameterType) { // return TypeParamSubst.isSameParameter((ParameterType) l, // (ParameterType) r); // } return equals((TypeObject) l, (TypeObject) r); } /** * Returns true iff type1 and type2 are equivalent. */ public boolean typeEquals(Type type1, Type type2, Context context) { assert_(type1); assert_(type2); return env(context).typeEquals(type1, type2); } /** * Returns true iff type1 and type2 are equivalent. */ public boolean packageEquals(Package type1, Package type2) { assert_(type1); assert_(type2); return env(emptyContext()).packageEquals(type1, type2); } /** * Returns true if <code>value</code> can be implicitly cast to Primitive * type <code>t</code>. */ public boolean numericConversionValid(Type t, Object value, Context context) { assert_(t); return env(context).numericConversionValid(t, value); } /** * Returns true if <code>value</code> can be implicitly cast to Primitive * type <code>t</code>. This method should be removed. It is kept for * backward compatibility. */ public boolean numericConversionValid(Type t, long value, Context context) { assert_(t); return env(context).numericConversionValid(t, value); } //// // Functions for one-type checking and resolution. //// /** * Checks whether the member mi can be accessed from Context "context". */ public boolean isAccessible(MemberInstance<?> mi, Context context) { assert_(mi); return env(context).isAccessible(mi); } /** True if the class targetClass accessible from the context. */ public boolean classAccessible(ClassDef targetClass, Context context) { assert_(targetClass); return env(context).classAccessible(targetClass); } /** True if the class targetClass accessible from the package pkg. */ public boolean classAccessibleFromPackage(ClassDef targetClass, Package pkg) { assert_(targetClass); return env(emptyContext()).classAccessibleFromPackage(targetClass, pkg); } /** * Return true if a member (in an accessible container) or a * top-level class with access flags <code>flags</code> * in package <code>pkg1</code> is accessible from package * <code>pkg2</code>. */ protected boolean accessibleFromPackage(Flags flags, Package pkg1, Package pkg2) { return env(emptyContext()).accessibleFromPackage(flags, pkg1, pkg2); } public boolean isEnclosed(ClassDef inner, ClassDef outer) { return inner.asType().isEnclosed(outer.asType()); } public boolean hasEnclosingInstance(ClassDef inner, ClassDef encl) { return inner.asType().hasEnclosingInstance(encl.asType()); } public void checkCycles(Type goal) throws SemanticException { checkCycles(Types.getDef(goal), Types.getDef(goal)); } protected void checkCycles(X10ClassDef_c curr, X10ClassDef_c goal) throws SemanticException { assert_(curr); assert_(goal); if (curr == null) { return; } final Ref<? extends Type> superRef = curr.superType(); X10ClassDef_c superType = superRef==null ? null : Types.getDef(superRef.get()); if (goal == superType) { throw new SemanticException("Circular inheritance involving " + goal,curr.errorPosition()); } checkCycles(superType, goal); for (Ref<? extends Type> siType : curr.interfaces()) { X10ClassDef_c si = Types.getDef(siType.get()); if (si == goal) { throw new SemanticException("Circular inheritance involving " + goal,curr.errorPosition()); } checkCycles(si, goal); } final Ref<? extends ClassDef> outerRef = curr.outer(); if (outerRef!=null) checkCycles((X10ClassDef_c) outerRef.get(), goal); } //// // Various one-type predicates. //// /** * Returns true iff the type t can be coerced to a String in the given * Context. If a type can be coerced to a String then it can be * concatenated with Strings, e.g. if o is of type T, then the code snippet * "" + o * would be allowed. */ public boolean canCoerceToString(Type t, Context c) { return env(c).canCoerceToString(t); } public boolean isUByte(Type t) { return finalSubtype(t,UByte()); } public boolean isUShort(Type t) { return finalSubtype(t,UShort()); } public boolean isUInt(Type t) { return finalSubtype(t,UInt()); } public boolean isULong(Type t) { return finalSubtype(t,ULong()); } public boolean isNumeric(Type t) { return isSignedNumeric(t) || isUnsignedNumeric(t) || isFloat(t) || isDouble(t); } public boolean isSignedNumeric(Type t) { return isByte(t) || isShort(t) || isInt(t) || isLong(t); } public boolean isUnsignedNumeric(Type t) { return isUByte(t) || isUShort(t) || isUInt(t) || isULong(t); } public boolean isIntOrLess(Type t) { return isByte(t) || isShort(t) || isInt(t) || isUByte(t) || isUShort(t); } public boolean isLongOrLess(Type t) { return isSignedNumeric(t) || isUnsignedNumeric(t); } public boolean isBoolean(Type t) { return finalSubtype(t,Boolean()); } public boolean isChar(Type t) { return finalSubtype(t,Char()); } public boolean isByte(Type t) { return finalSubtype(t,Byte()); } public boolean isShort(Type t) { return finalSubtype(t,Short()); } public boolean isInt(Type t) { return finalSubtype(t,Int()); } public boolean isLong(Type t) { return finalSubtype(t,Long()); } public boolean isFloat(Type t) { return finalSubtype(t,Float()); } public boolean isDouble(Type t) { return finalSubtype(t,Double()); } private final Context EMPTY_CONTEXT; // the context is a mutable object, but in isSubtype we do not mutate it. private boolean emptyContextSubtype(Type t, X10ClassType xlass) { return isSubtype(t, xlass, EMPTY_CONTEXT); } /** * A shortcut version of the subtype test -- only works if xclass cannot be subclassed. * @param t the type to test * @param xlass the potential supertype * @return true if t is a subtype of xclass, and false otherwise */ private boolean finalSubtype(Type t, X10ClassType xlass) { assert xlass.flags().isStruct() || xlass.flags().isFinal(); return hasSameClassDef(t,xlass) || isUnknown(t); } /** * Returns true iff an object of type <type> may be thrown. **/ public boolean isThrowable(Type type) { assert_(type); return emptyContextSubtype(type,CheckedThrowable()); } public boolean isException(Type type) { assert_(type); return emptyContextSubtype(type,Exception()); } public boolean isError(Type type) { assert_(type); return emptyContextSubtype(type,Error()); } /** * Returns a true iff the type or a supertype is in the list returned by * uncheckedExceptions(). */ public boolean isUncheckedException(Type type) { return isException(type) || isError(type); } /** * Returns a list of the Throwable types that need not be declared * in method and constructor signatures. */ public Collection<Type> uncheckedExceptions() { List<Type> l = new ArrayList<Type>(1); l.add(Exception()); l.add(Error()); return l; } public boolean isSubtype(Type t1, Type t2, Context context) { assert_(t1); assert_(t2); return env(context).isSubtype(t1, t2); } public boolean isSubtype(Type t1, Type t2) { return isSubtype(t1, t2, emptyContext()); } public MacroType findTypeDef(Type container, Name name, List<Type> typeArgs, List<Type> argTypes, Context context) throws SemanticException { TypeDefMatcher matcher = new TypeDefMatcher(container,name,typeArgs,argTypes,context); List<MacroType> acceptable = findAcceptableTypeDefs(container, matcher, context); if (acceptable.size() == 0) { throw new SemanticException("No valid type definition found for " + matcher.signature() + " in " + container + "."); } Collection<MacroType> maximal = findMostSpecificProcedures(acceptable, new FilteringMatcher<Type, MacroType>(matcher, MacroType.class), context); if (maximal.size() > 1) { // remove references that resolve to the same type. Collection<Type> reduced = Collections.<Type>emptyList(); Collection<MacroType> max2 = Collections.<MacroType>emptyList(); for (MacroType mt : maximal) { Type expanded = Types.baseType(mt); if (! reduced.contains(expanded)) { reduced.add(expanded); max2.add(mt); } } maximal = max2; } if (maximal.size() > 1) { StringBuffer sb = new StringBuffer(); for (Iterator<MacroType> i = maximal.iterator(); i.hasNext();) { MacroType ma = (MacroType) i.next(); sb.append(ma.returnType()); sb.append(" "); sb.append(ma.container()); sb.append("."); sb.append(ma.signature()); if (i.hasNext()) { if (maximal.size() == 2) { sb.append(" and "); } else { sb.append(", "); } } } throw new SemanticException("Reference to " + matcher.name() + " is ambiguous, multiple type defintions match: " + sb.toString()); } MacroType mi = maximal.iterator().next(); return mi; } public List<MacroType> findTypeDefs(Type container, Name name, ClassDef currClass) throws SemanticException { assert_(container); // Named n = classContextResolver(container, currClass).find(name); // // if (n instanceof MacroType) { // return (MacroType) n; // } throw new NoClassException(name.toString(), container); } //// // Functions for type membership. //// /** * Returns a set of fields named <code>name</code> defined * in type <code>container</code> or a supertype. The list * returned may be empty. */ private Set<FieldInstance> findFields(Type container, TypeSystem_c.FieldMatcher matcher) { assert_(container); Set<FieldInstance> candidates = CollectionFactory.newHashSet(); for (Type t : env(matcher.context()).upperBounds(container, true)) { Set<FieldInstance> fs = superFindFields(t, matcher); candidates.addAll(fs); } return candidates; } private Set<FieldInstance> superFindFields(Type container, TypeSystem_c.FieldMatcher matcher) { if (!matcher.visit(container)) return Collections.<FieldInstance>emptySet(); Name name = matcher.name(); assert_(container); if (container == null) { throw new InternalCompilerError("Cannot access field \"" + name + "\" within a null container type."); } if (container instanceof ContainerType) { FieldInstance fi = ((ContainerType) container).fieldNamed(name); if (fi != null) { try { fi = matcher.instantiate(fi); if (fi != null) return Collections.singleton(fi); } catch (SemanticException e) { } return Collections.<FieldInstance>emptySet(); } } Set<FieldInstance> fields = CollectionFactory.newHashSet(); if (container instanceof ObjectType) { ObjectType ot = (ObjectType) container; if (ot.superClass() != null && ot.superClass() instanceof ContainerType) { Set<FieldInstance> superFields = findFields((ContainerType) ot.superClass(), matcher); fields.addAll(superFields); } for (Type it : ot.interfaces()) { if (it instanceof ContainerType) { Set<FieldInstance> superFields = findFields((ContainerType) it, matcher); fields.addAll(superFields); } } } return fields; } public List<MacroType> findAcceptableTypeDefs(Type container, TypeDefMatcher matcher, Context context) throws SemanticException { assert_(container); return env(context).findAcceptableTypeDefs(container, matcher); } public Type findMemberType(Type container, Name name, Context context) throws SemanticException { // FIXME: check for ambiguities X10TypeEnv env = env(context); for (Type t : env.upperBounds(container, true)) { try { return env.findMemberType(t, name); } catch (SemanticException e) { } try { return this.findTypeDef(t, name, Collections.<Type>emptyList(), Collections.<Type>emptyList(), context); } catch (SemanticException e) { } } throw new NoClassException(name.toString(), container); } /** * Returns the list of methods with the given name defined or inherited * into container, checking if the methods are accessible from the * body of currClass */ public boolean hasMethodNamed(Type container, Name name) { if (container != null) container = Types.baseType(container); // HACK: use the def rather than the type to avoid gratuitous // reinstantiation of methods. if (container instanceof ClassType) { ClassType ct = (ClassType) container; for (MethodDef md : ct.def().methods()) { if (md.name().equals(name)) return true; } Type superType = Types.get(ct.def().superType()); if (superType != null && hasMethodNamed(superType, name)) return true; for (Ref<? extends Type> tref : ct.def().interfaces()) { Type ti = Types.get(tref); if (ti != null && hasMethodNamed(ti, name)) return true; } } if (container == null) { throw new InternalCompilerError("Cannot access method \"" + name + "\" within a null container type."); } if (container instanceof ContainerType) { if (! ((ContainerType) container).methodsNamed(name).isEmpty()) { return true; } } if (container instanceof ObjectType) { ObjectType ot = (ObjectType) container; if (ot.superClass() != null && ot.superClass() instanceof ContainerType) { if (hasMethodNamed((ContainerType) ot.superClass(), name)) { return true; } } for (Type it : ot.interfaces()) { if (it instanceof ContainerType) { if (hasMethodNamed((ContainerType) it, name)) { return true; } } } if (!ot.isAny() && hasMethodNamed((ContainerType)Any(), name)) return true; } return false; } public static class ConstructorMatcher extends BaseMatcher<ConstructorInstance> { protected final Type container; public final List<Type> argTypes; public final List<Type> typeArgs; protected final Context context; public final boolean isDumbMatcher; protected ConstructorMatcher(Type container, List<Type> typeArgs, List<Type> argTypes, Context context, boolean isDumbMatcher) { super(); this.container = container; this.argTypes = argTypes; this.typeArgs = typeArgs; this.isDumbMatcher = isDumbMatcher; this.context = context; } public Context context() { return context; } public Type container() { return container; } public Name name() { return Name.make(CONSTRUCTOR_NAME); } public String signature() { return container + argumentString(); } public List<Type> arguments() { return argTypes; } public String argumentString() { return "(" + CollectionUtil.listToString(argTypes) + ")"; } public ConstructorInstance instantiate(ConstructorInstance ci) throws SemanticException { if (ci.formalTypes().size() != argTypes.size()) return null; if (ci instanceof X10ConstructorInstance) { X10ConstructorInstance xmi = (X10ConstructorInstance) ci; Type c = container != null ? container : xmi.container(); if (isDumbMatcher) { X10ConstructorInstance newXmi = x10.types.matcher.Matcher.instantiate((Context) context, xmi, c, Collections.<Type>emptyList(), argTypes); return newXmi; } return x10.types.matcher.Matcher.inferAndCheckAndInstantiate(context(), xmi, c, Collections.<Type>emptyList(), argTypes, ci.position()); } return null; } public String toString() { return signature(); } public Object key() { return null; } } public static class MethodMatcher extends BaseMatcher<MethodInstance> implements Cloneable { protected Type container; protected final Name name; protected final List<Type> argTypes; protected final List<Type> typeArgs; protected final Context context; protected final boolean isDumbMatcher; protected MethodMatcher(Type container, Name name, List<Type> typeArgs, List<Type> argTypes, Context context, boolean isDumbMatcher) { super(); this.container = container; this.name = name; this.argTypes = argTypes; this.typeArgs = typeArgs; this.context = context; this.isDumbMatcher = isDumbMatcher; } public MethodMatcher container(Type container) { MethodMatcher n = shallowCopy(); n.container = container; return n; } public Type container() { return container; } public MethodMatcher shallowCopy() { try { return (MethodMatcher) super.clone(); } catch (CloneNotSupportedException e) { throw new InternalCompilerError(e); } } public String signature() { return name + argumentString(); } public Name name() { return name; } public MethodInstance instantiate(MethodInstance mi) throws SemanticException { if (!mi.name().equals(name)) return null; if (mi.formalTypes().size() != argTypes.size()) return null; Type c = container != null ? container : mi.container(); if (isDumbMatcher) { if (typeArgs.size() != mi.typeParameters().size()) return null; if (typeArgs.size() == mi.typeParameters().size()) { MethodInstance newXmi = x10.types.matcher.Matcher.instantiate((Context) context, mi, c, typeArgs, argTypes); return newXmi; } } else { if (typeArgs.isEmpty() || typeArgs.size() == mi.typeParameters().size()) return x10.types.matcher.Matcher.inferAndCheckAndInstantiate(context, mi, c, typeArgs, argTypes, mi.position()); } return null; } public final String typeArgsString() { return (typeArgs.isEmpty() ? "" : "[" + CollectionUtil.listToString(typeArgs) + "]"); } public String stripConstraints() { return name + typeArgsString() + "(" + CollectionUtil.listToString(Types.stripConstraintsIfDynamicCalls(argTypes)) + ")"; } public final String argumentString() { return typeArgsString() + "(" + CollectionUtil.listToString(argTypes) + ")"; } public final List<Type> arguments() { return argTypes; } public String toString() { return signature(); } public Object key() { return null; } public Context context() { return context; } } public static class FieldMatcher extends BaseMatcher<FieldInstance> implements Cloneable { protected Type container; protected Name name; protected Context context; protected FieldMatcher(Type container, Name name, Context context) { super(); this.container = container; this.name = name; this.context = context; } public Context context() { return context; } public Type container() { return container; } public FieldMatcher container(Type container) { FieldMatcher n = shallowCopy(); n.container = container; return n; } public FieldMatcher shallowCopy() { try { return (FieldMatcher) super.clone(); } catch (CloneNotSupportedException e) { throw new InternalCompilerError(e); } } public String signature() { return name.toString(); } public Name name() { return name; } public FieldInstance instantiate(FieldInstance mi) throws SemanticException { if (! mi.name().equals(name)) { return null; } return mi; } public String toString() { return signature(); } public Object key() { return null; } } // To prevent infinite recursion due to searching the field in the superclass/superinterface // e.g., class Q extends Q{i==1} {} public static abstract class BaseMatcher<T> implements Matcher<T> { private Set<Type> visitedDefs; public boolean visit(Type t) { if (visitedDefs==null) visitedDefs = CollectionFactory.newHashSet(); final Type p = Types.baseType(t); if (visitedDefs.contains(p)) return false; visitedDefs.add(p); return true; } } public static abstract class NameMatcher<T extends Named> extends BaseMatcher<T> { protected Name name; protected NameMatcher(Name name) { this.name = name; } public String signature() { return name.toString(); } public Name name() { return name; } public T instantiate(T t) throws SemanticException { if (t.name() == null || !t.name().equals(name)) { return null; } return t; } public String toString() { return signature(); } public Object key() { return name; } } public static abstract class MemberTypeMatcher extends NameMatcher<Type> { protected Type container; protected Context context; protected MemberTypeMatcher(Type container, Name name, Context context) { super(name); this.container = container; this.context = context; } public Type container() { return container; } public String signature() { return container/*.fullName()*/ + "." + name; } public Object key() { return QName.make(container.fullName(), name); } } public static abstract class TypeMatcher extends NameMatcher<Type> { protected TypeMatcher(Name name) { super(name); } } public Matcher<Type> MemberTypeMatcher(Type container, Name name, Context context) { return new X10MemberTypeMatcher(container, name, context); } public Matcher<Type> TypeMatcher(Name name) { return new X10TypeMatcher(name); } public MethodInstance SUPER_findMethod(Type container, MethodMatcher matcher) throws SemanticException { assert_(container); Context context = matcher.context(); List<MethodInstance> acceptable = findAcceptableMethods(container, matcher); if (acceptable.size() == 0) { throw new NoMemberException(NoMemberException.METHOD, "No valid method call found for call in given type." + "\n\t Call: " + matcher.stripConstraints() + "\n\t Type: " + Types.stripConstraintsIfDynamicCalls(container)); } Collection<MethodInstance> maximal = findMostSpecificProcedures(container, acceptable, (Matcher<MethodInstance>) matcher, context); if (maximal.size() > 1) { StringBuffer sb = new StringBuffer(); for (Iterator<MethodInstance> i = maximal.iterator(); i.hasNext();) { MethodInstance ma = i.next(); sb.append(ma.container()); sb.append("."); sb.append(ma.signature()); if (i.hasNext()) { if (maximal.size() == 2) { sb.append(" and "); } else { sb.append(", "); } } } throw Errors.MultipleMethodDefsMatch.make(maximal, matcher.toString(), Position.COMPILER_GENERATED); } MethodInstance mi = maximal.iterator().next(); return mi; } public ConstructorInstance SUPER_findConstructor(Type container, ConstructorMatcher matcher) throws SemanticException { assert_(container); Context context = matcher.context(); List<ConstructorInstance> acceptable = findAcceptableConstructors(container, matcher); if (acceptable.size() == 0) { throw new NoMemberException(NoMemberException.CONSTRUCTOR, "No valid constructor found for " + matcher.signature() + ")."); } Collection<ConstructorInstance> maximal = findMostSpecificProcedures(acceptable, matcher, context); if (maximal.size() > 1) { throw new NoMemberException(NoMemberException.CONSTRUCTOR, "Reference to " + container + " is ambiguous, multiple " + "constructors match: " + maximal); } ConstructorInstance ci = maximal.iterator().next(); return ci; } public <S extends ProcedureDef, T extends ProcedureInstance<S>> Collection<T> findMostSpecificProcedures(List<T> acceptable, Matcher<T> matcher, Context context) throws SemanticException { return findMostSpecificProcedures(null, acceptable, matcher, context); } public <S extends ProcedureDef, T extends ProcedureInstance<S>> Collection<T> findMostSpecificProcedures(Type container, List<T> acceptable, Matcher<T> matcher, Context context) throws SemanticException { // now, use JLS 15.11.2.2 // First sort from most- to least-specific. Comparator<T> msc = mostSpecificComparator(container, matcher, context); ArrayList<T> acceptable2 = new ArrayList<T>(acceptable); // make into array list to sort Collections.<T>sort(acceptable2, msc); List<T> maximal = new ArrayList<T>(acceptable2.size()); Iterator<T> i = acceptable2.iterator(); T first = i.next(); maximal.add(first); // Now check to make sure that we have a maximal most-specific method. while (i.hasNext()) { T p = i.next(); if (msc.compare(first, p) == X10MostSpecificComparator.NEITHER_MORE_SPECIFIC) { maximal.add(p); } if (msc.compare(p,first) == X10MostSpecificComparator.FIRST_MOST_SPECIFIC) { maximal.add(p); } } if (maximal.size() > 1) { // If exactly one method is not abstract, it is the most specific. List<T> notAbstract = new ArrayList<T>(maximal.size()); for (Iterator<T> j = maximal.iterator(); j.hasNext(); ) { T p = j.next(); if (! (p instanceof MemberInstance<?>) || ! ((MemberInstance<?>) p).flags().isAbstract()) { notAbstract.add(p); } } if (notAbstract.size() == 1) { maximal = notAbstract; } else if (notAbstract.size() == 0) { // all are abstract; if all signatures match, any will do. Iterator<T> j = maximal.iterator(); first = j.next(); S firstDecl = first.def(); List<Type> firstFormals = new TransformingList<Ref<? extends Type>,Type>(firstDecl.formalTypes(), new DerefTransform<Type>()); while (j.hasNext()) { T p = j.next(); // Use the declarations to compare formals. S pDecl = p.def(); List<Type> pFormals = new TransformingList<Ref<? extends Type>,Type>(pDecl.formalTypes(), new DerefTransform<Type>()); if (! CollectionUtil.allElementwise(firstFormals, pFormals, new TypeEquals(context))) { // not all signatures match; must be ambiguous return maximal; } } // all signatures match, just take the first maximal = Collections.<T>singletonList(first); } } return maximal; } public static class TypeEquals implements Predicate2<Type> { Context context; public TypeEquals(Context context) { this.context = context; } public boolean isTrue(Type o, Type p) { TypeSystem ts = context.typeSystem(); return ts.typeEquals(o, p, context); } } public static class ImplicitCastValid implements Predicate2<Type> { Context context; public ImplicitCastValid(Context context) { this.context = context; } public boolean isTrue(Type o, Type p) { TypeSystem ts = context.typeSystem(); return ts.isImplicitCastValid(o, p, context); } } public static class Subtype implements Predicate2<Type> { Context context; public Subtype(Context context) { this.context = context; } public boolean isTrue(Type o, Type p) { TypeSystem ts = context.typeSystem(); return ts.isSubtype(o, p, context); } } /** * Class to handle the comparisons; dispatches to moreSpecific method. */ public static class MostSpecificComparator<S extends ProcedureDef, T extends ProcedureInstance<S>> implements Comparator<T> { protected Context context; public MostSpecificComparator(Context context) { this.context = context; } public int compare(T p1, T p2) { if (p1.moreSpecific(null, p2, context)) return -1; if (p2.moreSpecific(null, p1, context)) return 1; return 0; } } protected <S extends ProcedureDef, T extends ProcedureInstance<S>> Comparator<T> mostSpecificComparator(Type ct, Matcher<T> matcher, Context context) { return new X10MostSpecificComparator<S,T>(ct, matcher, context); } protected static class X10MostSpecificComparator<S extends ProcedureDef, T extends ProcedureInstance<S>> extends MostSpecificComparator<S, T> { private Matcher<T> matcher; Type container; protected X10MostSpecificComparator(Type container, Matcher<T> matcher, Context context) { super(context); this.matcher = matcher; this.container=container; } public static int FIRST_MOST_SPECIFIC=-1; public static int SECOND_MOST_SPECIFIC=1; public static int NEITHER_MORE_SPECIFIC=0; public int compare(T p1, T p2) { if (p1.moreSpecific(container, p2, context)) return FIRST_MOST_SPECIFIC; if (p2.moreSpecific(container, p1, context)) return SECOND_MOST_SPECIFIC; return NEITHER_MORE_SPECIFIC; } public Type container() { return container; } } public List<MethodInstance> findAcceptableMethods(Type container, MethodMatcher matcher) throws SemanticException { List<MethodInstance> candidates = new ArrayList<MethodInstance>(); List<Type> types = env(matcher.context()).upperBounds(container, true); SemanticException err = null; for (Type t : types) { try { List<MethodInstance> ms = superFindAcceptableMethods(t, matcher); candidates.addAll(ms); } catch (SemanticException e) { err = e; } } if (candidates.size()==0 && err!=null) throw err; return candidates; } /** * Populates the list acceptable with those MethodInstances which are * Applicable and Accessible as defined by JLS 15.11.2.1 */ private List<MethodInstance> superFindAcceptableMethods(Type container, MethodMatcher matcher) throws SemanticException { if (container==null) return Collections.EMPTY_LIST; assert_(container); // Collect allMethods with the relevant name Name name = matcher.name(); Context context = matcher.context(); List<MethodInstance> allMethods = new ArrayList<MethodInstance>(); Set<Type> visitedTypes = CollectionFactory.newHashSet(); LinkedList<Type> typeQueue = new LinkedList<Type>(); typeQueue.addLast(container); typeQueue.addLast(container.typeSystem().Any()); Q: while (! typeQueue.isEmpty()) { Type t = typeQueue.removeFirst(); if (t instanceof ContainerType) { ContainerType type = (ContainerType) t; for (Type s : visitedTypes) { if (typeEquals(type, s, context)) continue Q; } if (visitedTypes.contains(type)) { continue; } visitedTypes.add(type); if (reporter.should_report(Reporter.types, 2)) reporter.report(2, "Searching type " + type + " for method " + matcher.signature()); allMethods.addAll(type.methodsNamed(name)); } if (t instanceof ObjectType) { ObjectType ot = (ObjectType) t; if (ot.superClass() != null) { typeQueue.addLast(ot.superClass()); } typeQueue.addAll(ot.interfaces()); } } // Collected all methods, now let's filter them List<Type> typeParams = matcher.typeArgs; List<Type> argTypes = matcher.argTypes; boolean isDumbMatcher = matcher.isDumbMatcher; SemanticException error = null; List<MethodInstance> resolved = resolveProcedure(container, context, allMethods, typeParams, argTypes, isDumbMatcher); List<MethodInstance> acceptable = new ArrayList<MethodInstance>(); for (MethodInstance mi : resolved) { MethodInstance oldmi = mi; mi = matcher.instantiate(mi); if (mi == null) { continue; } mi.setOrigMI(oldmi); if (isAccessible(mi, context)) { acceptable.add(mi); } else { // method call is valid, but the method is // unacceptable. if (error == null) { error = new NoMemberException(NoMemberException.METHOD, "Method " + mi.signature() + " in " + container + " is inaccessible."); } } } if (acceptable.size() == 0) { if (error == null) { throw new NoMemberException(NoMemberException.METHOD, "No valid method call found for call in given type." + "\n\t Call: " + matcher.stripConstraints() + "\n\t Type: " + Types.stripConstraintsIfDynamicCalls(container)); } throw error; } return acceptable; } public static <D extends ProcedureDef, T extends X10ProcedureInstance<D> & MemberInstance<D>> List<T> resolveProcedure(Type container, Context context, List<T> allMethods, List<Type> typeParams, List<Type> argTypes, boolean dumbMatcher) { int typeParamNum = typeParams.size(); int argNum = argTypes.size(); List<T> resolved = new ArrayList<T>(); TypeSystem ts = context.typeSystem(); for (T mi : allMethods) { List<Type> formals = mi.formalTypes(); if (argNum !=formals.size()) continue; List<ParameterType> miTypeParams = (List<ParameterType>)(List)mi.typeParameters(); int miTypeParamNum = miTypeParams.size(); if (typeParamNum!=0 && typeParamNum!=miTypeParamNum) continue; boolean isOk = true; if (!dumbMatcher) { // handle type param // def m[H](H) TypeParamSubst subst = null; List<Type> tmp_typeParams = typeParams; if (miTypeParamNum!=0 && typeParamNum==0) { // infer typeParams Type c = container != null ? container : mi.container(); try { Type[] Y = TypeConstraint.inferTypeArguments(mi, c, argTypes, formals, (List<Type>)(List)miTypeParams, context); assert Y.length==miTypeParamNum; for (int k=0; k<miTypeParamNum; k++) Y[k] = Types.stripConstraints(Y[k]); tmp_typeParams = Arrays.asList(Y); } catch (SemanticException e) { continue; } } if (tmp_typeParams.size()!=0) { subst = new TypeParamSubst(ts, tmp_typeParams, miTypeParams); } for (int p=0; p<argNum;p++) { Type arg = argTypes.get(p); Type formal = formals.get(p); if (subst!=null) formal = subst.reinstantiate(formal); if (!isSubtypeIgnoringConstraints(arg, formal, context)) { isOk = false; break; } } } if (isOk) resolved.add(mi); } return resolved; } private static boolean isSubtypeIgnoringConstraints(Type arg, Type formal, Context context) { arg = Types.stripConstraints(arg); formal = Types.stripConstraints(formal); TypeSystem ts = context.typeSystem(); // stripConstraints doesn't work for closure types // to get a more precise error message because I cannot strip constraints from closures if (arg instanceof FunctionType && formal instanceof FunctionType) { FunctionType argF = (FunctionType) arg; FunctionType formalF = (FunctionType) formal; List<Type> argA = argF.argumentTypes(); List<Type> formalA = formalF.argumentTypes(); if (formalA.size()!=argA.size()) return false; if (!isSubtypeIgnoringConstraints(argF.returnType(), formalF.returnType(), context)) return false; for (int i=0; i<formalA.size(); i++) if (!isSubtypeIgnoringConstraints(formalA.get(i), argA.get(i), context)) return false; return true; } else return ts.isSubtype(arg, formal, context); } /** * Populates the list acceptable with those MethodInstances which are * Applicable and Accessible as defined by JLS 15.11.2.1 */ public List<ConstructorInstance> findAcceptableConstructors(Type container, ConstructorMatcher matcher) throws SemanticException { return env(matcher.context()).findAcceptableConstructors(container, matcher); } /** * Returns whether method 1 is <i>more specific</i> than method 2, * where <i>more specific</i> is defined as JLS 15.11.2.2 */ public <T extends ProcedureDef> boolean moreSpecific(ProcedureInstance<T> p1, ProcedureInstance<T> p2, Context context) { return env(context).moreSpecific(p1, p2); } /** * Returns the supertype of type, or null if type has no supertype. **/ public Type superClass(Type type) { assert_(type); if (type instanceof ObjectType) return ((ObjectType) type).superClass(); return null; } /** * Returns an immutable list of all the interface types which type * implements. **/ public List<Type> interfaces(Type type) { assert_(type); if (type instanceof ObjectType) return ((ObjectType) type).interfaces(); return Collections.<Type>emptyList(); } /** * Requires: all type arguments are canonical. * Returns the least common ancestor of Type1 and Type2 **/ public Type leastCommonAncestor(Type type1, Type type2, Context context) { assert_(type1); assert_(type2); return env(context).leastCommonAncestor(type1, type2); } //// // Functions for method testing. //// /** Return true if t overrides mi */ public boolean hasMethod(Type t, MethodInstance mi, Context context) { assert_(t); assert_(mi); return env(context).hasMethod(t, mi); } public X10ConstructorInstance findConstructor(Type container, polyglot.types.TypeSystem_c.ConstructorMatcher matcher) throws SemanticException { return (X10ConstructorInstance) SUPER_findConstructor(container, matcher); } public Collection<X10ConstructorInstance> findConstructors(Type container, polyglot.types.TypeSystem_c.ConstructorMatcher matcher) throws SemanticException { assert_(container); Context context = matcher.context(); List<ConstructorInstance> acceptable = findAcceptableConstructors(container, matcher); if (acceptable.size() == 0) { throw new NoMemberException(NoMemberException.CONSTRUCTOR, "No valid constructor found for " + matcher.signature() + ")."); } Collection<ConstructorInstance> maximal = findMostSpecificProcedures(acceptable, matcher, context); Collection<X10ConstructorInstance> result = new ArrayList<X10ConstructorInstance>(); for (ConstructorInstance mi : maximal) { result.add((X10ConstructorInstance) mi); } return result; } public MethodInstance findMethod(Type container, MethodMatcher matcher) throws SemanticException { return (MethodInstance) SUPER_findMethod(container, matcher); } public Collection<MethodInstance> findMethods(Type container, MethodMatcher matcher) throws SemanticException { assert_(container); Context context = matcher.context(); List<MethodInstance> acceptable = findAcceptableMethods(container, matcher); if (acceptable.size() == 0) { throw new NoMemberException(NoMemberException.METHOD, "No valid method call found for call in given type." + "\n\t Call: " + matcher.stripConstraints() + "\n\t Type: " + Types.stripConstraintsIfDynamicCalls(container)); } Collection<MethodInstance> maximal = findMostSpecificProcedures(acceptable, (Matcher<MethodInstance>) matcher, context); Collection<MethodInstance> result = new ArrayList<MethodInstance>(); for (MethodInstance mi : maximal) { result.add(mi); } return result; } public MethodMatcher MethodMatcher(Type container, Name name, List<Type> argTypes, Context context) { return new MethodMatcher(container, name, Collections.EMPTY_LIST, argTypes, context, false); } public MethodMatcher MethodMatcher(Type container, Name name, List<Type> typeArgs, List<Type> argTypes, Context context) { return new MethodMatcher(container, name, typeArgs, argTypes, context, false); } public MethodMatcher MethodMatcher(Type container, Name name, List<Type> typeArgs, List<Type> argTypes, Context context, boolean isDumbMatcher) { return new MethodMatcher(container, name, typeArgs, argTypes, context, isDumbMatcher); } public ConstructorMatcher ConstructorMatcher(Type container, List<Type> argTypes, Context context) { return new ConstructorMatcher(container, Collections.EMPTY_LIST, argTypes, context, false); } public ConstructorMatcher ConstructorMatcher(Type container, List<Type> typeArgs, List<Type> argTypes, Context context) { return new ConstructorMatcher(container, typeArgs, argTypes, context, false); } public ConstructorMatcher ConstructorMatcher(Type container, List<Type> typeArgs, List<Type> argTypes, Context context, boolean isDumbMatcher) { return new ConstructorMatcher(container, typeArgs, argTypes, context, isDumbMatcher); } /** Return true if t overrides mi */ public boolean hasFormals(ProcedureInstance<? extends ProcedureDef> pi, List<Type> formalTypes, Context context) { assert_(pi); assert_(formalTypes); return env(context).hasFormals(pi, formalTypes); } public List<MethodInstance> overrides(MethodInstance mi, Context context) { return env(context).overrides(mi); } public List<MethodInstance> implemented(MethodInstance mi, Context context) { return env(context).implemented(mi); } public List<MethodInstance> implemented(MethodInstance mi, ContainerType st, Context context) { return env(context).implemented(mi, st); } public boolean canOverride(MethodInstance mi, MethodInstance mj, Context context) { return env(context).canOverride(mi, mj); } public void checkOverride(MethodInstance mi, MethodInstance mj, Context context) throws SemanticException { env(context).checkOverride(mi, mj); } // public void checkOverride(MethodInstance mi, MethodInstance mj, boolean allowCovariantReturn, Context context) throws SemanticException { //env(context).checkOverride(mi, mj, allowCovariantReturn); //} /** * Returns true iff <m1> is the same method as <m2> */ public boolean isSameMethod(MethodInstance m1, MethodInstance m2, Context context) { assert_(m1); assert_(m2); return env(context).isSameMethod(m1, m2); } public boolean callValid(ProcedureInstance<? extends ProcedureDef> prototype, Type thisType, List<Type> argTypes, Context context) { assert_(prototype); assert_(argTypes); return env(context).callValid(prototype, thisType, argTypes); } //// // Functions which yield particular types. //// public NullType JavaNull(){ return JAVA_NULL_; } public Type JavaVoid() { return JAVA_VOID_; } public Type JavaBoolean() { return JAVA_BOOLEAN_; } public Type JavaChar() { return JAVA_CHAR_; } public Type JavaByte() { return JAVA_BYTE_; } public Type JavaShort() { return JAVA_SHORT_; } public Type JavaInt() { return JAVA_INT_; } public Type JavaLong() { return JAVA_LONG_; } public Type JavaFloat() { return JAVA_FLOAT_; } public Type JavaDouble() { return JAVA_DOUBLE_; } public X10ClassType load(String name) { QName qualName = QName.make(name); try { return (X10ClassType) forName(qualName); } catch (SemanticException e) { extensionInfo().compiler().errorQueue().enqueue( ErrorInfo.INTERNAL_ERROR, "Cannot load X10 runtime class \"" + name + "\". Is the X10 runtime library in your classpath or sourcepath?"); Goal goal = extensionInfo().scheduler().currentGoal(); if (goal != null) goal.fail(); return createFakeClass(qualName, e); } } public X10ClassType createFakeClass(QName fullName, SemanticException error) { X10ClassDef cd = (X10ClassDef) createClassDef(); cd.name(fullName.name()); cd.position(Position.COMPILER_GENERATED); cd.kind(ClassDef.TOP_LEVEL); cd.flags(Flags.PUBLIC); cd.superType(null); try { cd.setPackage(Types.ref(packageForName(fullName.qualifier()))); } catch (SemanticException e) { } return ((X10ParsedClassType) cd.asType()).error(error); } public X10FieldInstance createFakeField(QName containerName, Flags flags, Name name, SemanticException error) { return createFakeField(typeForNameSilent(containerName), flags, name, error); } public X10FieldInstance createFakeField(Name name, SemanticException error) { return createFakeField(unknownClassDef().asType(), Flags.PUBLIC.Static(), name, error); } public X10FieldInstance createFakeField(ClassType container, Flags flags, Name name, SemanticException error) { Position pos = Position.compilerGenerated(container == null ? null : container.position()); Type type = unknownType(pos); ThisDef thisDef = thisDef(pos, Types.ref(container)); List<Ref<? extends Type>> excTypes = Collections.emptyList(); X10FieldDef fd = (X10FieldDef) fieldDef(pos, Types.ref(container), flags, Types.ref(type), name, thisDef); return ((X10FieldInstance) fd.asInstance()).error(error); } public MethodInstance createFakeMethod(QName containerName, Flags flags, Name name, List<Type> typeArgs, List<Type> argTypes, SemanticException error) { return createFakeMethod(typeForNameSilent(containerName), flags, name, typeArgs, argTypes, error); } public MethodInstance createFakeMethod(Name name, List<Type> typeArgs, List<Type> argTypes, SemanticException error) { return createFakeMethod(unknownClassDef().asType(), Flags.PUBLIC.Static(), name, typeArgs, argTypes, error); } public MethodInstance createFakeMethod(ClassType container, Flags flags, Name name, List<Type> typeArgs, List<Type> argTypes, SemanticException error) { Position pos = Position.compilerGenerated(container == null ? null : container.position()); Type returnType = unknownType(pos); List<Ref<? extends Type>> args = new ArrayList<Ref<? extends Type>>(); List<LocalDef> formalNames = new ArrayList<LocalDef>(); int i = 0; for (Type t : argTypes) { args.add(Types.ref(t)); formalNames.add(localDef(pos, Flags.FINAL, Types.ref(t), Name.make("p"+(++i)))); } ThisDef thisDef = thisDef(pos, Types.ref(container)); X10MethodDef md = (X10MethodDef) methodDef(pos, pos, Types.ref(container), flags, Types.ref(returnType), name, Collections.<ParameterType>emptyList(), args, Collections.<Ref<? extends Type>>emptyList(), thisDef, formalNames, null, null, null, null); List<ParameterType> typeParams = new ArrayList<ParameterType>(); i = 0; for (Type r : typeArgs) { typeParams.add(new ParameterType(this, pos, pos, Name.make("T"+(++i)), Types.ref(md))); } md.setTypeParameters(typeParams); return md.asInstance().error(error); } public X10ConstructorInstance createFakeConstructor(QName containerName, Flags flags, List<Type> typeArgs, List<Type> argTypes, SemanticException error) { return createFakeConstructor(typeForNameSilent(containerName).typeArguments(typeArgs), flags, argTypes, error); } public X10ConstructorInstance createFakeConstructor(ClassType container, Flags flags, List<Type> argTypes, SemanticException error) { Position pos = Position.compilerGenerated(container == null ? null : container.position()); List<Ref<? extends Type>> args = new ArrayList<Ref<? extends Type>>(); List<LocalDef> formalNames = new ArrayList<LocalDef>(); int i = 0; for (Type t : argTypes) { args.add(Types.ref(t)); formalNames.add(localDef(pos, Flags.FINAL, Types.ref(t), Name.make("p"+(++i)))); } ThisDef thisDef = thisDef(pos, Types.ref(container)); X10ConstructorDef cd = (X10ConstructorDef) constructorDef(pos, pos, Types.ref(container), flags, Types.ref(container), args, Collections.<Ref<? extends Type>>emptyList(), thisDef, formalNames, null, null, null); // List<Ref<? extends Type>> typeParams = new ArrayList<Ref<? extends Type>>(); // i = 0; // for (Type r : typeArgs) { // typeParams.add(Types.ref(new ParameterType_c(this, pos, Name.make("T"+(++i)), Types.ref(cd)))); // } // cd.setTypeParameters(typeParams); return ((X10ConstructorInstance) cd.asInstance()).error(error); } public X10LocalInstance createFakeLocal(Name name, SemanticException error) { Position pos = Position.COMPILER_GENERATED; Type type = unknownType(pos); List<Ref<? extends Type>> excTypes = Collections.emptyList(); X10LocalDef ld = (X10LocalDef) localDef(pos, Flags.FINAL, Types.ref(type), name); return ((X10LocalInstance) ld.asInstance()).error(error); } protected X10ClassType typeForNameSilent(QName fullName) { try { if (fullName == null) { return (X10ClassType) unknownClassDef().asType(); } return (X10ClassType) forName(fullName); } catch (SemanticException e) { return createFakeClass(fullName, e); } } public Type forName(QName name) throws SemanticException { List<Type> res; try { res = systemResolver.find(name); } catch (SemanticException e) { if (name.qualifier() != null) { try { Type container = forName(name.qualifier()); if (container instanceof ClassType) { res = classContextResolver(container).find(MemberTypeMatcher(container, name.name(), emptyContext())); } } catch (SemanticException e2) { } } // throw the original exception throw e; } return res.get(0); // FIXME } /** * {@inheritDoc} * @deprecated */ public final Type typeForName(QName name) throws SemanticException { return forName(name); } protected Type CLASS_; protected X10ClassType STRING_; protected X10ClassType EXCEPTION_; public Type JavaClass() { if (CLASS_ != null) return CLASS_; return CLASS_ = load("java.lang.Class"); } public Type Cloneable() { return load("java.lang.Cloneable"); } public Type JLIterable() { return load("java.lang.Iterable"); } public Type Serializable() { return load("java.io.Serializable"); } protected NullType createJavaNull() { return new NullType(this); } protected JavaPrimitiveType createPrimitive(Name name) { return new JavaPrimitiveType(this, name); } public static final Name voidName = Name.make("void"); protected final NullType JAVA_NULL_ = createJavaNull(); protected final JavaPrimitiveType JAVA_VOID_ = createPrimitive(voidName); protected final JavaPrimitiveType JAVA_BOOLEAN_ = createPrimitive(Name.make("boolean")); protected final JavaPrimitiveType JAVA_CHAR_ = createPrimitive(Name.make("char")); protected final JavaPrimitiveType JAVA_BYTE_ = createPrimitive(Name.make("byte")); protected final JavaPrimitiveType JAVA_SHORT_ = createPrimitive(Name.make("short")); protected final JavaPrimitiveType JAVA_INT_ = createPrimitive(Name.make("int")); protected final JavaPrimitiveType JAVA_LONG_ = createPrimitive(Name.make("long")); protected final JavaPrimitiveType JAVA_FLOAT_ = createPrimitive(Name.make("float")); protected final JavaPrimitiveType JAVA_DOUBLE_ = createPrimitive(Name.make("double")); Type VOID_ = new VoidType(this); public Type Void() { return VOID_; } public boolean isVoid(Type t) { return t != null && Types.baseType( // in case someone writes: void{i==1} expandMacros(t)).equals((Object) Void()); } // do not use typeEquals NullType Null_ = createNull(); public NullType Null() { return Null_; } protected NullType createNull() { return new NullType(this); } protected X10ClassType Boolean_; public X10ClassType Boolean() { if (Boolean_ == null) Boolean_ = load("x10.lang.Boolean"); return Boolean_; } protected X10ClassType Byte_; public X10ClassType Byte() { if (Byte_ == null) Byte_ = load("x10.lang.Byte"); return Byte_; } protected X10ClassType Short_; public X10ClassType Short() { if (Short_ == null) Short_ = load("x10.lang.Short"); return Short_; } protected X10ClassType Char_; public X10ClassType Char() { if (Char_ == null) Char_ = load("x10.lang.Char"); return Char_; } protected X10ClassType Int_; public X10ClassType Int() { if (Int_ == null) Int_ = load("x10.lang.Int"); return Int_; } protected X10ClassType Long_; public X10ClassType Long() { if (Long_ == null) Long_ = load("x10.lang.Long"); return Long_; } protected X10ClassType Float_; public X10ClassType Float() { if (Float_ == null) Float_ = load("x10.lang.Float"); return Float_; } protected X10ClassType Double_; public X10ClassType Double() { if (Double_ == null) Double_ = load("x10.lang.Double"); return Double_; } // Unsigned integers protected X10ClassType UByte_; public X10ClassType UByte() { if (UByte_ == null) UByte_ = load("x10.lang.UByte"); return UByte_; } protected X10ClassType UShort_; public X10ClassType UShort() { if (UShort_ == null) UShort_ = load("x10.lang.UShort"); return UShort_; } protected X10ClassType UInt_; public X10ClassType UInt() { if (UInt_ == null) UInt_ = load("x10.lang.UInt"); return UInt_; } protected X10ClassType ULong_; public X10ClassType ULong() { if (ULong_ == null) ULong_ = load("x10.lang.ULong"); return ULong_; } // Atomic protected X10ClassType AtomicBoolean_; public X10ClassType AtomicBoolean() { if (AtomicBoolean_ == null) AtomicBoolean_ = load("x10.util.concurrent.AtomicBoolean"); return AtomicBoolean_; } protected X10ClassType AtomicInteger_; public X10ClassType AtomicInteger() { if (AtomicInteger_ == null) AtomicInteger_ = load("x10.util.concurrent.AtomicInteger"); return AtomicInteger_; } protected X10ClassType IndexedMemoryChunk_; public X10ClassType IndexedMemoryChunk() { if (IndexedMemoryChunk_ == null) IndexedMemoryChunk_ = load("x10.util.IndexedMemoryChunk"); return IndexedMemoryChunk_; } protected X10ClassType GLOBAL_REF_; public X10ClassType GlobalRef() { if (GLOBAL_REF_ == null) GLOBAL_REF_ = load("x10.lang.GlobalRef"); return GLOBAL_REF_; } public Type Class() { if (CLASS_ != null) return CLASS_; return CLASS_ = load("x10.lang.Class"); } X10ClassType ANY_ = null; public X10ClassType Any() { if (ANY_ != null) return ANY_; return ANY_ = load("x10.lang.Any"); // x10.util.Any.makeDef(this).asType(); } public LazyRef<Type> lazyAny() { final LazyRef<Type> ANY = Types.lazyRef(null); ANY.setResolver(new Runnable() { public void run() { ANY.update(Any()); } }); return ANY; } public X10ClassType String() { if (STRING_ != null) return (X10ClassType) STRING_; X10ClassType t = load("x10.lang.String"); STRING_ = t; return t; } public X10ClassType Exception() { if (EXCEPTION_ != null) return (X10ClassType) EXCEPTION_; X10ClassType t = load("x10.lang.Exception"); EXCEPTION_ = t; return t; } public X10ClassType Error() { return load("x10.lang.Error"); } public X10ClassType CheckedThrowable() { return load("x10.lang.CheckedThrowable"); } public X10ClassType CheckedException() { return load("x10.lang.CheckedException"); } public X10ClassType NullPointerException() { return load("x10.lang.NullPointerException"); } public X10ClassType ClassCastException() { return FailedDynamicCheckException(); } public X10ClassType FailedDynamicCheckException() { return load("x10.lang.FailedDynamicCheckException"); } public X10ClassType OutOfBoundsException() { return load("x10.lang.ArrayIndexOutOfBoundsException"); } public X10ClassType ArrayStoreException() { return load("x10.lang.ArrayStoreException"); } public X10ClassType ArithmeticException() { return load("x10.lang.ArithmeticException"); } protected X10ClassType comparableType_; public X10ClassType Comparable() { if (comparableType_ == null) comparableType_ = load("x10.lang.Comparable"); // java file return comparableType_; } protected X10ClassType iterableType_; public X10ClassType Iterable() { if (iterableType_ == null) iterableType_ = load("x10.lang.Iterable"); // java file return iterableType_; } protected X10ClassType customSerializationType_; public X10ClassType CustomSerialization() { if (customSerializationType_ == null) customSerializationType_ = load("x10.io.CustomSerialization"); // java file return customSerializationType_; } protected X10ClassType serialDataType_; public X10ClassType SerialData() { if (serialDataType_ == null) serialDataType_ = load("x10.io.SerialData"); // java file return serialDataType_; } protected X10ClassType reducibleType_; public X10ClassType Reducible() { if (reducibleType_ == null) reducibleType_ = load("x10.lang.Reducible"); // java file return reducibleType_; } protected X10ClassType arithmeticType_; public X10ClassType Arithmetic() { if (arithmeticType_ == null) arithmeticType_ = load("x10.lang.Arithmetic"); return arithmeticType_; } protected X10ClassType bitwiseType_; public X10ClassType Bitwise() { if (bitwiseType_ == null) bitwiseType_ = load("x10.lang.Bitwise"); return bitwiseType_; } protected X10ClassType orderedType_; public X10ClassType Ordered() { if (orderedType_ == null) orderedType_ = load("x10.util.Ordered"); return orderedType_; } protected X10ClassType nativeRepType_; public X10ClassType NativeRep() { if (nativeRepType_ == null) nativeRepType_ = load("x10.compiler.NativeRep"); return nativeRepType_; } protected X10ClassType nativeType_; public X10ClassType NativeType() { if (nativeType_ == null) nativeType_ = load("x10.compiler.Native"); return nativeType_; } protected X10ClassType nativeClassType_; public X10ClassType NativeClass() { if (nativeClassType_ == null) nativeClassType_ = load("x10.compiler.NativeClass"); return nativeClassType_; } protected X10ClassType EndpointType_; public X10ClassType Endpoint() { if (EndpointType_ == null) EndpointType_ = load("x10.compiler.Endpoint"); return EndpointType_; } protected X10ClassType RuntimeProfileType_; public X10ClassType RuntimeProfile() { if (RuntimeProfileType_ == null) RuntimeProfileType_ = load("x10.lang.Runtime.Profile"); return RuntimeProfileType_; } protected X10ClassType ProfileType_; public X10ClassType Profile() { if (ProfileType_ == null) ProfileType_ = load("x10.compiler.Profile"); return ProfileType_; } protected X10ClassType compileTimeConstantType_; public X10ClassType CompileTimeConstant() { if (compileTimeConstantType_ == null) compileTimeConstantType_ = load("x10.compiler.CompileTimeConstant"); return compileTimeConstantType_; } public X10ClassType Iterable(Type index) { return Types.instantiate(Iterable(), index); } public X10ClassType Iterator(Type index) { return Types.instantiate(Iterator(), index); } protected X10ClassType iteratorType_; public X10ClassType Iterator() { if (iteratorType_ == null) iteratorType_ = load("x10.lang.Iterator"); // java file return iteratorType_; } protected X10ClassType containsType_; public X10ClassType Contains() { if (containsType_ == null) containsType_ = load("x10.lang.Contains"); // java file return containsType_; } protected X10ClassType settableType_; public X10ClassType Settable() { if (settableType_ == null) settableType_ = load("x10.lang.Settable"); // java file return settableType_; } protected X10ClassType containsAllType_; public X10ClassType ContainsAll() { if (containsAllType_ == null) containsAllType_ = load("x10.lang.ContainsAll"); // java file return containsAllType_; } protected X10ClassType placeType_; public X10ClassType Place() { if (placeType_ == null) placeType_ = load("x10.lang.Place"); // java file return placeType_; } protected X10ClassType regionType_; public X10ClassType Region() { if (regionType_ == null) regionType_ = load("x10.array.Region"); // java file return regionType_; } protected X10ClassType pointType_; public X10ClassType Point() { if (pointType_ == null) pointType_ = load("x10.array.Point"); return pointType_; } protected X10ClassType distributionType_; public X10ClassType Dist() { if (distributionType_ == null) distributionType_ = load("x10.array.Dist"); // java file return distributionType_; } protected X10ClassType clockType_; public X10ClassType Clock() { if (clockType_ == null) clockType_ = load("x10.lang.Clock"); // java file return clockType_; } protected X10ClassType finishStateType_; public X10ClassType FinishState() { if (finishStateType_ == null) finishStateType_ = load("x10.lang.FinishState"); // java file return finishStateType_; } protected X10ClassType runtimeType_; public X10ClassType Runtime() { if (runtimeType_ == null) runtimeType_ = load("x10.lang.Runtime"); // java file return runtimeType_; } protected X10ClassType systemType_; public X10ClassType System() { if (systemType_ == null) systemType_ = load("x10.lang.System"); return systemType_; } protected X10ClassType embedType_; public X10ClassType Embed() { if (embedType_ == null) embedType_ = load("x10.compiler.Embed"); return embedType_; } protected X10ClassType perProcessType_; public X10ClassType PerProcess() { if (perProcessType_ == null) perProcessType_ = load("x10.compiler.PerProcess"); return perProcessType_; } protected X10ClassType remoteInvocationType_; public X10ClassType RemoteInvocation() { if (remoteInvocationType_ == null) remoteInvocationType_ = load("x10.compiler.RemoteInvocation"); return remoteInvocationType_; } protected X10ClassType arrayType_ = null; public X10ClassType Array() { if (arrayType_ == null) arrayType_ = load("x10.array.Array"); return arrayType_; } protected X10ClassType remoteArrayType_ = null; public X10ClassType RemoteArray() { if (remoteArrayType_ == null) remoteArrayType_ = load("x10.array.RemoteArray"); return remoteArrayType_; } protected X10ClassType distArrayType_ = null; public X10ClassType DistArray() { if (distArrayType_ == null) distArrayType_ = load("x10.array.DistArray"); return distArrayType_; } protected X10ClassType intRangeType_ = null; public X10ClassType IntRange() { if (intRangeType_ == null) { intRangeType_ = load("x10.lang.IntRange"); } return intRangeType_; } protected X10ClassType longRangeType_ = null; public X10ClassType LongRange() { if (longRangeType_ == null) { longRangeType_ = load("x10.lang.LongRange"); } return longRangeType_; } protected X10ClassType mortalType_ = null; public X10ClassType Mortal() { if (mortalType_ == null) mortalType_ = load("x10.lang.Runtime.Mortal"); return mortalType_; } protected X10ClassType frameType_; public X10ClassType Frame() { if (frameType_ == null) frameType_ = load("x10.compiler.ws.Frame"); return frameType_; } protected X10ClassType finishFrameType_; public X10ClassType FinishFrame() { if (finishFrameType_ == null) finishFrameType_ = load("x10.compiler.ws.FinishFrame"); return finishFrameType_; } protected X10ClassType asyncFrameType_; public X10ClassType AsyncFrame() { if (asyncFrameType_ == null) asyncFrameType_ = load("x10.compiler.ws.AsyncFrame"); return asyncFrameType_; } protected X10ClassType collectingFinishType_; public X10ClassType CollectingFinish() { if (collectingFinishType_ == null) collectingFinishType_ = load("x10.compiler.ws.CollectingFinish"); return collectingFinishType_; } protected X10ClassType throwFrameType_; public X10ClassType ThrowFrame() { if (throwFrameType_ == null) throwFrameType_ = load("x10.compiler.ws.ThrowFrame"); return throwFrameType_; } protected X10ClassType tryFrameType_; public X10ClassType TryFrame() { if (tryFrameType_ == null) tryFrameType_ = load("x10.compiler.ws.TryFrame"); return tryFrameType_; } protected X10ClassType atFrameType_; public X10ClassType AtFrame() { if (atFrameType_ == null) atFrameType_ = load("x10.compiler.ws.AtFrame"); return atFrameType_; } protected X10ClassType regularFrameType_; public X10ClassType RegularFrame() { if (regularFrameType_ == null) regularFrameType_ = load("x10.compiler.ws.RegularFrame"); return regularFrameType_; } protected X10ClassType mainFrameType_; public X10ClassType MainFrame() { if (mainFrameType_ == null) mainFrameType_ = load("x10.compiler.ws.MainFrame"); return mainFrameType_; } protected X10ClassType workerType_; public X10ClassType Worker() { if (workerType_ == null) workerType_ = load("x10.compiler.ws.Worker"); return workerType_; } protected X10ClassType remoteFinishType_; public X10ClassType RemoteFinish() { if (remoteFinishType_ == null) remoteFinishType_ = load("x10.compiler.ws.RemoteFinish"); return remoteFinishType_; } protected X10ClassType rootFinishType_; public X10ClassType RootFinish() { if (rootFinishType_ == null) rootFinishType_ = load("x10.compiler.ws.RootFinish"); return rootFinishType_; } protected X10ClassType abortType_; public X10ClassType Abort() { if (abortType_ == null) abortType_ = load("x10.compiler.Abort"); return abortType_; } protected X10ClassType stackAllocateType_; public X10ClassType StackAllocate() { if (stackAllocateType_ == null) stackAllocateType_ = load("x10.compiler.StackAllocate"); return stackAllocateType_; } protected X10ClassType inlineOnlyType_; public X10ClassType InlineOnly() { if (inlineOnlyType_ == null) inlineOnlyType_ = load("x10.compiler.InlineOnly"); return inlineOnlyType_; } protected X10ClassType inlineType_; public X10ClassType Inline() { if (inlineType_ == null) inlineType_ = load("x10.compiler.Inline"); return inlineType_; } protected X10ClassType noInlineType_; public X10ClassType NoInline() { if (noInlineType_ == null) noInlineType_ = load("x10.compiler.NoInline"); return noInlineType_; } protected X10ClassType headerType_; public X10ClassType Header() { if (headerType_ == null) headerType_ = load("x10.compiler.Header"); return headerType_; } protected X10ClassType ephemeralType_; public X10ClassType Ephemeral() { if (ephemeralType_ == null) ephemeralType_ = load("x10.compiler.Ephemeral"); return ephemeralType_; } protected X10ClassType uninitializedType_; public X10ClassType Uninitialized() { if (uninitializedType_ == null) uninitializedType_ = load("x10.compiler.Uninitialized"); return uninitializedType_; } protected X10ClassType suppressTransientErrorType_; public X10ClassType SuppressTransientError() { if (suppressTransientErrorType_ == null) suppressTransientErrorType_ = load("x10.compiler.SuppressTransientError"); return suppressTransientErrorType_; } public Object placeHolder(TypeObject o) { return placeHolder(o, Collections.<TypeObject>emptySet()); } public Object placeHolder(TypeObject o, Set<TypeObject> roots) { assert_(o); if (o instanceof Ref_c<?>) { Ref_c<?> ref = (Ref_c<?>) o; if (ref.get() instanceof ClassDef) { ClassDef ct = (ClassDef) ref.get(); // This should never happen: anonymous and local types cannot // appear in signatures. if (ct.isLocal() || ct.isAnonymous()) { throw new InternalCompilerError("Cannot serialize " + o + "."); } // Use the transformed name so that member classes will // be sought in the correct class file. QName name = getTransformedClassName(ct); TypeSystem_c ts = this; LazyRef<X10ClassDef> sym = Types.lazyRef( unknownClassDef(), null); Goal resolver = extInfo.scheduler().LookupGlobalTypeDef(sym, name); resolver.update(Goal.Status.SUCCESS); sym.setResolver(resolver); return sym; } } return o; } protected X10ClassDef unknownClassDef = null; public X10ClassDef unknownClassDef() { if (unknownClassDef == null) { unknownClassDef = (X10ClassDef) createFakeClass(QName.make("<unknown class>"), new SemanticException("Unknown class")).def(); } return unknownClassDef; } protected UnknownType unknownType = new UnknownType(this); protected UnknownPackage unknownPackage = new UnknownPackage_c(this); protected UnknownQualifier unknownQualifier = new UnknownQualifier_c(this); public UnknownType unknownType(Position pos) { return unknownType; } public UnknownPackage unknownPackage(Position pos) { return unknownPackage; } public UnknownQualifier unknownQualifier(Position pos) { return unknownQualifier; } public Package packageForName(Package prefix, Name name) throws SemanticException { return createPackage(prefix, name); } public Package packageForName(Ref<? extends Package> prefix, Name name) throws SemanticException { return createPackage(prefix, name); } public Package packageForName(QName name) throws SemanticException { if (name == null) { return null; } return packageForName(packageForName(name.qualifier()), name.name()); } /** @deprecated */ public Package createPackage(Package prefix, Name name) { return createPackage(prefix != null ? Types.ref(prefix) : null, name); } /** @deprecated */ public Package createPackage(Ref<? extends Package> prefix, Name name) { assert_(prefix); return new Package_c(this, prefix, name); } /** @deprecated */ public Package createPackage(QName name) { if (name == null) { return null; } return createPackage(createPackage(name.qualifier()), name.name()); } public Type arrayOf(Position pos, Ref<? extends Type> type) { // Should be called only by the Java class file loader. Type r = JavaArray(); return Types.instantiate(r, type); } /** * Returns a type identical to <type>, but with <dims> more array * dimensions. */ public Type arrayOf(Type type) { assert_(type); return arrayOf(type.position(), Types.ref(type)); } public Type arrayOf(Ref<? extends Type> type) { assert_(type); return arrayOf(null, type); } public Type arrayOf(Position pos, Type type) { assert_(type); return arrayOf(pos, Types.ref(type)); } public Type arrayOf(Type type, int dims) { return arrayOf(Types.ref(type), dims); } public Type arrayOf(Position pos, Type type, int dims) { return arrayOf(pos, Types.ref(type), dims); } Map<Ref<? extends Type>,Type> arrayTypeCache = CollectionFactory.newHashMap(); /** * Factory method for ArrayTypes. */ protected JavaArrayType arrayType(Position pos, Ref<? extends Type> type) { JavaArrayType t = (JavaArrayType) arrayTypeCache.get(type); if (t == null) { t = createArrayType(pos, type); arrayTypeCache.put(type, t); } return t; } protected JavaArrayType createArrayType(Position pos, Ref<? extends Type> type) { return new JavaArrayType_c(this, pos, type); } protected X10ClassType javaInteropType_ = null; public X10ClassType JavaInterop() { if (javaInteropType_ == null) javaInteropType_ = load("x10.interop.Java"); return javaInteropType_; } private static final class JavaArrayClassWrapper extends X10ParsedClassType_c { private static final long serialVersionUID = 815224489372855897L; private JavaArrayType arrType = null; private JavaArrayClassWrapper(TypeSystem ts, Position pos, Position errorPos, Ref<? extends X10ClassDef> def) { super(ts, pos, errorPos, def); ts.systemResolver().install(def.get().fullName(), this); } @Override public X10ParsedClassType typeArguments(List<Type> typeArgs) { JavaArrayClassWrapper n = (JavaArrayClassWrapper) super.typeArguments(typeArgs); if (n == this) return n; assert (typeArgs != null && typeArgs.size() == 1); n.arrType = ((TypeSystem_c) typeSystem()).arrayType(position(), Types.ref(typeArgs.get(0))); return n; } } protected X10ClassType javaArrayType_ = null; public X10ClassType JavaArray() { if (javaArrayType_ == null) { X10ClassDef cd = new X10ClassDef_c(this, null) { private static final long serialVersionUID = -1118624958040369022L; @Override public X10ClassType asType() { if (asType == null) { asType = new JavaArrayClassWrapper(ts, position(), errorPosition(), Types.ref(this)); } return (X10ClassType) asType; } }; cd.name(Name.make("array")); cd.position(Position.COMPILER_GENERATED); cd.flags(Flags.PUBLIC.Static()); cd.superType(null); javaArrayType_ = cd.asType(); // Careful here -- JavaInterop will refer back to array X10ClassDef xiJdef = JavaInterop().def(); cd.setPackage(xiJdef.package_()); cd.outer(Types.ref(xiJdef)); cd.kind(ClassDef.MEMBER); xiJdef.addMemberClass(Types.ref(javaArrayType_)); //cd.setFromJavaClassFile(); // pretend it's a Java class } return javaArrayType_; } public boolean isJavaArray(Type me) { return me.isClass() && me.toClass().def() == JavaArray().def(); } public boolean isPrimitiveJavaArray(Type me) { if (!isJavaArray(me)) { return false; } String arrayType = me.toClass().typeArguments().get(0).toString(); return "x10.lang.Boolean".equals(arrayType) || "x10.lang.String".equals(arrayType) || "x10.lang.Int".equals(arrayType) || "x10.lang.Byte".equals(arrayType) || "x10.lang.Char".equals(arrayType) || "x10.lang.Short".equals(arrayType) || "x10.lang.Double".equals(arrayType) || "x10.lang.Float".equals(arrayType) || "x10.lang.Long".equals(arrayType); } public Type arrayOf(Ref<? extends Type> type, int dims) { return arrayOf(null, type, dims); } public Type arrayOf(Position pos, Ref<? extends Type> type, int dims) { if (dims > 1) { return arrayOf(pos, arrayOf(pos, type, dims-1)); } else if (dims == 1) { return arrayOf(pos, type); } else { throw new InternalCompilerError( "Must call arrayOf(type, dims) with dims > 0"); } } /** * Returns a canonical type corresponding to the Java Class object * theClass. Does not require that <theClass> have a JavaClass * registered in this typeSystem. Does not register the type in * this TypeSystem. For use only by JavaClass implementations. **/ public Type typeForJavaClass(Class<?> clazz) throws SemanticException { if (clazz == Void.TYPE) return JAVA_VOID_; if (clazz == Boolean.TYPE) return JAVA_BOOLEAN_; if (clazz == Byte.TYPE) return JAVA_BYTE_; if (clazz == Character.TYPE) return JAVA_CHAR_; if (clazz == Short.TYPE) return JAVA_SHORT_; if (clazz == Integer.TYPE) return JAVA_INT_; if (clazz == Long.TYPE) return JAVA_LONG_; if (clazz == Float.TYPE) return JAVA_FLOAT_; if (clazz == Double.TYPE) return JAVA_DOUBLE_; if (clazz.isArray()) { return arrayOf(typeForJavaClass(clazz.getComponentType())); } return systemResolver.findOne(QName.make(clazz.getName())); } /** * Return the set of objects that should be serialized into the * type information for the given TypeObject. * Usually only the object itself should get encoded, and references * to other classes should just have their name written out. * If it makes sense for additional types to be fully encoded, * (i.e., they're necessary to correctly reconstruct the given clazz, * and the usual class resolvers can't otherwise find them) they * should be returned in the set in addition to clazz. */ public Set<TypeObject> getTypeEncoderRootSet(TypeObject t) { return Collections.singleton(t); } /** * Get the transformed class name of a class. * This utility method returns the "mangled" name of the given class, * whereby all periods ('.') following the toplevel class name * are replaced with dollar signs ('$'). If any of the containing * classes is not a member class or a top level class, then null is * returned. * * Return null if the class is not globally accessible. */ public QName getTransformedClassName(ClassDef ct) { assert ct != null; assert ct.fullName() != null; if (!ct.isMember() && !ct.isTopLevel()) { assert ! ct.asType().isGloballyAccessible(); return null; } StringBuilder sb = new StringBuilder(); while (ct.isMember()) { sb.insert(0, ct.name()); sb.insert(0, '$'); ct = ct.outer().get(); if (!ct.isMember() && !ct.isTopLevel()) { assert ! ct.asType().isGloballyAccessible(); return null; } } assert ct.asType().isGloballyAccessible(); if (sb.length() > 0) { QName fullName = ct.fullName(); sb.insert(0, fullName.name()); return QName.make(fullName.qualifier(), Name.make(sb.toString())); } else return QName.make(ct.fullName()); } public String translatePackage(Resolver c, Package p) { return p.translate(c); } public String translateArray(Resolver c, JavaArrayType t) { return t.translate(c); } public String translateClass(Resolver c, ClassType t) { return t.translate(c); } public String translatePrimitive(Resolver c, JavaPrimitiveType t) { return t.translate(c); } public Type primitiveForName(Name sname) throws SemanticException { String name = sname.toString(); if (name.equals("void")) return Void(); if (name.equals("boolean")) return Boolean(); if (name.equals("char")) return Char(); if (name.equals("byte")) return Byte(); if (name.equals("short")) return Short(); if (name.equals("int")) return Int(); if (name.equals("long")) return Long(); if (name.equals("float")) return Float(); if (name.equals("double")) return Double(); throw new SemanticException("Unrecognized primitive type \"" + name + "\"."); } public final X10ClassDef createClassDef() { return createClassDef((Source) null); } public X10ClassDef createClassDef(Source fromSource) { return new X10ClassDef_c(this, fromSource); } public X10ParsedClassType createClassType(Position pos, Position errorPosition, Ref<? extends X10ClassDef> def) { return new X10ParsedClassType_c(this, pos, errorPosition, def); } public X10ConstructorInstance createConstructorInstance(Position pos, Position errorPos, Ref<? extends ConstructorDef> def) { return new X10ConstructorInstance_c(this, pos, errorPos, (Ref<? extends X10ConstructorDef>) def); } public MethodInstance createMethodInstance(Position pos, Position errorPos, Ref<? extends MethodDef> def) { return new MethodInstance_c(this, pos, errorPos, (Ref<? extends X10MethodDef>) def); } public X10FieldInstance createFieldInstance(Position pos, Ref<? extends FieldDef> def) { return new X10FieldInstance_c(this, pos, (Ref<? extends X10FieldDef>) def); } public X10LocalInstance createLocalInstance(Position pos, Ref<? extends LocalDef> def) { return new X10LocalInstance_c(this, pos, (Ref<? extends X10LocalDef>) def); } public ClosureInstance createClosureInstance(Position pos, Position errorPos, Ref<? extends ClosureDef> def) { return new ClosureInstance_c(this, pos, errorPos, def); } public ThisInstance createThisInstance(Position pos, Ref<? extends ThisDef> def) { return new ThisInstance_c(this, pos, def); } public ThisDef thisDef(Position pos, Ref<? extends ClassType> baseType) { assert_(baseType); return new ThisDef_c(this, pos, null, baseType); } public ThisDef thisDef(Position pos, Ref<? extends ClassType> qType, Ref<? extends ClassType> baseType) { assert_(baseType); return new ThisDef_c(this, pos, qType, baseType); } public InitializerInstance createInitializerInstance(Position pos, Ref<? extends InitializerDef> def) { return new InitializerInstance_c(this, pos, def); } public List<QName> defaultOnDemandImports() { List<QName> l = new ArrayList<QName>(1); l.add(QName.make("x10.lang")); l.add(QName.make("x10.lang", TypeSystem.DUMMY_PACKAGE_CLASS_NAME.toString())); l.add(QName.make("x10.array")); return l; } public Type promote(Type t) throws SemanticException { Type pt = promote2(t); return Types.baseType(pt); } public Type promote(Type t1, Type t2) throws SemanticException { Type pt = promote2(t1, t2); return Types.baseType(pt); } /** All flags allowed for an initializer block. */ public Flags legalInitializerFlags() { return Static(); } protected final Flags INITIALIZER_FLAGS = legalInitializerFlags(); /** All flags allowed for a method. */ public Flags legalMethodFlags() { Flags x = legalAccessFlags().Abstract().Static().Final().Native(); x = x.Clocked().Property().Pure().Atomic(); return x; } protected final Flags METHOD_FLAGS = legalMethodFlags(); public Flags legalAbstractMethodFlags() { Flags x = legalAccessFlags().clearPrivate().Abstract(); x = x.Clocked().Property().Pure().Atomic(); return x; } protected final Flags ABSTRACT_METHOD_FLAGS = legalAbstractMethodFlags(); /** All flags allowed for a top-level class. */ public Flags legalTopLevelClassFlags() { return legalAccessFlags().clearPrivate().Abstract().Final().Interface().Clocked().Struct(); } protected final Flags TOP_LEVEL_CLASS_FLAGS = legalTopLevelClassFlags(); protected final Flags X10_TOP_LEVEL_CLASS_FLAGS = legalTopLevelClassFlags(); /** All flags allowed for an interface. */ public Flags legalInterfaceFlags() { return legalAccessFlags().Abstract().Interface().Static().Clocked(); } protected final Flags INTERFACE_FLAGS = legalInterfaceFlags(); protected final Flags X10_INTERFACE_FLAGS = legalInterfaceFlags(); /** All flags allowed for a member class. */ public Flags legalMemberClassFlags() { return legalAccessFlags().Static().Abstract().Final().Interface().Clocked().Struct(); } protected final Flags MEMBER_CLASS_FLAGS = legalMemberClassFlags(); protected final Flags X10_MEMBER_CLASS_FLAGS = legalMemberClassFlags(); /** All flags allowed for a local class. */ public Flags legalLocalClassFlags() { return Abstract().Final().Interface().Struct(); } protected final Flags LOCAL_CLASS_FLAGS = legalLocalClassFlags(); protected final Flags X10_LOCAL_CLASS_FLAGS = legalLocalClassFlags(); public Flags legalLocalFlags() { return Final().Clocked(); } protected final Flags LOCAL_FLAGS = legalLocalFlags(); protected final Flags X10_LOCAL_VARIABLE_FLAGS = legalLocalFlags(); public Flags legalFieldFlags() { return legalAccessFlags().Static().Final().Transient().Property().Clocked(); } protected final Flags FIELD_FLAGS = legalFieldFlags(); protected final Flags X10_FIELD_VARIABLE_FLAGS = legalFieldFlags(); /** All possible <i>access</i> flags. */ public Flags legalAccessFlags() { return Public().Protected().Private(); } protected final Flags ACCESS_FLAGS = legalAccessFlags(); /** All flags allowed for a constructor. */ public Flags legalConstructorFlags() { return legalAccessFlags().Native(); // allow native } protected final Flags CONSTRUCTOR_FLAGS = legalConstructorFlags(); protected final Flags X10_METHOD_FLAGS = legalMethodFlags(); public void checkMethodFlags(Flags f) throws SemanticException { // reporter.report(1, "X10TypeSystem_c:method_flags are |" + // X10_METHOD_FLAGS + "|"); if (!f.clear(X10_METHOD_FLAGS).equals(Flags.NONE)) { throw new SemanticException("Cannot declare method with flags " + f.clear(X10_METHOD_FLAGS) + "."); } if (f.isAbstract() && !f.clear(ABSTRACT_METHOD_FLAGS).equals(Flags.NONE)) { throw new SemanticException("Cannot declare abstract method with flags " + f.clear(ABSTRACT_METHOD_FLAGS) + "."); } checkAccessFlags(f); } public void checkLocalFlags(Flags f) throws SemanticException { if (! f.clear(LOCAL_FLAGS).equals(Flags.NONE)) { throw new SemanticException( "Cannot declare local variable with flags " + f.clear(LOCAL_FLAGS) + "."); } } public void checkFieldFlags(Flags f) throws SemanticException { if (! f.clear(FIELD_FLAGS).equals(Flags.NONE)) { throw new SemanticException( "Cannot declare field with flags " + f.clear(FIELD_FLAGS) + "."); } checkAccessFlags(f); } public void checkConstructorFlags(Flags f) throws SemanticException { if (! f.clear(CONSTRUCTOR_FLAGS).equals(Flags.NONE)) { throw new SemanticException( "Cannot declare constructor with flags " + f.clear(CONSTRUCTOR_FLAGS) + "."); } checkAccessFlags(f); } public void checkInitializerFlags(Flags f) throws SemanticException { if (! f.clear(INITIALIZER_FLAGS).equals(Flags.NONE)) { throw new SemanticException( "Cannot declare initializer with flags " + f.clear(INITIALIZER_FLAGS) + "."); } } public void checkTopLevelClassFlags(Flags f) throws SemanticException { if (!f.clear(X10_TOP_LEVEL_CLASS_FLAGS).equals(Flags.NONE)) { throw new SemanticException("Cannot declare a top-level class with flag(s) " + f.clear(X10_TOP_LEVEL_CLASS_FLAGS) + "."); } if (f.isInterface() && !f.clear(X10_INTERFACE_FLAGS).equals(Flags.NONE)) { throw new SemanticException("Cannot declare interface with flags " + f.clear(X10_INTERFACE_FLAGS) + "."); } checkAccessFlags(f); } public void checkMemberClassFlags(Flags f) throws SemanticException { if (!f.clear(X10_MEMBER_CLASS_FLAGS).equals(Flags.NONE)) { throw new SemanticException("Cannot declare a member class with flag(s) " + f.clear(X10_MEMBER_CLASS_FLAGS) + "."); } checkAccessFlags(f); } public void checkLocalClassFlags(Flags f) throws SemanticException { if (f.isInterface()) { throw new SemanticException("Cannot declare a local interface."); } if (!f.clear(X10_LOCAL_CLASS_FLAGS).equals(Flags.NONE)) { throw new SemanticException("Cannot declare a local class with flag(s) " + f.clear(X10_LOCAL_CLASS_FLAGS) + "."); } checkAccessFlags(f); } public void checkAccessFlags(Flags f) throws SemanticException { int count = 0; if (f.isPublic()) count++; if (f.isProtected()) count++; if (f.isPrivate()) count++; if (count > 1) { throw new SemanticException( "Invalid access flags: " + f.retain(ACCESS_FLAGS) + "."); } } /** * Utility method to gather all the superclasses and interfaces of * <code>ct</code> that may contain abstract methods that must be * implemented by <code>ct</code>. The list returned also contains * <code>rt</code>. */ public List<Type> abstractSuperInterfaces(Type t) { if (t instanceof ObjectType) { ObjectType rt = (ObjectType) t; List<Type> superInterfaces = new LinkedList<Type>(); superInterfaces.add(rt); for (Type interf : rt.interfaces()) { superInterfaces.addAll(abstractSuperInterfaces(interf)); } if (rt.superClass() instanceof ClassType) { ClassType c = (ClassType) rt.superClass(); if (c.flags().isAbstract()) { // the superclass is abstract, so it may contain methods // that must be implemented. superInterfaces.addAll(abstractSuperInterfaces(c)); } else { // the superclass is not abstract, so it must implement // all abstract methods of any interfaces it implements, and // any superclasses it may have. } } return superInterfaces; } return Collections.<Type>emptyList(); } /** * Assert that <code>ct</code> implements all abstract methods required; * that is, if it is a concrete class, then it must implement all * interfaces and abstract methods that it or it's superclasses declare, and if * it is an abstract class then any methods that it overrides are overridden * correctly. */ public void checkClassConformance(ClassType ct, Context context) throws SemanticException { env(context).checkClassConformance(ct); } public MethodInstance findImplementingMethod(ClassType ct, MethodInstance mi, Context context) { return findImplementingMethod(ct, mi, false, context); } public Flags NoFlags() { return Flags.NONE; } public Flags Public() { return Flags.PUBLIC; } public Flags Private() { return Flags.PRIVATE; } public Flags Protected() { return Flags.PROTECTED; } public Flags Static() { return Flags.STATIC; } public Flags Final() { return Flags.FINAL; } public Flags Transient() { return Flags.TRANSIENT; } public Flags Native() { return Flags.NATIVE; } public Flags Interface() { return Flags.INTERFACE; } public Flags Abstract() { return Flags.ABSTRACT; } // RMF 11/1/2005 - Not having the "static" qualifier on interfaces causes // problems, // e.g. for New_c.disambiguate(AmbiguityRemover), which assumes that // instantiating // non-static types requires a "this" qualifier expression. // [IP] FIXME: why does the above matter when we supply the bits? public Flags flagsForBits(int bits) { Flags f = Flags.NONE; if ((bits & Modifier.PUBLIC) != 0) f = f.Public(); if ((bits & Modifier.PRIVATE) != 0) f = f.Private(); if ((bits & Modifier.PROTECTED) != 0) f = f.Protected(); if ((bits & Modifier.STATIC) != 0) f = f.Static(); if ((bits & Modifier.FINAL) != 0) f = f.Final(); if ((bits & Modifier.TRANSIENT) != 0) f = f.Transient(); if ((bits & Modifier.NATIVE) != 0) f = f.Native(); if ((bits & Modifier.INTERFACE) != 0) f = f.Interface(); if ((bits & Modifier.ABSTRACT) != 0) f = f.Abstract(); if (f.isInterface()) return f.Static(); return f; } protected String getCreatorStack(int limit) { StackTraceElement[] trace = creator.getStackTrace(); // The first 3 elements will be the factory methods and the constructor int size = trace.length-3 < limit ? trace.length-3 : limit; StackTraceElement[] res = new StackTraceElement[size]; for (int i = 0; i < res.length; i++) res[i] = trace[i+3]; return Arrays.toString(res); } Name homeName = Name.make("home"); public static final int EXPAND_MACROS_DEPTH=25; public Name homeName() { return homeName;} public String toString() { return StringUtil.getShortNameComponent(getClass().getName()) + " created at " + creationTime; } /* Not used. public void existsStructWithName(Id name, ContextVisitor tc) throws SemanticException { NodeFactory nf = (NodeFactory) tc.nodeFactory(); TypeSystem ts = (TypeSystem) tc.typeSystem(); Context c = tc.context(); TypeBuilder tb = new X10TypeBuilder(tc.job(), ts, nf); // First, try to determine if there in fact a struct in scope with the given name. TypeNode otn = new X10ParsedName(nf, ts, Position.COMPILER_GENERATED, name).toType();// // nf.AmbDepTypeNode(position(), null, name(), typeArguments, Collections.EMPTY_LIST, null); TypeNode tn = (TypeNode) otn.visit(tb); // First ensure that there is a type associated with tn. tn = (TypeNode) tn.disambiguate(tc); // ok, if we made it this far, then there is a type. Check that it is a struct. Type t = tn.type(); t = ts.expandMacros(t); CConstraint xc = Types.xclause(t); t = Types.baseType(t); if (!(ts.isStructType(t))) { // bail throw new SemanticException(); } } */ private boolean isIn(Collection<FieldInstance> newFields, FieldInstance fi) { for (FieldInstance fi2 : newFields) if (fi.def()==fi2.def()) return true; return false; } public X10FieldInstance findField(Type container, Type receiver, Name name, Context context) throws SemanticException { return findField(container, false, new FieldMatcher(receiver, name, context)); } public X10FieldInstance findField(Type container, Type receiver, Name name, Context context, boolean receiverInContext) throws SemanticException { return findField(container, receiverInContext, new FieldMatcher(receiver, name, context)); } public Set<FieldInstance> findFields(Type container, Type receiver, Name name, Context context) { return findFields(container, new FieldMatcher(receiver, name, context)); } private X10FieldInstance findField(Type container, boolean receiverInContext, TypeSystem_c.FieldMatcher matcher) throws SemanticException { Context context = matcher.context(); Collection<FieldInstance> fields = findFields(container, matcher); if (fields.size() >= 2) { // if the field is defined in a class, then it will appear only once in "fields". // if it is defined in an interface (then it is either a "static val" or a property field), then it may appear multiple times in "fields", so we need to filter duplicates. // e.g., // interface I1(z:Int) { static val a = 1;} // interface I2 extends I1 {} // interface I3 extends I1 {} // interface I4 extends I2,I3 {} // class Example implements I4 { // def example() = a; // def m(a:Example{self.z==1}) = 1; // } Collection<FieldInstance> newFields = CollectionFactory.newHashSet(); for (FieldInstance fi : fields) { if ((fi.flags().isStatic())){ if (!isIn(newFields,fi)) newFields.add(fi); continue; } if (! (fi.container().toClass().flags().isInterface())){ newFields.add(fi); } } fields = newFields; } if (fields.size() == 0) { if (matcher.name().toString().equals("rank")) { int q =1; } throw new NoMemberException(NoMemberException.FIELD, "Field " + matcher.signature() + " not found in type \"" + container + "\"."); } Iterator<FieldInstance> i = fields.iterator(); X10FieldInstance fi = (X10FieldInstance) i.next(); if (i.hasNext()) { FieldInstance fi2 = i.next(); throw new SemanticException("Field " + matcher.signature() + " is ambiguous; it is defined in both " + fi.container() + " and " + fi2.container() + "."); } if (context != null && ! isAccessible(fi, context)) { throw new SemanticException("Cannot access " + fi + "."); } // todo: check it is consistent receiverInContext fi = X10FieldMatcher.instantiateAccess(fi,matcher.name,matcher.container,receiverInContext,context); return fi; } // Returns the number of bytes required to represent the type, or null if unknown (e.g. involves an address somehow) // Note for rails this returns the size of 1 element, this will have to be scaled // by the number of elements to get the true figure. public Long size(Type t) { if (t.isFloat()) return 4l; if (t.isDouble()) return 8l; if (t.isChar()) return 2l; if (t.isByte()) return 1l; if (t.isShort()) return 2l; if (t.isInt()) return 4l; if (t.isLong()) return 8l; return null; } public static class TypeEqualsInEnvironment implements Predicate2<Type> { Context context; TypeConstraint env; public TypeEqualsInEnvironment(Context context, TypeConstraint env) { this.context = context; this.env = env; } public boolean isTrue(Type o, Type p) { TypeConstraint newEnv = new TypeConstraint(); newEnv.addTerm(new SubtypeConstraint(o, p, true)); // FIXME: Vijay, why doesn't this work? return env.entails(newEnv, context); } } public static class BaseTypeEquals implements Predicate2<Type> { Context context; public BaseTypeEquals(Context context) { this.context = context; } public boolean isTrue(Type o, Type p) { TypeSystem ts = context.typeSystem(); return ts.typeEquals(Types.baseType(o), Types.baseType(p), context); } } public List<MethodInstance> methods(ContainerType t, Name name, List<Type> typeParams, List<LocalInstance> formalNames, XVar thisVar, XVar placeTerm, Context context) { XVar[] xvars = Types.toVarArray(Types.toLocalDefList(formalNames), placeTerm); List<MethodInstance> l = new ArrayList<MethodInstance>(); for (MethodInstance mi : t.methodsNamed(name)) { List<XVar> ys = new ArrayList<XVar>(2); List<XVar> xs = new ArrayList<XVar>(2); MethodInstance_c.buildSubst(mi, ys, xs, thisVar); final XVar[] y = ys.toArray(new XVar[ys.size()]); final XVar[] x = xs.toArray(new XVar[ys.size()]); mi = new X10TypeEnv_c(context).fixThis((MethodInstance) mi, y, x); if (mi.typeParameters().size() != typeParams.size()) { continue; } if (mi.formalNames().size() != formalNames.size()) { continue; } // TypeConstraint env = new TypeConstraint(); // for (int j = 0; j < mi.typeParameters().size(); j++) { // Type p1 = mi.typeParameters().get(j); // Type p2 = typeParams.get(j); // env.addTerm(new SubtypeConstraint(p1, p2, true)); // } // // if (CollectionUtil.allElementwise(argTypes, mi.formalTypes(), // new TypeEqualsInEnvironment((X10Context)context, env))) // { // l.add(mi); // } List<Type> formalTypes = new ArrayList<Type>(); for (LocalInstance li : formalNames) { formalTypes.add(li.type()); } try { XVar pt = Types.getPlaceTerm(mi); XVar[] yvars = Types.toVarArray(Types.toLocalDefList(mi.formalNames()), pt); formalTypes = Subst.subst(formalTypes, yvars, xvars); } catch (SemanticException e) { throw new InternalCompilerError("Unexpected exception while translating a method instance", e); } TypeParamSubst tps = new TypeParamSubst(this, typeParams, mi.x10Def().typeParameters()); if (CollectionUtil.allElementwise(formalTypes, tps.reinstantiate(mi.formalTypes()), new TypeEquals(context))) { l.add(mi); } } return l; } public MethodInstance findImplementingMethod(ClassType ct, MethodInstance mi, boolean includeAbstract, Context context) { XVar thisVar = ((X10ClassDef) ct.def()).thisVar(); // XTerms.makeLocal(XTerms.makeFreshName("this")); List<XVar> ys = new ArrayList<XVar>(2); List<XVar> xs = new ArrayList<XVar>(2); MethodInstance_c.buildSubst(mi, ys, xs, thisVar); MethodInstance_c.buildSubst(ct, ys, xs, thisVar); final XVar[] y = ys.toArray(new XVar[ys.size()]); final XVar[] x = xs.toArray(new XVar[ys.size()]); mi = new X10TypeEnv_c(context).fixThis( mi, y, x); XVar placeTerm = Types.getPlaceTerm(mi); context = context.pushBlock(); CConstraint cc = context.currentConstraint(); cc.addIn(thisVar, Types.realX(ct)); context.setCurrentConstraint(cc); ContainerType curr = ct; while (curr != null) { List<MethodInstance> possible = methods(curr, mi.name(), mi.typeParameters(), mi.formalNames(), thisVar, placeTerm, context); for (MethodInstance mj : possible) { if ((includeAbstract || !mj.flags().isAbstract()) && ((isAccessible(mi, context) && isAccessible(mj, context)) || isAccessible(mi, context))) { // The method mj may be a suitable implementation of mi. // mj is not abstract, and either mj's container // can access mi (thus mj can really override mi), or // mi and mj are both accessible from ct (e.g., // mi is declared in an interface that ct implements, // and mj is defined in a superclass of ct). return mj; } } if (curr.typeEquals(mi.container(), context)) { // we've reached the definition of the abstract // method. We don't want to look higher in the // hierarchy; this is not an optimization, but is // required for correctness. break; } if (curr instanceof ObjectType) { ObjectType ot = (ObjectType) curr; if (ot.superClass() instanceof ContainerType) { curr = (ContainerType) ot.superClass(); } else { curr = null; } } else { curr = null; } } return null; } // public void checkOverride(ClassType ct, MethodInstance mi0, MethodInstance mj0, Context context) throws SemanticException { // env(context).checkOverride(ct, mi0, mj0); // } public X10TypeEnv env(Context context) { return new X10TypeEnv_c(context == null ? emptyContext() : context); } public Type AnnotatedType(Position pos, Type baseType, List<Type> annotations) { baseType = baseType.annotations(annotations); return baseType; } public boolean clausesConsistent(CConstraint c1, CConstraint c2, Context context) { X10TypeEnv env = env(context); return env.clausesConsistent(c1, c2); } public Type performBinaryOperation(Type t, Type l, Type r, Binary.Operator op) { CConstraint cl = Types.realX(l); CConstraint cr = Types.realX(r); TypeSystem xts = (TypeSystem) t.typeSystem(); CConstraint c = xts.xtypeTranslator().binaryOp(op, cl, cr); return Types.xclause(Types.baseType(t), c); } public Type performUnaryOperation(Type t, Type a, polyglot.ast.Unary.Operator op) { CConstraint ca = Types.realX(a); TypeSystem xts = (TypeSystem) t.typeSystem(); CConstraint c = xts.xtypeTranslator().unaryOp(op, ca); if (c == null) return t; return Types.xclause(Types.baseType(t), c); } public void addAnnotation(X10Def o, Type annoType, boolean replace) { List<Ref<? extends Type>> newATs = new ArrayList<Ref<? extends Type>>(); if (replace) { for (Ref<? extends Type> at : o.defAnnotations()) { if (!at.get().isSubtype(Types.baseType(annoType), emptyContext())) { newATs.add(at); } } } else { newATs.addAll(o.defAnnotations()); } newATs.add(Types.ref(annoType)); o.setDefAnnotations(newATs); } /* public boolean equivClause(Type me, Type other, Context context) { return entailsClause(me, other, context) && entailsClause(other, me, context); } public boolean entailsClause(CConstraint c1, CConstraint c2, Context context, Type selfType) { return entails(c1, c2, context, selfType); } public boolean entailsClause(Type me, Type other, Context context) { try { CConstraint c1 = Types.realX(me); CConstraint c2 = Types.xclause(other); return entailsClause(c1, c2, context, null); } catch (InternalCompilerError e) { if (e.getCause() instanceof XFailure) { return false; } throw e; } } */ /* protected XLit hereConstraintLit; // Maybe this should be declared as C_Lit // instead of a concrete impl class? public XLit here() { if (hereConstraintLit == null) hereConstraintLit = xtypeTranslator().transHere(); return hereConstraintLit; } */ protected XLit FALSE; public XLit FALSE() { if (FALSE == null) FALSE = XTypeTranslator.translate(false, this); return FALSE; } protected XLit TRUE; public XLit TRUE() { if (TRUE == null) TRUE = XTypeTranslator.translate(true, this); return TRUE; } protected XLit NEG_ONE; public XLit NEG_ONE() { if (NEG_ONE == null) NEG_ONE = XTypeTranslator.translate(-1, this); return NEG_ONE; } protected XLit ZERO; public XLit ZERO() { if (ZERO == null) ZERO = XTypeTranslator.translate(0, this); return ZERO; } protected XLit ONE; public XLit ONE() { if (ONE == null) ONE = XTypeTranslator.translate(1, this); return ONE; } protected XLit TWO; public XLit TWO() { if (TWO == null) TWO = XTypeTranslator.translate(2, this); return TWO; } protected XLit THREE; public XLit THREE() { if (THREE == null) THREE = XTypeTranslator.translate(3, this); return THREE; } protected XLit NULL; public XLit NULL() { if (NULL == null) NULL = XTypeTranslator.transNull(this); return NULL; } /* public boolean entails(final CConstraint c1, final CConstraint c2, final Context context, Type selfType) { if (c1 != null || c2 != null) { boolean result = true; if (c1 != null && c2 != null) { result = c1.entails(c2, new ConstraintMaker() { public CConstraint make() throws XFailure { return context.constraintProjection(c1, c2); } }); } else if (c2 != null) { result = c2.valid(); } return result; } return true; } */ public Type promote2(Type t1, Type t2) throws SemanticException { if (isDouble(t1) || isDouble(t2)) return Double(); if (isFloat(t1) || isFloat(t2)) return Float(); if (isLong(t1) || isLong(t2)) return Long(); if (isULong(t1) || isULong(t2)) return Long(); if (isInt(t1) || isInt(t2)) return Int(); if (isUInt(t1) || isUInt(t2)) return Int(); if (isShort(t1) || isShort(t2)) return Int(); if (isChar(t1) || isChar(t2)) return Int(); if (isByte(t1) || isByte(t2)) return Int(); if (isUShort(t1) || isUShort(t2)) return Int(); if (isUByte(t1) || isUByte(t2)) return Int(); throw new SemanticException("Cannot promote non-numeric type " + t1); } public Type promote2(Type t) throws SemanticException { if (isUByte(t) || isUShort(t) || isUInt(t)) return UInt(); if (isULong(t)) return ULong(); if (isByte(t) || isShort(t) || isInt(t)) return Int(); if (isLong(t)) return Long(); if (isFloat(t)) return Float(); if (isDouble(t)) return Double(); throw new SemanticException("Cannot promote non-numeric type " + t); } public boolean typeBaseEquals(Type type1, Type type2, Context context) { assert_(type1); assert_(type2); if (type1 == type2) return true; if (type1 == null || type2 == null) return false; return typeEquals(Types.baseType(type1), Types.baseType(type2), context); } public boolean typeDeepBaseEquals(Type type1, Type type2, Context context) { assert_(type1); assert_(type2); if (type1 == type2) return true; if (type1 == null || type2 == null) return false; return typeEquals(Types.stripConstraints(type1), Types.stripConstraints(type2), context); } public X10LocalDef localDef(Position pos, Flags flags, Ref<? extends Type> type, Name name) { assert_(type); return new X10LocalDef_c(this, pos, flags, type, name); } public boolean numericConversionValid(Type t, Type fromType, java.lang.Object value, Context context) { return env(context).numericConversionValid(t, fromType, value); } protected boolean typeRefListEquals(List<Ref<? extends Type>> l1, List<Ref<? extends Type>> l2, Context context) { return CollectionUtil.<Type> allElementwise(new TransformingList<Ref<? extends Type>, Type>(l1, new DerefTransform<Type>()), new TransformingList<Ref<? extends Type>, Type>(l2, new DerefTransform<Type>()), new TypeSystem_c.TypeEquals(context)); } protected boolean typeListEquals(List<Type> l1, List<Type> l2, Context context) { return CollectionUtil.<Type> allElementwise(l1, l2, new TypeSystem_c.TypeEquals(context)); } protected boolean listEquals(List<XVar> l1, List<XVar> l2) { return CollectionUtil.<XVar> allEqual(l1, l2); } protected boolean isX10BaseSubtype(Type me, Type sup, Context context) { Type xme = Types.baseType(me); Type xsup = Types.baseType(sup); return isSubtype(xme, xsup, context); } public final Context createContext() { return emptyContext(); } public Context emptyContext() { return new Context(this); } public boolean isArray(Type t) { return finalSubtype(t, Array()); } public static Type getArrayComponentType(Type t) { List<Type> ta = ((X10ClassType)Types.baseType(t)).typeArguments(); assert (ta.size() == 1); return ta.get(0); } public boolean isArrayOf(Type t, Type p) { if (!isArray(t)) return false; return getArrayComponentType(t).typeEquals(p, createContext()); } public boolean isRemoteArray(Type t) { return finalSubtype(t, RemoteArray()); } public boolean isRemoteArrayOf(Type t, Type p) { if (!isRemoteArray(t)) return false; List<Type> ta = ((X10ClassType)Types.baseType(t)).typeArguments(); assert (ta.size() == 1); Type array_type = ta.get(0); List<Type> ta2 = ((X10ClassType)Types.baseType(array_type)).typeArguments(); assert (ta2.size() == 1); return ta2.get(0).typeEquals(p, createContext()); } public boolean hasSameClassDef(Type t1, Type t2) { Type b1 = Types.baseType(t1); Type b2 = Types.baseType(t2); if (b1 instanceof ClassType && b2 instanceof ClassType) { X10ClassType ct1 = (X10ClassType) b1; X10ClassType ct2 = (X10ClassType) b2; return ct1.def().equals(ct2.def()); } return false; } public X10ClassType Array(Type arg) { return Types.instantiate(Array(), arg); } public X10ClassType Settable(Type domain, Type range) { return Types.instantiate(Settable(), domain, range); } public boolean isX10Array(Type me) { if (finalSubtype(me, Array())) { return true; } else if (me.isClass()) { Type parent = me.toClass().superClass(); return parent != null && isX10Array(parent); } else { return false; } } public boolean isX10DistArray(Type me) { if (finalSubtype(me, DistArray())) { return true; } else if (me.isClass()) { Type parent = me.toClass().superClass(); return parent != null && isX10DistArray(parent); } else { return false; } } public boolean isIntRange(Type me) { if (finalSubtype(me, IntRange())) { return true; } else if (me.isClass()) { Type parent = me.toClass().superClass(); return parent != null && isIntRange(parent); } else { return false; } } public boolean isLongRange(Type me) { if (finalSubtype(me, LongRange())) { return true; } else if (me.isClass()) { Type parent = me.toClass().superClass(); return parent != null && isLongRange(parent); } else { return false; } } public boolean isTypeConstrained(Type me) { return me instanceof ConstrainedType; } public boolean isAny(Type me) { return typeEquals(me, Any(), emptyContext()); } public boolean isStruct(Type me) { return Types.isX10Struct(me); //typeEquals(me, Struct(), emptyContext()); } public boolean isHandOptimizedInterface(Type me) { return hasSameClassDef(me, Any()) || hasSameClassDef(me, Arithmetic()) || hasSameClassDef(me, Ordered()) || hasSameClassDef(me, Bitwise()); } public boolean isString(Type me) { return finalSubtype(me,String()); } public boolean isIndexedMemoryChunk(Type me) { return finalSubtype(me,IndexedMemoryChunk()); } public boolean isRuntime(Type me) { return finalSubtype(me,Runtime()); } public boolean isClock(Type me) { return finalSubtype(me,Clock()); } public boolean isPoint(Type me) { return finalSubtype(me,Point()); } public boolean isPlace(Type me) { return finalSubtype(me,Place()); } public boolean isRegion(Type me) { return emptyContextSubtype(me,Region()); } public boolean isDistribution(Type me) { return emptyContextSubtype(me,Dist()); } public boolean isDistributedArray(Type me) { return isX10DistArray(me); } public boolean isComparable(Type me) { return emptyContextSubtype(me,Comparable()); } public boolean isIterable(Type me) { return emptyContextSubtype(me,Iterable()); } public boolean isIterator(Type me) { return emptyContextSubtype(me,Iterator()); } public boolean isReducible(Type me) { return emptyContextSubtype(me,Reducible()); } public boolean isContains(Type me) { return emptyContextSubtype(me,Contains()); } public boolean isContainsAll(Type me) { return emptyContextSubtype(me,ContainsAll()); } public boolean isFunctionType(Type t) { t = Types.baseType(t); if (! (t instanceof X10ClassType)) { return false; } X10ClassType xt = (X10ClassType) t; return declaredFunctionType(xt) || ((X10ClassDef) xt.def()).isFunction(); } public boolean declaredFunctionType(X10ClassType t) { for (Type i : t.interfaces()) { if (i instanceof FunctionType) return true; } return false; } public boolean isExactlyFunctionType(Type t) { t = Types.baseType(t); if (! (t instanceof X10ClassType)) { return false; } X10ClassType xt = (X10ClassType) t; return (xt instanceof FunctionType) || ((X10ClassDef) xt.def()).isFunction(); } public boolean isInterfaceType(Type t) { t = Types.baseType(t); if (t instanceof ClassType) if (((ClassType) t).flags().isInterface()) return true; return false; } public Kind kind(Type t, Context c) { return env(c).kind(t); } public boolean isParameterType(Type t) { t = Types.baseType(t); return t instanceof ParameterType; } public boolean isObjectOrInterfaceType(Type t, Context c) { Kind kind = kind(t, c); return kind == Kind.OBJECT || kind == Kind.INTERFACE; } public boolean isObjectType(Type t, Context c) { return kind(t, c) == Kind.OBJECT; } public boolean isInterfaceType(Type t, Context c) { return kind(t, c) == Kind.INTERFACE; } public boolean isStructType(Type t) { return kind(t, null) == Kind.STRUCT; } public boolean isUnknown(Type t) { return Types.baseType(t) instanceof UnknownType; } public List<Type> superTypes(ObjectType t) { Type sup = t.superClass(); if (sup == null) return t.interfaces(); List<Type> ts = new ArrayList<Type>(); ts.add(sup); ts.addAll(t.interfaces()); return ts; } public List<FunctionType> getFunctionSupertypes(Type t, Context context) { if (t == null) return Collections.<FunctionType>emptyList(); List<FunctionType> l = new ArrayList<FunctionType>(); for (Type bound : env(context).upperBounds(t, false)) { if (bound instanceof FunctionType) l.add((FunctionType) bound); if (bound instanceof ObjectType) { ObjectType ot = (ObjectType) bound; for (Type ti : superTypes(ot)) { List<FunctionType> supFunctions = getFunctionSupertypes(ti, context); l.addAll(supFunctions); } } } return l; } protected XTypeTranslator xtt = new XTypeTranslator(this); public XTypeTranslator xtypeTranslator() { return xtt; } /** * Return a nullable type based on a given type. TODO: rename this to * nullableType() -- the name is misleading. */ public Type boxOf(Position pos, Ref<? extends Type> type) { return type.get(); // X10ParsedClassType box = (X10ParsedClassType) Box(); // return X10TypeMixin.instantiate(box, type); } X10ParsedClassType futureType_; public Type futureOf(Position pos, Ref<? extends Type> base) { if (futureType_ == null) futureType_ = (X10ParsedClassType) load("x10.lang.Future"); return Types.instantiate(futureType_, base); } // TODO: [IP] this should be a special CodeInstance instead public AsyncDef asyncCodeInstance(Position pos, ThisDef thisDef, List<ParameterType> typeParameters, Ref<? extends CodeInstance<?>> methodContainer, Ref<? extends ClassType> typeContainer, boolean isStatic) { // Need to create a new one on each call. Portions of this asyncDef, such as thisVar may be destructively modified later. return new AsyncDef_c(this, pos, thisDef, typeParameters, methodContainer, typeContainer, isStatic); } // TODO: [IP] this should be a special CodeInstance instead public AtDef atCodeInstance(Position pos, ThisDef thisDef, List<ParameterType> typeParameters, Ref<? extends CodeInstance<?>> methodContainer, Ref<? extends ClassType> typeContainer, boolean isStatic) { // Need to create a new one on each call. Portions of this atDef, such as thisVar may be destructively modified later. return new AtDef_c(this, pos, thisDef, typeParameters, methodContainer, typeContainer, isStatic); } public ClosureDef closureDef(Position p, Ref<? extends ClassType> typeContainer, Ref<? extends CodeInstance<?>> methodContainer, Ref<? extends Type> returnType, List<Ref<? extends Type>> argTypes, ThisDef thisDef, List<LocalDef> formalNames, Ref<CConstraint> guard, Ref<? extends Type> offerType) { return new ClosureDef_c(this, p, typeContainer, methodContainer, returnType, argTypes, thisDef, formalNames, guard, offerType); } public FunctionType functionType(Position p, Ref<? extends Type> returnType, List<ParameterType> typeParameters, List<Ref<? extends Type>> argTypes, List<LocalDef> formalNames, Ref<CConstraint> guard //Ref<TypeConstraint> typeGuard, ) { Type rt = Types.get(returnType); X10ClassDef def = ClosureSynthesizer.closureBaseInterfaceDef(this, typeParameters.size(), argTypes.size(), rt.isVoid(), formalNames, guard); FunctionType ct = (FunctionType) def.asType(); XVar[] yvars = Types.toVarArray(Types.toLocalDefList(ct.formalNames())); XVar[] xvars = Types.toVarArray(formalNames); List<Type> typeArgs = new ArrayList<Type>(); for (Ref<? extends Type> ref : argTypes) { Type t = Types.get(ref); try { t = Subst.subst(t, yvars, xvars); } catch (SemanticException e) { throw new InternalCompilerError("Unexpected exception while creating a function type", p, e); } typeArgs.add(t); } if (!rt.isVoid()) { try { rt = Subst.subst(rt, yvars, xvars); } catch (SemanticException e) { throw new InternalCompilerError("Unexpected exception while creating a function type", p, e); } typeArgs.add(rt); } return (FunctionType) ct.typeArguments(typeArgs); } public ClosureType closureType(ClosureDef cd) { X10ClassDef def = ClosureSynthesizer.closureAnonymousClassDef(this, cd); return (ClosureType) def.asType(); } public Type expandMacros(Type t) { return expandMacros(t, 0); } private Type expandMacros(Type t, int depth) { if (depth > TypeSystem_c.EXPAND_MACROS_DEPTH) { Errors.issue(t.typeSystem().extensionInfo(),new Errors.MaxMacroExpansionDepth(t,t.position()),t.position()); return unknownType(Position.COMPILER_GENERATED); // bottom } /*if (t instanceof AnnotatedType) return expandMacros(((AnnotatedType) t).baseType(), depth+1); */ if (t instanceof MacroType) return expandMacros(((MacroType) t).definedType(), depth+1); if (t instanceof ConstrainedType) { ConstrainedType ct = (ConstrainedType) t; Type base = ct.baseType().get(); Type ebase = expandMacros(base, depth+1); if (base == ebase) return t; // yoav todo: why are we looking only at the base and not at the constraint that we should expand??? CConstraint c = ct.constraint().get(); return Types.xclause(ebase, c); } return t; } public boolean equalTypeParameters(List<Type> a, List<Type> b, Context context) { if (a == null || a.isEmpty()) return b == null || b.isEmpty(); if (b == null || b.isEmpty()) return false; int i = a.size(), j = b.size(); if (i != j) return false; boolean result = true; for (int k = 0; result && k < i; k++) { result = typeEquals(a.get(k), b.get(k), context); } return result; } private static final String WRAPPER_PACKAGE = "x10.compilergenerated"; public List<X10ClassType> allImplementedInterfaces(X10ClassType c) { return allImplementedInterfaces(c, true); } public List<X10ClassType> allImplementedInterfaces(X10ClassType c, boolean checkSuperClasses) { List<X10ClassType> ans = new ArrayList<X10ClassType>(); allImplementedInterfaces(c, checkSuperClasses, ans); return ans; } private void allImplementedInterfaces(X10ClassType c, boolean checkSuperClasses, List<X10ClassType> l) { Context context = createContext(); //if (c.typeEquals(Object(), context)) { // return; //} for (Type old : l) { if (c.typeEquals(old, context)) { return; /* Already been here */ } } if (c.flags().isInterface()) { l.add(c); } if (checkSuperClasses && c.superClass() != null) { allImplementedInterfaces((X10ClassType)Types.baseType(c.superClass()), checkSuperClasses, l); } for (Type parent : c.interfaces()) { allImplementedInterfaces((X10ClassType)Types.baseType(parent), checkSuperClasses, l); } } // User-defined structs and do they have zero (haszero) // This is not just a cache: we use this map to prevent infinite recursion such as in the case of: // struct U(u:U) {} public Map<X10ClassDef_c, Boolean> structHaszero = CollectionFactory.newHashMap(); public Boolean structHaszero(X10ClassDef x) { return structHaszero.get(x); } public Map<X10ClassDef_c, Boolean> structHaszero() { return structHaszero; } public boolean hasUnknown(Type t) { return hasUnknownType(t,new HashSet<Type>()); } private boolean hasUnknownType(Type t, HashSet<Type> visited) { if (visited.contains(t)) { return false; } visited.add(t); if (isUnknown(t)) { return true; } if (t instanceof X10ClassType) { X10ClassType ct = (X10ClassType) t; if (ct.typeArguments() != null) { for (Type a : ct.typeArguments()) { if (hasUnknownType(a, visited)) { return true; } } } if (ct.x10Def().isFunction()) { // Look at the superclass and interfaces (if any) if (hasUnknownType(ct.superClass(),visited)) { return true; } for (Type i : ct.interfaces()) { if (hasUnknownType(i, visited)) { return true; } } } } /*if (t instanceof AnnotatedType) { if (hasUnknownType(X10TypeMixin.baseType(t))) { unknownTypeMap.put(t, true); return true; } AnnotatedType at = (AnnotatedType) t; List<Type> ann = at.annotations(); for (Type a : ann) { if (hasUnknownType(a)) { unknownTypeMap.put(t, true); return true; } } }*/ if (t instanceof ConstrainedType) { if (hasUnknownType(Types.baseType(t),visited)) { return true; } ConstrainedType ct = (ConstrainedType) t; CConstraint c = Types.xclause(ct); for (XVar x : c.vars()) { if (hasUnknown(x, visited)) { return true; } } for (XFormula x : c.atoms()) { //assert x != null; if (hasUnknown(x, visited)) { return true; } } } return false; } private boolean hasUnknown(XFormula<?> x, HashSet<Type> visited) { for (XTerm a : x.arguments()) { if (hasUnknown(a, visited)) return true; } return false; } private boolean hasUnknown(XTerm x, HashSet<Type> visited) { if (x instanceof XField<?>) { if (hasUnknown(((XField<?>) x).receiver(),visited)) return true; if (x instanceof CField) return hasUnknownType(((CField) x).type(),visited); } if (x instanceof XTypeLit) { return hasUnknownType(((XTypeLit) x).type(),visited); } if (x instanceof CLocal) return hasUnknownType(((CLocal) x).type(),visited); return false; } /** Return true if the constraint is consistent. */ public boolean consistent(CConstraint c) { return env(null).consistent(c); } /** Return true if the constraint is consistent. */ public boolean consistent(TypeConstraint c, Context context) { return env(context).consistent(c); } /** Return true if constraints in the type are all consistent. */ public boolean consistent(Type t, Context context) { return env(context).consistent(t); } /** * Returns true iff <p1> throws fewer exceptions than <p2>. */ public <T extends ProcedureDef> boolean throwsSubset(ProcedureInstance<T> p1, ProcedureInstance<T> p2) { assert_(p1); assert_(p2); return ((ProcedureInstance_c<T>) p1).throwsSubset(p2); } // checks that the number of type args match the number of type params public static void internalConsistencyCheck (Type t) { if (t instanceof X10ParsedClassType_c) { X10ParsedClassType_c t2 = (X10ParsedClassType_c) t; X10ClassDef t2_def = t2.def(); List<ParameterType> t2_params = t2_def.typeParameters(); List<Type> t2_args = t2.typeArguments(); int num_params = t2_params.size(); // sometimes t2_args == null means it has not yet been filled in // sometimes it means 0 args // this ambiguity weakens the following check but that's life if (t2_args == null) { return; } int num_args = t2_args.size(); // sometimes num_args==0 can mean that the type is used in a static fashion // e.g. class C[T] { static PI = 3.142; } ... C.PI; if (num_args == 0) return; if (num_params != num_args) { throw new InternalCompilerError(t+" has "+t2_params+" type params but "+t2_args+" type arguments."); } } else if (t instanceof ConstrainedType) { ConstrainedType t2 = (ConstrainedType) t; internalConsistencyCheck(t2.baseType().get()); // Look for broken types inside variables in the constraint CConstraint c = t2.constraint().get(); for (XTerm xt : c.getTerms()) { if (xt instanceof CNativeLocal) { X10LocalDef xld = ((CNativeLocal) xt).name(); Type t3 = xld.type().get(); if (t3 == t) return; // simple cycle check internalConsistencyCheck(t3); } } } } // calling this on unpopulated mi may result in a runtime error public static void internalConsistencyCheck (MethodInstance mi) { for (Type t : mi.formalTypes()) { TypeSystem_c.internalConsistencyCheck(t); } for (Ref<? extends Type> t : mi.def().formalTypes()) { TypeSystem_c.internalConsistencyCheck(t.get()); } for (LocalDef ld : mi.def().formalNames()) { TypeSystem_c.internalConsistencyCheck(ld.type().get()); } for (LocalInstance li : mi.formalNames()) { TypeSystem_c.internalConsistencyCheck(li.type()); } } }