001 /* 002 * The JastAdd Extensible Java Compiler (http://jastadd.org) is covered 003 * by the modified BSD License. You should have received a copy of the 004 * modified BSD license with this compiler. 005 * 006 * Copyright (c) 2005-2008, Torbjorn Ekman 007 * All rights reserved. 008 */ 009 010 import java.util.*; 011 012 aspect AccessTypes { 013 syn boolean Expr.isTypeAccess() = false; 014 eq TypeAccess.isTypeAccess() = true; 015 eq AbstractDot.isTypeAccess() = getRight().isTypeAccess(); 016 017 syn boolean Expr.isMethodAccess() = false; 018 eq AbstractDot.isMethodAccess() = getRight().isMethodAccess(); 019 eq MethodAccess.isMethodAccess() = true; 020 021 syn boolean Expr.isFieldAccess() = false; 022 eq AbstractDot.isFieldAccess() = getRight().isFieldAccess(); 023 syn lazy boolean VarAccess.isFieldAccess() = decl().isClassVariable() || decl().isInstanceVariable(); 024 025 syn boolean Expr.isSuperAccess() = false; 026 eq AbstractDot.isSuperAccess() = getRight().isSuperAccess(); 027 eq SuperAccess.isSuperAccess() = true; 028 eq ParExpr.isSuperAccess() = getExpr().isSuperAccess(); 029 eq CastExpr.isSuperAccess() = getExpr().isSuperAccess(); 030 031 syn boolean Expr.isThisAccess() = false; 032 eq AbstractDot.isThisAccess() = getRight().isThisAccess(); 033 eq ThisAccess.isThisAccess() = true; 034 eq ParExpr.isThisAccess() = getExpr().isThisAccess(); 035 eq CastExpr.isThisAccess() = getExpr().isThisAccess(); 036 037 syn boolean Expr.isPackageAccess() = false; 038 eq AbstractDot.isPackageAccess() = getRight().isPackageAccess(); 039 eq PackageAccess.isPackageAccess() = true; 040 041 syn boolean Expr.isArrayAccess() = false; 042 eq AbstractDot.isArrayAccess() = getRight().isArrayAccess(); 043 eq ArrayAccess.isArrayAccess() = true; 044 045 syn boolean Expr.isClassAccess() = false; 046 eq AbstractDot.isClassAccess() = getRight().isClassAccess(); 047 eq ClassAccess.isClassAccess() = true; 048 049 syn boolean Expr.isSuperConstructorAccess() = false; 050 eq AbstractDot.isSuperConstructorAccess() = getRight().isSuperConstructorAccess(); 051 eq SuperConstructorAccess.isSuperConstructorAccess() = true; 052 } 053 054 aspect QualifiedNames { 055 syn boolean Expr.isLeftChildOfDot() = hasParentDot() && parentDot().getLeft() == this; 056 syn boolean Expr.isRightChildOfDot() = hasParentDot() && parentDot().getRight() == this; 057 058 syn boolean Access.isQualified() = hasPrevExpr(); 059 eq AbstractDot.isQualified() = hasParentDot(); 060 061 syn Expr Access.qualifier() = prevExpr(); 062 063 syn Expr AbstractDot.leftSide() = getLeft(); 064 syn Access AbstractDot.rightSide() = getRight/*NoTransform*/() instanceof AbstractDot ? (Access)((AbstractDot)getRight/*NoTransform*/()).getLeft() : (Access)getRight(); 065 066 syn Access Access.lastAccess() = this; 067 eq AbstractDot.lastAccess() = getRight().lastAccess(); 068 069 syn AbstractDot Expr.parentDot() = getParent() instanceof AbstractDot ? (AbstractDot)getParent() : null; 070 syn boolean Expr.hasParentDot() = parentDot() != null; 071 072 syn Access Expr.nextAccess() = parentDot().nextAccess(); 073 syn boolean Expr.hasNextAccess() = isLeftChildOfDot(); 074 075 syn Access AbstractDot.nextAccess() = rightSide(); 076 077 syn Expr AbstractDot.prevExpr() = leftSide(); 078 syn lazy Expr Access.prevExpr() { 079 if(isLeftChildOfDot()) { 080 if(parentDot().isRightChildOfDot()) 081 return parentDot().parentDot().leftSide(); 082 } 083 else if(isRightChildOfDot()) 084 return parentDot().leftSide(); 085 throw new Error(this + " does not have a previous expression"); 086 } 087 088 syn boolean AbstractDot.hasPrevExpr() = true; 089 syn lazy boolean Access.hasPrevExpr() { 090 if(isLeftChildOfDot()) { 091 if(parentDot().isRightChildOfDot()) 092 return true; 093 } 094 else if(isRightChildOfDot()) 095 return true; 096 return false; 097 } 098 099 public Dot Dot.lastDot() { 100 Dot node = this; 101 while(node.getRightNoTransform() instanceof Dot) 102 node = (Dot)node.getRightNoTransform(); 103 return node; 104 } 105 106 public Dot Expr.qualifiesAccess(Access access) { 107 Dot dot = new Dot(this, access); 108 dot.setStart(this.getStart()); 109 dot.setEnd(access.getEnd()); 110 return dot; 111 } 112 113 public Dot Dot.qualifiesAccess(Access access) { 114 Dot lastDot = lastDot(); 115 Expr l = lastDot.getRightNoTransform(); 116 Dot dot = new Dot(lastDot.getRightNoTransform(), access); 117 dot.setStart(l.getStart()); 118 dot.setEnd(access.getEnd()); 119 lastDot.setRight(dot); 120 return this; 121 } 122 123 // Used when replacing pairs from a list to concatenate the result to the tail of the current location. 124 private Access Dot.qualifyTailWith(Access expr) { 125 if(getRight/*NoTransform*/() instanceof AbstractDot) { 126 AbstractDot dot = (AbstractDot)getRight/*NoTransform*/(); 127 return expr.qualifiesAccess(dot.getRight/*NoTransform*/()); 128 } 129 return expr; 130 } 131 132 133 // These are used by the parser to extract the last name which 134 // will be replaced by a method name 135 public Access AbstractDot.extractLast() { 136 return getRightNoTransform(); 137 } 138 public void AbstractDot.replaceLast(Access access) { 139 setRight(access); 140 } 141 public Access Dot.extractLast() { 142 return lastDot().getRightNoTransform(); 143 } 144 public void Dot.replaceLast(Access access) { 145 lastDot().setRight(access); 146 } 147 148 public Access Access.addArrayDims(List list) { 149 Access a = this; 150 for(int i = 0; i < list.getNumChildNoTransform(); i++) { 151 Dims dims = (Dims)list.getChildNoTransform(i); 152 Opt opt = dims.getExprOpt(); 153 if(opt.getNumChildNoTransform() == 1) 154 a = new ArrayTypeWithSizeAccess(a, (Expr)opt.getChildNoTransform(0)); 155 else 156 a = new ArrayTypeAccess(a); 157 a.setStart(dims.start()); 158 a.setEnd(dims.end()); 159 } 160 return a; 161 } 162 163 } 164 165 aspect NameResolution { 166 167 // Resolve Package or Type name 168 rewrite PackageOrTypeAccess { 169 /* 170 when(!lookupType(name()).isEmpty()) 171 to Access new TypeAccess(name()); 172 when(hasPackage(name())) 173 to Access new PackageAccess(name()); 174 */ 175 when(!duringSyntacticClassification()) 176 to Access{ 177 if(!lookupType(name()).isEmpty()) 178 return new TypeAccess(name(), start(), end()); 179 else 180 return new PackageAccess(name(), start(), end()); 181 } 182 } 183 184 // Resolve Ambiguous name 185 rewrite AmbiguousAccess { 186 /* 187 when(!lookupVariable(name()).isEmpty()) 188 to Access new VarAccess(name()); 189 when(!lookupType(name()).isEmpty()) 190 to Access new TypeAccess(name()); 191 when(hasPackage(name())) 192 to Access new PackageAccess(name()); 193 */ 194 when(!duringSyntacticClassification()) 195 to Access { 196 if(!lookupVariable(name()).isEmpty()) { 197 return new VarAccess(name(), start(), end()); 198 } 199 else if(!lookupType(name()).isEmpty()) { 200 return new TypeAccess(name(), start(), end()); 201 } 202 else { 203 return new PackageAccess(name(), start(), end()); 204 } 205 } 206 } 207 208 // combine two package access into one node 209 rewrite Dot { 210 when(!duringSyntacticClassification() && leftSide().isPackageAccess() && rightSide().isPackageAccess()) 211 to Access { 212 PackageAccess left = (PackageAccess)leftSide(); 213 PackageAccess right = (PackageAccess)rightSide(); 214 left.setPackage(left.getPackage() + "." + right.getPackage()); 215 left.setEnd(right.end()); 216 return qualifyTailWith(left); 217 } 218 } 219 220 // combine PackageAccess + TypeAccess into one qualified TypeAccess 221 rewrite Dot { 222 when(!duringSyntacticClassification() && leftSide().isPackageAccess() && !((Access)leftSide()).hasPrevExpr() && rightSide() instanceof TypeAccess) 223 to Access { 224 PackageAccess left = (PackageAccess)leftSide(); 225 TypeAccess right = (TypeAccess)rightSide(); 226 right.setPackage(left.getPackage()); 227 right.setStart(left.start()); 228 return qualifyTailWith(right); 229 } 230 } 231 }