/** * 5.1.10: Capture Conversion * * First, I wanted to store the upper and lower bound of fresh type variables * in the qualifier of TypeVar. However, these bounds can refer to the type * variables themselves, which can be recursive. To workaround this, the bounds * are now stored in dynamic rules. Unfortunately, the bounds are now not part * of the ATerm after serialization. Maybe there should be a representation * for declaring these fresh type variables. * * @author Martin Bravenboer */ module dryad/jls/conversions/CaptureConversion strategies /** * Applies capture conversion if necessary. * * @type Type -> Type */ capture-conversion = if must-be-capture-converted then apply-capture-conversion end must-be-capture-converted = where( (?ClassType(_, Some(TypeArgs(<id>))) + ?InterfaceType(_, Some(TypeArgs(<id>)))) ; fetch(?Wildcard(<id>)) ) strategies apply-capture-conversion : ClassType(tn, Some(TypeArgs(args))) -> ClassType(tn, Some(TypeArgs(capturedargs))) where <apply-capture-conversion-helper(|tn)> args => capturedargs apply-capture-conversion : InterfaceType(tn, Some(TypeArgs(args))) -> InterfaceType(tn, Some(TypeArgs(capturedargs))) where <apply-capture-conversion-helper(|tn)> args => capturedargs /** * @param TypeName * @type List(ActualTypeArg) -> List(ActualTypeArg) */ apply-capture-conversion-helper(|tn) = ?args ; <lookup-class> tn => class ; <get-formal-type-parameters> class => tparams ; <zip(try(capture-wildcard))> (tparams, args) ; where( map(?OpenWildcard(_, _, <id>)) => capturedargs ) ; where( map(capture-set-open-wildcard-bounds(|class, capturedargs)) ) ; !capturedargs rules capture-wildcard : (param, wild@Wildcard(_)) -> OpenWildcard(param, wild, TypeVar(Fresh(CapturedWildcard(wild)), Id(x))) where <newname> "WT" => x rules /** * @param Class Object * @param List(ActualTypeArgument) * @type OpenWildcard -> OpenWildcard */ capture-set-open-wildcard-bounds(|class, capturedargs) = ?OpenWildcard(param, Wildcard(None()), tv@TypeVar(Fresh(_), Id(x))) ; where( <get-upper-bound> param ; apply-type-substitution(|class, capturedargs) => upper-bound ; !Null() => lower-bound ; <capture-declare-bounds(|upper-bound, lower-bound)> tv ) /** * Utils to declare upper and lower bounds */ strategies capture-declare-bounds(|upper-bound, lower-bound) = capture-declare-upper-bound(|upper-bound) ; capture-declare-lower-bound(|lower-bound) capture-declare-upper-bound(|upper-bound) = ?TypeVar(Fresh(source), Id(x)) ; rules( /** * Returns the list of upperbounds of a fresh type variable. * * @todo Return list or intersection type? * @type TypeVar -> List(Type) */ FreshTypeVarUpperBound : TypeVar(Fresh(source), Id(x)) -> upper-bound ) capture-declare-lower-bound(|lower-bound) = ?TypeVar(Fresh(source), Id(x)) ; rules( FreshTypeVarLowerBound : TypeVar(Fresh(source), Id(x)) -> Null() ) signature constructors OpenWildcard : TypeParam * ActualTypeArg * ActualTypeArg -> ActualTypeArg