1 package polyglot.ext.jl.ast; 2 3 import java.util.Collections ; 4 import java.util.List ; 5 6 import polyglot.ast.AmbReceiver; 7 import polyglot.ast.Expr; 8 import polyglot.ast.Field; 9 import polyglot.ast.Node; 10 import polyglot.ast.Precedence; 11 import polyglot.ast.Receiver; 12 import polyglot.ast.Special; 13 import polyglot.ast.Term; 14 import polyglot.ast.TypeNode; 15 import polyglot.types.Context; 16 import polyglot.types.FieldInstance; 17 import polyglot.types.Flags; 18 import polyglot.types.SemanticException; 19 import polyglot.types.Type; 20 import polyglot.types.TypeSystem; 21 import polyglot.types.VarInstance; 22 import polyglot.util.CodeWriter; 23 import polyglot.util.InternalCompilerError; 24 import polyglot.util.Position; 25 import polyglot.visit.AscriptionVisitor; 26 import polyglot.visit.CFGBuilder; 27 import polyglot.visit.NodeVisitor; 28 import polyglot.visit.PrettyPrinter; 29 import polyglot.visit.TypeBuilder; 30 import polyglot.visit.TypeChecker; 31 32 38 public class Field_c extends Expr_c implements Field 39 { 40 protected Receiver target; 41 protected String name; 42 protected FieldInstance fi; 43 protected boolean targetImplicit; 44 45 public Field_c(Position pos, Receiver target, String name) { 46 super(pos); 47 this.target = target; 48 this.name = name; 49 this.targetImplicit = false; 50 51 if (target == null) { 52 throw new InternalCompilerError("Cannot create a field with a null " 53 + "target. Use AmbExpr or prefix " 54 + "with the appropriate type node or " 55 + "this."); 56 } 57 } 58 59 60 public Precedence precedence() { 61 return Precedence.LITERAL; 62 } 63 64 65 public Receiver target() { 66 return this.target; 67 } 68 69 70 public Field target(Receiver target) { 71 Field_c n = (Field_c) copy(); 72 n.target = target; 73 return n; 74 } 75 76 77 public String name() { 78 return this.name; 79 } 80 81 82 public Field name(String name) { 83 Field_c n = (Field_c) copy(); 84 n.name = name; 85 return n; 86 } 87 88 89 public Flags flags() { 90 return fi.flags(); 91 } 92 93 94 public FieldInstance fieldInstance() { 95 return fi; 96 } 97 98 99 public Field fieldInstance(FieldInstance fi) { 100 106 107 Field_c n = (Field_c) copy(); 108 n.fi = fi; 109 return n; 110 } 111 112 public boolean isTargetImplicit() { 113 return this.targetImplicit; 114 } 115 116 public Field targetImplicit(boolean implicit) { 117 Field_c n = (Field_c) copy(); 118 n.targetImplicit = implicit; 119 return n; 120 } 121 122 123 protected Field_c reconstruct(Receiver target) { 124 if (target != this.target) { 125 Field_c n = (Field_c) copy(); 126 n.target = target; 127 return n; 128 } 129 130 return this; 131 } 132 133 134 public Node visitChildren(NodeVisitor v) { 135 Receiver target = (Receiver) visitChild(this.target, v); 136 return reconstruct(target); 137 } 138 139 public Node buildTypes(TypeBuilder tb) throws SemanticException { 140 Field_c n = (Field_c) super.buildTypes(tb); 141 142 TypeSystem ts = tb.typeSystem(); 143 144 FieldInstance fi = ts.fieldInstance(position(), ts.Object(), Flags.NONE, 145 ts.unknownType(position()), name); 146 return n.fieldInstance(fi); 147 } 148 149 150 public Node typeCheck(TypeChecker tc) throws SemanticException { 151 Context c = tc.context(); 152 TypeSystem ts = tc.typeSystem(); 153 154 if (! target.type().isReference()) { 155 throw new SemanticException("Cannot access field \"" + name + 156 "\" " + (target instanceof Expr 157 ? "on an expression " 158 : "") + 159 "of non-reference type \"" + 160 target.type() + "\".", target.position()); 161 } 162 163 FieldInstance fi = ts.findField(target.type().toReference(), name, c.currentClass()); 164 165 if (fi == null) { 166 throw new InternalCompilerError("Cannot access field on node of type " + 167 target.getClass().getName() + "."); 168 } 169 170 Field_c f = (Field_c)fieldInstance(fi).type(fi.type()); 171 f.checkConsistency(c); 172 173 return f; 174 } 175 176 public Type childExpectedType(Expr child, AscriptionVisitor av) 177 { 178 if (child == target) { 179 return fi.container(); 180 } 181 182 return child.type(); 183 } 184 185 186 public void prettyPrint(CodeWriter w, PrettyPrinter tr) { 187 if (!targetImplicit) { 188 if (target instanceof Expr) { 190 printSubExpr((Expr) target, w, tr); 191 } 192 else if (target instanceof TypeNode || target instanceof AmbReceiver) { 193 print(target, w, tr); 194 } 195 196 w.write("."); 197 } 198 w.write(name); 199 } 200 201 public void dump(CodeWriter w) { 202 super.dump(w); 203 204 w.allowBreak(4, " "); 205 w.begin(0); 206 w.write("(name \"" + name + "\")"); 207 w.end(); 208 } 209 210 public Term entry() { 211 if (target instanceof Expr) { 212 return ((Expr) target).entry(); 213 } 214 return this; 215 } 216 217 public List acceptCFG(CFGBuilder v, List succs) { 218 if (target instanceof Expr) { 219 v.visitCFG((Expr) target, this); 220 } 221 return succs; 222 } 223 224 225 public String toString() { 226 return ((target != null && !targetImplicit)? target + "." : "") + name; 227 } 228 229 230 public List throwTypes(TypeSystem ts) { 231 if (target instanceof Expr && ! (target instanceof Special)) { 232 return Collections.singletonList(ts.NullPointerException()); 233 } 234 235 return Collections.EMPTY_LIST; 236 } 237 238 public boolean isConstant() { 239 if (fi != null && 240 (target instanceof TypeNode || 241 (target instanceof Special && targetImplicit))) { 242 return fi.isConstant(); 243 } 244 245 return false; 246 } 247 248 public Object constantValue() { 249 if (isConstant()) { 250 return fi.constantValue(); 251 } 252 253 return null; 254 } 255 256 protected void checkConsistency(Context c) { 258 if (targetImplicit) { 259 VarInstance vi = c.findVariableSilent(name); 260 if (vi instanceof FieldInstance) { 261 FieldInstance rfi = (FieldInstance) vi; 262 if (c.typeSystem().equals(rfi, fi)) { 263 return; 265 } 266 } 267 throw new InternalCompilerError("Field " + this + " has an " + 268 "implicit target, but the name " + name + " resolves to " + 269 vi + " instead of " + target, position()); 270 } 271 } 272 273 } 274 | Popular Tags |