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    }