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 }