    001    /* Copyright 2000, 2001, Compaq Computer Corporation */
    002
    003    package escjava.translate;
    004
    005    import javafe.ast.*;
    006    import escjava.ast.SimpleModifierPragma;
    007    import escjava.ast.TagConstants;
    008
    009    import javafe.tc.TypeSig;
    010    import javafe.util.*;
    011
    012    /**
    013     * * This class contains a number of routines used in the * interpretation of
    014     * Java 1.1 as Java 1.0. *
    015     */
    016
    017    public class Inner {
    018
    019      /*****************************************************************************
    020       * * Getting the enclosing instance field (this$0): * *
    021       ****************************************************************************/
    022
    023      /**
    024       * * Decorates TypeSig nodes to point to their enclosing instance * field
    025       * (this$0).
    026       * <p>
    027       */
    028      //@ invariant enclosingInstanceDecoration.decorationType == \type(FieldDecl);
    029      //@ spec_public
    030      private static final ASTDecoration enclosingInstanceDecoration = new ASTDecoration(
    031          "enclosingInstanceDecoration");
    032
    033      /**
    034       * * Return the FieldDecl for a given non-top-level TypeSig's * enclosing
    035       * instance field (this$0).
    036       * <p>* * The resulting field is public, final, and non_null.
    037       * <p>
    038       */
    039      //@ ensures \result != null;
    040      public static FieldDecl getEnclosingInstanceField(TypeSig T) {
    041        // Memorize our result:
    042        FieldDecl result = (FieldDecl)enclosingInstanceDecoration.get(T);
    043        if (result != null) return result;
    044
    045        Assert.notFalse(!T.isTopLevelType(), T.toString());
    046
    047        int loc = T.getTypeDecl().getStartLoc();
    048        // String name = "this$of$" + T.simpleName; // for debugging use...
    049        String name = "this$0";
    050
    051        ModifierPragmaVec pmodifiers = ModifierPragmaVec.make(1);
    052        pmodifiers
    053            .addElement(SimpleModifierPragma.make(TagConstants.NON_NULL, loc));
    054
    055        result = FieldDecl.make(Modifiers.ACC_PUBLIC | Modifiers.ACC_FINAL,
    056            pmodifiers, Identifier.intern(name), T.enclosingType, // the Type of the
    057                                                                  // decl...
    058            loc, null, Location.NULL); // has no initializer
    059        result.parent = T.getTypeDecl(); // breaks invariant.... !!!!
    060
    061        enclosingInstanceDecoration.set(T, result);
    062        return result;
    063      }
    064
    065      /*****************************************************************************
    066       * * Getting the enclosing-instance-field argument (this$0arg): * *
    067       ****************************************************************************/
    068
    069      /**
    070       * * Decorates ConstructorDecl nodes to point to their enclosing-instance- *
    071       * field argument (this$0arg).
    072       * <p>
    073       */
    074      /*
    075       * @ invariant enclosingInstanceArgument.decorationType ==
    076       * \type(FormalParaDecl);
    077       */
    078      //@ spec_public
    079      private static final ASTDecoration enclosingInstanceArgument = new ASTDecoration(
    080          "enclosingInstanceArgument");
    081
    082      /**
    083       * * Return the FormalParaDecl for a given inner-class constructor's *
    084       * enclosing-instance-field argument (this$0arg).
    085       * <p>* * The resulting argument is non_null.
    086       * <p>* * WARNING: Translate.call depends on the exact name of * this$0arg.
    087       * If you change this$0arg's name, you must change * Translate.call
    088       * accordingly.
    089       * <p>
    090       */
    091      //@ ensures \result != null;
    092      public static FormalParaDecl getEnclosingInstanceArg(ConstructorDecl cd) {
    093        // Memorize our result:
    094        FormalParaDecl result = (FormalParaDecl)enclosingInstanceArgument.get(cd);
    095        if (result != null) return result;
    096
    097        TypeSig T = TypeSig.getSig(cd.parent);
    098        Assert.notFalse(!T.isTopLevelType(), T.toString());
    099
    100        String name = "this$0arg";
    101        ModifierPragmaVec pmodifiers = ModifierPragmaVec.make(1);
    102        pmodifiers.addElement(SimpleModifierPragma.make(TagConstants.NON_NULL,
    103            cd.locId));
    104
    105        result = FormalParaDecl.make(Modifiers.NONE, pmodifiers, Identifier
    106            .intern(name), T.enclosingType, //the Type of the argument...
    107            cd.locId);
    108
    109        enclosingInstanceArgument.set(cd, result);
    110        return result;
    111      }
    112
    113      /*****************************************************************************
    114       * * Unfolding <class>.this Exprs: * *
    115       ****************************************************************************/
    116
    117      /**
    118       * * If non-null, the local variable or formal to use instead of * this.this$0
    119       * when unfolding <class>.this's.
    120       */
    121      static GenericVarDecl firstThis0 = null;
    122
    123      /**
    124       * * Converts a 1.1 ThisExpr of the form <class>.this into an Java * 1.0
    125       * expression of the form this.this$0.this$0.this$0...
    126       * <p>* * The type of this is taken from GC.thisvar.decl.type.
    127       * <p>* * The this$0 fields are the appropriate fields from the *
    128       * getEnclosingInstanceField(-) routine above.
    129       * <p>* * The resulting Expr has already been "prepped", but *not* type *
    130       * checked.
    131       * <p>* * * Exception: If firstThis0 is non-null, then it is used instead *
    132       * of this.this$0 at the start.
    133       * <p>
    134       */
    135      //@ requires t.classPrefix != null;
    136      static Expr unfoldThis(/* @non_null */ThisExpr t) {
    137        TypeSig target = javafe.tc.Types.toClassTypeSig(t.classPrefix);
    138
    139        Expr result = ThisExpr.make(null, t.loc);
    140        TypeSig thisType = (TypeSig)GC.thisvar.decl.type;
    141
    142        for (int level = 0; thisType != target; level++) {
    143          /*
    144           * add a .this$0 to result, using firstThis0 the first time if non-null:
    145           */
    146          if (level == 0 && firstThis0 != null)
    147            result = TrAnExpr.makeVarAccess(firstThis0, t.loc);
    148          else {
    149            FieldDecl thisDollar = getEnclosingInstanceField(thisType);
    150            result = FieldAccess.make(ExprObjectDesignator.make(t.loc, result),
    151                thisDollar.id, t.loc);
    152            ((FieldAccess)result).decl = thisDollar;
    153          }
    154
    155          thisType = thisType.enclosingType;
    156          Assert.notNull(thisType);
    157        }
    158
    159        return result;
    160      }
    161    }