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 }