Clover coverage report - DynamicJava Test Coverage (dynamicjava-20130615-r5436)
Coverage timestamp: Sat Jun 15 2013 03:01:32 CDT
file stats: LOC: 638   Methods: 36
NCLOC: 256   Classes: 17
 
 Source file Conditionals Statements Methods TOTAL
TypeSystem.java 27.8% 63.2% 72.2% 60.4%
coverage coverage
 1    package edu.rice.cs.dynamicjava.symbol;
 2   
 3    import edu.rice.cs.dynamicjava.symbol.type.*;
 4    import koala.dynamicjava.tree.Expression;
 5   
 6    import edu.rice.cs.plt.tuple.Pair;
 7    import edu.rice.cs.plt.tuple.Option;
 8    import edu.rice.cs.plt.iter.IterUtil;
 9    import edu.rice.cs.plt.lambda.Thunk;
 10    import edu.rice.cs.plt.lambda.Lambda;
 11    import edu.rice.cs.plt.object.ObjectUtil;
 12   
 13    import java.io.Serializable;
 14   
 15    import static edu.rice.cs.plt.debug.DebugUtil.debug;
 16   
 17    /** A type system allows for variance in the typing rules of the system, while maintaining
 18    * a standard type checker. It separates the type checker from most of the details of type
 19    * implementations. For simplicity, it is also defined independently of most type-checker implementation
 20    * issues, such as syntax. To enforce these relationships, the type checker should minimize
 21    * references to specific subtypes of {@link Type}; and the type system should minimize references
 22    * to specific subtypes of {@link Expression}.
 23    */
 24    public abstract class TypeSystem {
 25   
 26    public static final BooleanType BOOLEAN = new BooleanType();
 27    public static final CharType CHAR = new CharType();
 28    public static final ByteType BYTE = new ByteType();
 29    public static final ShortType SHORT = new ShortType();
 30    public static final IntType INT = new IntType();
 31    public static final LongType LONG = new LongType();
 32    public static final FloatType FLOAT = new FloatType();
 33    public static final DoubleType DOUBLE = new DoubleType();
 34    public static final NullType NULL = new NullType();
 35    public static final VoidType VOID = new VoidType();
 36    public static final TopType TOP = new TopType();
 37    public static final BottomType BOTTOM = new BottomType();
 38   
 39    public static final SimpleClassType OBJECT = new SimpleClassType(SymbolUtil.wrapClass(Object.class));
 40    public static final SimpleClassType STRING = new SimpleClassType(SymbolUtil.wrapClass(String.class));
 41    public static final SimpleClassType CLONEABLE = new SimpleClassType(SymbolUtil.wrapClass(Cloneable.class));
 42    public static final SimpleClassType SERIALIZABLE = new SimpleClassType(SymbolUtil.wrapClass(Serializable.class));
 43    public static final SimpleClassType THROWABLE = new SimpleClassType(SymbolUtil.wrapClass(Throwable.class));
 44    public static final SimpleClassType EXCEPTION = new SimpleClassType(SymbolUtil.wrapClass(Exception.class));
 45    public static final SimpleClassType RUNTIME_EXCEPTION =
 46    new SimpleClassType(SymbolUtil.wrapClass(RuntimeException.class));
 47    public static final SimpleClassType BOOLEAN_CLASS = new SimpleClassType(SymbolUtil.wrapClass(Boolean.class));
 48    public static final SimpleClassType CHARACTER_CLASS = new SimpleClassType(SymbolUtil.wrapClass(Character.class));
 49    public static final SimpleClassType BYTE_CLASS = new SimpleClassType(SymbolUtil.wrapClass(Byte.class));
 50    public static final SimpleClassType SHORT_CLASS = new SimpleClassType(SymbolUtil.wrapClass(Short.class));
 51    public static final SimpleClassType INTEGER_CLASS = new SimpleClassType(SymbolUtil.wrapClass(Integer.class));
 52    public static final SimpleClassType LONG_CLASS = new SimpleClassType(SymbolUtil.wrapClass(Long.class));
 53    public static final SimpleClassType FLOAT_CLASS = new SimpleClassType(SymbolUtil.wrapClass(Float.class));
 54    public static final SimpleClassType DOUBLE_CLASS = new SimpleClassType(SymbolUtil.wrapClass(Double.class));
 55    public static final SimpleClassType VOID_CLASS = new SimpleClassType(SymbolUtil.wrapClass(Void.class));
 56   
 57    protected static final Type[] EMPTY_TYPE_ARRAY = new Type[0];
 58    protected static final Iterable<Type> EMPTY_TYPE_ITERABLE = IterUtil.empty();
 59    protected static final Iterable<Expression> EMPTY_EXPRESSION_ITERABLE = IterUtil.empty();
 60    protected static final Option<Type> NONE_TYPE_OPTION = Option.none();
 61   
 62  3887 public TypeWrapper wrap(Type t) { return (t == null) ? null : new TypeWrapper(t); }
 63   
 64  1104 public Iterable<TypeWrapper> wrap(Iterable<? extends Type> ts) {
 65  1104 return (ts == null) ? null : IterUtil.map(ts, WRAP_TYPE);
 66    }
 67   
 68    private final Lambda<Type, TypeWrapper> WRAP_TYPE = new Lambda<Type, TypeWrapper>() {
 69  0 public TypeWrapper value(Type t) { return (t == null) ? null : new TypeWrapper(t); }
 70    };
 71   
 72  552 public Option<TypeWrapper> wrap(Option<Type> t) {
 73  0 if (t == null) return null;
 74  552 else return t.isSome() ? Option.some(new TypeWrapper(t.unwrap())) : Option.<TypeWrapper>none();
 75    }
 76   
 77    /**
 78    * A wrapper for types that provides an alternate {@code toString()} and {@code equals()} implementation:
 79    * {@code toString()} is defined in terms of {@link #userRepresentation}; {@code equals()} is defined
 80    * in terms of {@link #isEqual}. (Note that a corresponding {@code hashCode()} function is not implemented.)
 81    */
 82    public class TypeWrapper {
 83    private Type _t;
 84  4055 public TypeWrapper(Type t) { _t = t; }
 85    /** Produce a string using {@link #userRepresentation}. */
 86  0 public String toString() { return typePrinter().print(_t); }
 87    /** Compare two TypeWrappers using {@link #isEqual}. */
 88  0 public boolean equals(Object o) {
 89  0 if (this == o) { return true; }
 90  0 else if (!(o instanceof TypeWrapper)) { return false; }
 91  0 else { return isEqual(_t, ((TypeWrapper) o)._t); }
 92    }
 93    /** Throws an UnsupportedOperationException. */
 94  0 public int hashCode() { throw new UnsupportedOperationException(); }
 95    }
 96   
 97   
 98    public abstract TypePrinter typePrinter();
 99   
 100    /* Type Predicates */
 101   
 102    /** Determine if {@code t} is a primitive. */
 103    public abstract boolean isPrimitive(Type t);
 104   
 105    /** Determine if {@code t} is a reference. */
 106    public abstract boolean isReference(Type t);
 107   
 108    /** Determine if {@code t} is an array. */
 109    public abstract boolean isArray(Type t);
 110   
 111   
 112    /** Determine if the type is well-formed. */
 113    public abstract boolean isWellFormed(Type t);
 114   
 115    /**
 116    * Determine if the type can be used in an enhanced for loop. {@code true} implies that an object of
 117    * type {@code t} has member {@code iterator()}, which returns a {@link java.util.Iterator}.
 118    */
 119    public abstract boolean isIterable(Type t);
 120   
 121    /**
 122    * Determine if an object with type {@code t} is enumerable (and so can be used as the selector of a
 123    * {@code switch} statement)
 124    */
 125    public abstract boolean isEnum(Type t);
 126   
 127    /** Determine if the type is available at runtime (via a {@link Class} object) */
 128    public abstract boolean isReifiable(Type t);
 129   
 130    /**
 131    * Determine if there exist values whose most specific type is {@code t} (ignoring
 132    * constructor-accessibility issues). (Note that this implies that {@code t} is captured.)
 133    */
 134    public abstract boolean isConcrete(Type t);
 135   
 136    /** Determine if {@code t} is valid in the {@code extends} clause of a class definition */
 137    public abstract boolean isExtendable(Type t);
 138   
 139    /** Determine if {@code t} is valid in the {@code implements} clause of a class definition */
 140    public abstract boolean isImplementable(Type t);
 141   
 142   
 143    /* Fundamental Type Relationships */
 144   
 145    /** Determine if the given types may be treated as equal. This is recursive, transitive, and symmetric. */
 146    public abstract boolean isEqual(Type t1, Type t2);
 147   
 148    /**
 149    * Determine if {@code subT} is a subtype of {@code superT}. This is a recursive
 150    * (in terms of {@link #isEqual}), transitive relation.
 151    */
 152    public abstract boolean isSubtype(Type subT, Type superT);
 153   
 154    /** Whether two types are known to be disjoint. */
 155    public abstract boolean isDisjoint(Type t1, Type t2);
 156   
 157    /** Determine if {@link #assign} would succeed given a non-constant expression of the given type */
 158    public abstract boolean isAssignable(Type target, Type expT);
 159   
 160    /** Determine if {@link #assign} would succeed given a constant expression of the given type and value */
 161    public abstract boolean isAssignable(Type target, Type expT, Object expValue);
 162   
 163    /** Determine if {@link #makePrimitive} would succeed given an expression of the given type */
 164    public abstract boolean isPrimitiveConvertible(Type t);
 165   
 166    /** Determine if {@link #makeReference} would succeed given an expression of the given type */
 167    public abstract boolean isReferenceConvertible(Type t);
 168   
 169    /** Compute a common supertype of the given list of types. */
 170    public abstract Type join(Iterable<? extends Type> ts);
 171   
 172    /** Compute a common supertype of the given pair of types. */
 173  0 public Type join(Type t1, Type t2) { return join(IterUtil.make(t1, t2)); }
 174   
 175    /** Compute a common subtype of the given list of types. */
 176    public abstract Type meet(Iterable<? extends Type> ts);
 177   
 178    /** Compute a common supertype of the given pair of types. */
 179  0 public Type meet(Type t1, Type t2) { return meet(IterUtil.make(t1, t2)); }
 180   
 181   
 182    /* Unary Operations on Types */
 183   
 184    /**
 185    * Compute the capture of {@code t}. Capture eliminates wildcards in a {@link ParameterizedClassType}
 186    * and converts VarargArrayTypes to StandardArrayTypes.
 187    */
 188    public abstract Type capture(Type t);
 189   
 190    /**
 191    * Compute the erased type of {@code t}. The result is guaranteed to be reifiable (according
 192    * to {@link #isReifiable}) and a supertype of {@code t}.
 193    */
 194    public abstract Type erase(Type t);
 195   
 196    /**
 197    * Determine the class corresponding to the erasure of {@code t}. To prevent over-eager loading of
 198    * user-defined classes, computation of the result is delayed by wrapping it in a thunk. (A DJClass
 199    * return type would be incorrect, as there's no such thing (for example) as an array DJClass.)
 200    */
 201    public abstract Thunk<Class<?>> erasedClass(Type t);
 202   
 203    /**
 204    * Determine the type of the class object associated with t (for example, (informally)
 205    * {@code classOf(Integer) = Class<Integer>}).
 206    */
 207    public abstract Type reflectionClassOf(Type t);
 208   
 209   
 210    /**
 211    * Determine the element type of the given array type. Assumes {@code t} is an array type (according to
 212    * {@link #isArray}).
 213    */
 214    public abstract Type arrayElementType(Type t);
 215   
 216    /** Get the type of the object, if any, that dynamically encloses instances of {@code t}. */
 217    public abstract Option<Type> dynamicallyEnclosingType(Type t);
 218   
 219    /* Class Type Operations */
 220   
 221    /** Create a {@link SimpleClassType} or {@link RawClassType} corresponding to the given class. */
 222    public abstract ClassType makeClassType(DJClass c);
 223   
 224    /**
 225    * Create a {@link SimpleClassType}, {@link RawClassType}, or {@link ParameterizedClassType}
 226    * corresponding to the given class with given type arguments. If {@code args} is nonempty,
 227    * the result must be a {@code ParameterizedClassType} (or an error must occur).
 228    *
 229    * @param c The class to be instantiated
 230    * @param args The type arguments for {@code c}
 231    * @throws InvalidTypeArgumentException If the arguments do not correspond to the formal parameters of
 232    * {@code c} (bounds are not checked, so the result may not be
 233    * well-formed).
 234    */
 235    public abstract ClassType makeClassType(DJClass c, Iterable<? extends Type> args)
 236    throws InvalidTypeArgumentException;
 237   
 238   
 239    /* Conversions on Expressions */
 240   
 241    /**
 242    * Convert the expression to a primitive. The result is guaranteed to have a primitive type as its
 243    * TYPE property (according to {@link #isPrimitive}).
 244    *
 245    * @param e A typed expression
 246    * @return A typed expression equivalent to {@code e} that has a primitive type
 247    * @throws UnsupportedConversionException If the expression cannot be converted to a primitive
 248    */
 249    public abstract Expression makePrimitive(Expression e) throws UnsupportedConversionException;
 250   
 251    /**
 252    * Convert the expression to a reference. The result is guaranteed to have a reference type as its
 253    * TYPE property (according to {@link #isReference}).
 254    *
 255    * @param e A typed expression
 256    * @return A typed expression equivalent to {@code e} that has a reference type
 257    * @throws UnsupportedConversionException If the expression cannot be converted to a reference
 258    */
 259    public abstract Expression makeReference(Expression e) throws UnsupportedConversionException;
 260   
 261    /**
 262    * Perform unary numeric promotion on an expression.
 263    *
 264    * @param e A typed expression with a primitive type
 265    * @return A typed expression equivalent to {@code e} with the promoted type
 266    * @throws UnsupportedConversionException If the expression cannot be used for numeric promotion
 267    */
 268    public abstract Expression unaryPromote(Expression e) throws UnsupportedConversionException;
 269   
 270    /**
 271    * Perform binary numeric promotion on a pair of expressions. The resulting pair of expressions
 272    * are guaranteed to have the same type.
 273    *
 274    * @param e1 A typed expression with a primitive type
 275    * @param e2 A typed expression with a primitive type
 276    * @return Two typed expressions equivalent to {@code e1} and {@code e2} with the promoted type
 277    * @throws UnsupportedConversionException If either expression cannot be used for numeric promotion
 278    */
 279    public abstract Pair<Expression, Expression> binaryPromote(Expression e1, Expression e2)
 280    throws UnsupportedConversionException;
 281   
 282    /**
 283    * Perform a join (as defined for the ? : operator) on a pair of expressions. The resulting pair
 284    * of expressions are guaranteed to have the same type. That type may contain uncaptured wildcards.
 285    *
 286    * @param e1 A typed expression
 287    * @param e2 A typed expression
 288    * @return Two typed expressions equivalent to {@code e1} and {@code e2} with the joined type
 289    * @throws UnsupportedConversionException If the two types are incompatible.
 290    */
 291    public abstract Pair<Expression, Expression> mergeConditional(Expression e1, Expression e2)
 292    throws UnsupportedConversionException;
 293   
 294    /**
 295    * Perform a cast on the given expression. Any necessary conversions are performed. If necessary,
 296    * the {@code CHECKED_TYPE} and {@code CONVERTED_TYPE} properties are set on the result.
 297    *
 298    * @return An expression equivalent to {@code e}, wrapped in any necessary conversions
 299    * @throws UnsupportedConversionException If the cast is to an incompatible type.
 300    */
 301    public abstract Expression cast(Type target, Expression e) throws UnsupportedConversionException;
 302   
 303    /**
 304    * Prepare the given expression for assignment, wrapping it in any necessary conversions.
 305    *
 306    * @return An expression equivalent to {@code e}, wrapped in any necessary conversions
 307    * @throws UnsupportedConversionException If assignment to the given type is incorrect.
 308    */
 309    public abstract Expression assign(Type target, Expression e) throws UnsupportedConversionException;
 310   
 311   
 312    /* Member lookup operations */
 313   
 314    /**
 315    * Lookup the constructor corresponding the the given invocation.
 316    * @param t The type of the object to be constructed.
 317    * @param typeArgs The type arguments for the constructor's type parameters.
 318    * @param args A list of typed expressions corresponding to the constructor's parameters.
 319    * @param expected The type expected in the invocation's calling context, if any.
 320    * @return A {@link ConstructorInvocation} object representing the matched constructor.
 321    * @throws InvalidTypeArgumentException If the type arguments are invalid (for example, a primitive type).
 322    * @throws UnmatchedLookupException If 0 or more than 1 constructor matches the given arguments and type
 323    * arguments.
 324    */
 325    // Must produce a reasonable value when looking up a constructor in an interface (for anonymous classes)
 326    public abstract ConstructorInvocation lookupConstructor(Type t, Iterable<? extends Type> typeArgs,
 327    Iterable<? extends Expression> args,
 328    Option<Type> expected, Access.Module accessModule)
 329    throws InvalidTypeArgumentException, UnmatchedLookupException;
 330   
 331   
 332    public abstract boolean containsMethod(Type t, String name, Access.Module accessModule);
 333   
 334    public abstract boolean containsStaticMethod(Type t, String name, Access.Module accessModule);
 335   
 336    /**
 337    * Lookup the method corresponding the the given invocation.
 338    * @param object A typed expression representing the object whose method is to be invoked.
 339    * @param name The name of the method.
 340    * @param typeArgs The type arguments for the method's type parameters.
 341    * @param args A list of typed expressions corresponding to the method's parameters.
 342    * @param expected The type expected in the invocation's calling context, if any.
 343    * @return An {@link ObjectMethodInvocation} object representing the matched method.
 344    * @throws InvalidTypeArgumentException If the type arguments are invalid (for example, a primitive type).
 345    * @throws UnmatchedLookupException If 0 or more than 1 method matches the given name, arguments, and type
 346    * arguments.
 347    */
 348    public abstract ObjectMethodInvocation lookupMethod(Expression object, String name,
 349    Iterable<? extends Type> typeArgs,
 350    Iterable<? extends Expression> args,
 351    Option<Type> expected, Access.Module accessModule)
 352    throws InvalidTypeArgumentException, UnmatchedLookupException;
 353   
 354   
 355    /**
 356    * Lookup the static method corresponding the the given invocation.
 357    * @param t The type in which to search for a static method.
 358    * @param name The name of the method.
 359    * @param typeArgs The type arguments for the method's type parameters.
 360    * @param args A list of typed expressions corresponding to the method's parameters.
 361    * @param expected The type expected in the invocation's calling context, if any.
 362    * @return A {@link StaticMethodInvocation} object representing the matched method.
 363    * @throws InvalidTypeArgumentException If the type arguments are invalid (for example, a primitive type).
 364    * @throws UnmatchedLookupException If 0 or more than 1 method matches the given name, arguments, and type
 365    * arguments.
 366    */
 367    public abstract StaticMethodInvocation lookupStaticMethod(Type t, String name,
 368    Iterable<? extends Type> typeArgs,
 369    Iterable<? extends Expression> args,
 370    Option<Type> expected, Access.Module accessModule)
 371    throws InvalidTypeArgumentException, UnmatchedLookupException;
 372   
 373   
 374    public abstract boolean containsField(Type t, String name, Access.Module accessModule);
 375   
 376    public abstract boolean containsStaticField(Type t, String name, Access.Module accessModule);
 377   
 378    /**
 379    * Lookup the field with the given name in the given object.
 380    * @param object A typed expression representing the object whose field is to be accessed.
 381    * @param name The name of the field.
 382    * @return An {@link ObjectFieldReference} object representing the matched field.
 383    * @throws UnmatchedLookupException If 0 or more than 1 field matches the given name.
 384    */
 385    public abstract ObjectFieldReference lookupField(Expression object, String name, Access.Module accessModule)
 386    throws UnmatchedLookupException;
 387   
 388    /**
 389    * Lookup the static field with the given name.
 390    * @param t The type in which to search for a static field.
 391    * @param name The name of the field.
 392    * @return A {@link StaticFieldReference} object representing the matched field.
 393    * @throws UnmatchedLookupException If 0 or more than 1 field matches the given name.
 394    */
 395    public abstract StaticFieldReference lookupStaticField(Type t, String name, Access.Module accessModule)
 396    throws UnmatchedLookupException;
 397   
 398   
 399    public abstract boolean containsClass(Type t, String name, Access.Module accessModule);
 400   
 401    public abstract boolean containsStaticClass(Type t, String name, Access.Module accessModule);
 402   
 403    /**
 404    * Lookup the class with the given name in the given object.
 405    * @param object A typed expression representing the object whose class is to be accessed.
 406    * @param name The name of the class.
 407    * @param typeArgs The type arguments for the class
 408    * @return A type representing the named class.
 409    * @throws InvalidTypeArgumentException If the type arguments are invalid or do not correspond to the
 410    * class's formal parameters (bounds are not checked, so the result
 411    * may not be well-formed).
 412    * @throws UnmatchedLookupException If 0 or more than 1 class matches the given name.
 413    */
 414    public abstract ClassType lookupClass(Expression object, String name, Iterable<? extends Type> typeArgs,
 415    Access.Module accessModule)
 416    throws InvalidTypeArgumentException, UnmatchedLookupException;
 417   
 418    /**
 419    * Lookup the class with the given name in the given type.
 420    * @param t The type in which to search for a static class.
 421    * @param name The name of the class.
 422    * @param typeArgs The type arguments for the class
 423    * @return A type representing the named class.
 424    * @throws InvalidTypeArgumentException If the type arguments are invalid or do not correspond to the
 425    * class's formal parameters (bounds are not checked, so the
 426    * result may not be well-formed).
 427    * @throws UnmatchedLookupException If 0 or more than 1 class matches the given name.
 428    */
 429    public abstract ClassType lookupClass(Type t, String name, Iterable<? extends Type> typeArgs,
 430    Access.Module accessModule)
 431    throws InvalidTypeArgumentException, UnmatchedLookupException;
 432   
 433    /**
 434    * Lookup the static class with the given name.
 435    * @param t The type in which to search for a static class.
 436    * @param name The name of the class.
 437    * @param typeArgs The type arguments for the class
 438    * @return A type representing the named class.
 439    * @throws InvalidTypeArgumentException If the type arguments are invalid or do not correspond to the
 440    * class's formal parameters (bounds are not checked, so the result
 441    * may not be well-formed).
 442    * @throws UnmatchedLookupException If 0 or more than 1 class matches the given name.
 443    */
 444    public abstract ClassType lookupStaticClass(Type t, String name, Iterable<? extends Type> typeArgs,
 445    Access.Module accessModule)
 446    throws InvalidTypeArgumentException, UnmatchedLookupException;
 447   
 448   
 449    public static interface TypePrinter {
 450    /** Produce a string representing the type */
 451    public String print(Type t);
 452    /** Produce a string representing the list of types */
 453    public String print(Iterable<? extends Type> ts);
 454    /** Produce a string representing the signature of the function */
 455    public String print(Function f);
 456    }
 457   
 458    /** Abstraction of the result of a method or constructor lookup */
 459    public static abstract class FunctionInvocation {
 460    private final Iterable<? extends Type> _typeArgs;
 461    private final Iterable<? extends Expression> _args;
 462    private final Iterable<? extends Type> _thrown;
 463   
 464  821 protected FunctionInvocation(Iterable<? extends Type> typeArgs, Iterable<? extends Expression> args,
 465    Iterable<? extends Type> thrown) {
 466  821 _typeArgs = typeArgs;
 467  821 _args = args;
 468  821 _thrown = thrown;
 469    }
 470   
 471    /** @return The (possible inferred) type arguments used in the invocation */
 472  0 public Iterable<? extends Type> typeArgs() { return _typeArgs; }
 473   
 474    /**
 475    * @return The arguments, wrapped in any necessary promotions so that each expression has the same
 476    * type as its corresponding formal parameter.
 477    */
 478  815 public Iterable<? extends Expression> args() { return _args; }
 479   
 480    /** @return The declared thrown types of the invocation */
 481  789 public Iterable<? extends Type> thrown() { return _thrown; }
 482    }
 483   
 484   
 485    /** The result of a constructor lookup */
 486    public static class ConstructorInvocation extends FunctionInvocation {
 487    private final DJConstructor _constructor;
 488   
 489  551 public ConstructorInvocation(DJConstructor constructor, Iterable<? extends Type> typeArgs,
 490    Iterable<? extends Expression> args, Iterable<? extends Type> thrown) {
 491  551 super(typeArgs, args, thrown);
 492  551 _constructor = constructor;
 493    }
 494   
 495    /** @return The reflection object corresponding to the invoked constructor */
 496  551 public DJConstructor constructor() { return _constructor; }
 497    }
 498   
 499   
 500    /** Abstraction of the result of a static or non-static method lookup */
 501    public static abstract class MethodInvocation extends FunctionInvocation {
 502    private final DJMethod _method;
 503    private final Type _returnType;
 504   
 505  270 protected MethodInvocation(DJMethod method, Type returnType, Iterable<? extends Type> typeArgs,
 506    Iterable<? extends Expression> args, Iterable<? extends Type> thrown) {
 507  270 super(typeArgs, args, thrown);
 508  270 _method = method;
 509  270 _returnType = returnType;
 510    }
 511   
 512    /** @return The reflection object corresponding to the invoked method */
 513  502 public DJMethod method() { return _method; }
 514   
 515    /** @return The return type of the invocation (before capture) */
 516  270 public Type returnType() { return _returnType; }
 517   
 518    }
 519   
 520   
 521    /** The result of a non-static method lookup */
 522    public static class ObjectMethodInvocation extends MethodInvocation {
 523    private final Expression _object;
 524   
 525  97 public ObjectMethodInvocation(DJMethod method, Type returnType, Expression object,
 526    Iterable<? extends Type> typeArgs, Iterable<? extends Expression> args,
 527    Iterable<? extends Type> thrown) {
 528  97 super(method, returnType, typeArgs, args, thrown);
 529  97 _object = object;
 530    }
 531   
 532    /**
 533    * @return The object whose method is invoked, wrapped in any necessary promotions so that
 534    * the type is the type whose declared member is the matched method.
 535    */
 536  91 public Expression object() { return _object; }
 537    }
 538   
 539   
 540    /** The result of a static method lookup */
 541    public static class StaticMethodInvocation extends MethodInvocation {
 542  173 public StaticMethodInvocation(DJMethod method, Type returnType, Iterable<? extends Type> typeArgs,
 543    Iterable<? extends Expression> args, Iterable<? extends Type> thrown) {
 544  173 super(method, returnType, typeArgs, args, thrown);
 545    }
 546    }
 547   
 548   
 549    /** Abstraction of the result of a static or non-static field lookup */
 550    public static abstract class FieldReference {
 551    private final DJField _field;
 552    private final Type _type;
 553   
 554  432 protected FieldReference(DJField field, Type type) {
 555  432 _field = field;
 556  432 _type = type;
 557    }
 558   
 559    /** @return The reflection object corresponding to the accessed field */
 560  426 public DJField field() { return _field; }
 561   
 562    /** @return The return type of the access (before capture) */
 563  356 public Type type() { return _type; }
 564   
 565  0 public boolean equals(Object that) {
 566  0 if (this == that) { return true; }
 567  0 else if (!(that instanceof FieldReference)) { return false; }
 568    else {
 569  0 FieldReference r = (FieldReference) that;
 570  0 return _field.equals(r._field) && _type.equals(r._type);
 571    }
 572    }
 573   
 574  1728 public int hashCode() { return ObjectUtil.hash(FieldReference.class, _field, _type); }
 575   
 576    }
 577   
 578   
 579    /** The result of a non-static field lookup */
 580    public static class ObjectFieldReference extends FieldReference {
 581    private final Expression _object;
 582   
 583  177 public ObjectFieldReference(DJField field, Type type, Expression object) {
 584  177 super(field, type);
 585  177 _object = object;
 586    }
 587   
 588    /**
 589    * @return The object whose field is accessed, wrapped in any necessary promotions so that
 590    * the type is the type whose declared member is the matched field.
 591    */
 592  108 public Expression object() { return _object; }
 593    }
 594   
 595   
 596    /** The result of a static field lookup */
 597    public static class StaticFieldReference extends FieldReference {
 598  1 public StaticFieldReference(DJField field, Type type) {
 599  1 super(field, type);
 600    }
 601    }
 602   
 603    public static class TypeSystemException extends Exception {
 604    }
 605   
 606    public static class InvalidTypeArgumentException extends TypeSystemException {
 607    }
 608   
 609    public static class UnsupportedConversionException extends TypeSystemException {
 610    }
 611   
 612    public static class UnmatchedLookupException extends TypeSystemException {
 613    private final int _matches;
 614  17 public UnmatchedLookupException(int matches) { _matches = matches; }
 615  17 public int matches() { return _matches; }
 616    }
 617   
 618    /** A function lookup that failed because none of the given candidates matched the provided arguments. */
 619    public static class UnmatchedFunctionLookupException extends UnmatchedLookupException {
 620    private final Iterable<? extends Function> _candidates;
 621  17 public UnmatchedFunctionLookupException(Iterable<? extends Function> candidates) {
 622  17 super(0);
 623  17 _candidates = candidates;
 624    }
 625  17 public Iterable<? extends Function> candidates() { return _candidates; }
 626    }
 627   
 628    /** A function lookup that failed because all of the given candidates equally matched the provided arguments. */
 629    public static class AmbiguousFunctionLookupException extends UnmatchedLookupException {
 630    private final Iterable<? extends Function> _candidates;
 631  0 public AmbiguousFunctionLookupException(Iterable<? extends Function> candidates) {
 632  0 super(IterUtil.sizeOf(candidates));
 633  0 _candidates = candidates;
 634    }
 635  0 public Iterable<? extends Function> candidates() { return _candidates; }
 636    }
 637   
 638    }