Produced by Araxis Merge on 9/25/2018 2:13:07 PM Central Daylight Time. See www.araxis.com for information about Merge. This report uses XHTML and CSS2, and is best viewed with a modern standards-compliant browser. For optimum results when printing this report, use landscape orientation and enable printing of background images and colours in your browser.
# | Location | File | Last Modified |
---|---|---|---|
1 | build 3.zip\build 3\MHLTH_YS_137_Source\JavaScript\resources\javaJDF-1.8.0\src\com\sun\tools\javac\comp | Lower.java | Mon Jan 22 14:47:06 2018 UTC |
2 | build 3.zip\build 3\MHLTH_YS_137_Source\JavaScript\resources\javaJDF-1.8.0\src\com\sun\tools\javac\comp | Lower.java | Wed Sep 12 16:49:37 2018 UTC |
Description | Between Files 1 and 2 |
|
---|---|---|
Text Blocks | Lines | |
Unchanged | 2 | 7928 |
Changed | 1 | 2 |
Inserted | 0 | 0 |
Removed | 0 | 0 |
Whitespace | |
---|---|
Character case | Differences in character case are significant |
Line endings | Differences in line endings (CR and LF characters) are ignored |
CR/LF characters | Not shown in the comparison detail |
No regular expressions were active.
1 | /* | |
2 | * Copyrig ht (c) 199 9, 2014, O racle and/ or its aff iliates. A ll rights reserved. | |
3 | * DO NOT ALTER OR R EMOVE COPY RIGHT NOTI CES OR THI S FILE HEA DER. | |
4 | * | |
5 | * This co de is free software; you can r edistribut e it and/o r modify i t | |
6 | * under t he terms o f the GNU General Pu blic Licen se version 2 only, a s | |
7 | * publish ed by the Free Softw are Founda tion. Ora cle design ates this | |
8 | * particu lar file a s subject to the "Cl asspath" e xception a s provided | |
9 | * by Orac le in the LICENSE fi le that ac companied this code. | |
10 | * | |
11 | * This co de is dist ributed in the hope that it wi ll be usef ul, but WI THOUT | |
12 | * ANY WAR RANTY; wit hout even the implie d warranty of MERCHA NTABILITY or | |
13 | * FITNESS FOR A PAR TICULAR PU RPOSE. Se e the GNU General Pu blic Licen se | |
14 | * version 2 for mor e details (a copy is included in the LIC ENSE file that | |
15 | * accompa nied this code). | |
16 | * | |
17 | * You sho uld have r eceived a copy of th e GNU Gene ral Public License v ersion | |
18 | * 2 along with this work; if not, write to the Fr ee Softwar e Foundati on, | |
19 | * Inc., 5 1 Franklin St, Fifth Floor, Bo ston, MA 0 2110-1301 USA. | |
20 | * | |
21 | * Please contact Or acle, 500 Oracle Par kway, Redw ood Shores , CA 94065 USA | |
22 | * or visi t www.orac le.com if you need a dditional informatio n or have any | |
23 | * questio ns. | |
24 | */ | |
25 | ||
26 | package co m.sun.tool s.javac.co mp; | |
27 | ||
28 | import jav a.util.*; | |
29 | ||
30 | import com .sun.tools .javac.cod e.*; | |
31 | import com .sun.tools .javac.cod e.Type.Ann otatedType ; | |
32 | import com .sun.tools .javac.jvm .*; | |
33 | import com .sun.tools .javac.mai n.Option.P kgInfo; | |
34 | import com .sun.tools .javac.tre e.*; | |
35 | import com .sun.tools .javac.uti l.*; | |
36 | import com .sun.tools .javac.uti l.JCDiagno stic.Diagn osticPosit ion; | |
37 | import com .sun.tools .javac.uti l.List; | |
38 | ||
39 | import com .sun.tools .javac.cod e.Symbol.* ; | |
40 | import com .sun.tools .javac.tre e.JCTree.* ; | |
41 | import com .sun.tools .javac.cod e.Type.*; | |
42 | ||
43 | import com .sun.tools .javac.jvm .Target; | |
44 | import com .sun.tools .javac.tre e.EndPosTa ble; | |
45 | ||
46 | import sta tic com.su n.tools.ja vac.code.F lags.*; | |
47 | import sta tic com.su n.tools.ja vac.code.F lags.BLOCK ; | |
48 | import sta tic com.su n.tools.ja vac.code.K inds.*; | |
49 | import sta tic com.su n.tools.ja vac.code.T ypeTag.*; | |
50 | import sta tic com.su n.tools.ja vac.jvm.By teCodes.*; | |
51 | import sta tic com.su n.tools.ja vac.tree.J CTree.Tag. *; | |
52 | ||
53 | /** This p ass transl ates away some synta ctic sugar : inner cl asses, | |
54 | * class literals, assertions , foreach loops, etc . | |
55 | * | |
56 | * <p><b> This is NO T part of any suppor ted API. | |
57 | * If you write cod e that dep ends on th is, you do so at you r own risk . | |
58 | * This c ode and it s internal interface s are subj ect to cha nge or | |
59 | * deleti on without notice.</ b> | |
60 | */ | |
61 | public cla ss Lower e xtends Tre eTranslato r { | |
62 | protec ted static final Con text.Key<L ower> lowe rKey = | |
63 | ne w Context. Key<Lower> (); | |
64 | ||
65 | public static Lo wer instan ce(Context context) { | |
66 | Lo wer instan ce = conte xt.get(low erKey); | |
67 | if (instance == null) | |
68 | instance = new Low er(context ); | |
69 | re turn insta nce; | |
70 | } | |
71 | ||
72 | privat e Names na mes; | |
73 | privat e Log log; | |
74 | privat e Symtab s yms; | |
75 | privat e Resolve rs; | |
76 | privat e Check ch k; | |
77 | privat e Attr att r; | |
78 | privat e TreeMake r make; | |
79 | privat e Diagnost icPosition make_pos; | |
80 | privat e ClassWri ter writer ; | |
81 | privat e ClassRea der reader ; | |
82 | privat e ConstFol d cfolder; | |
83 | privat e Target t arget; | |
84 | privat e Source s ource; | |
85 | privat e final Ty peEnvs typ eEnvs; | |
86 | privat e boolean allowEnums ; | |
87 | privat e final Na me dollarA ssertionsD isabled; | |
88 | privat e final Na me classDo llar; | |
89 | privat e Types ty pes; | |
90 | privat e boolean debugLower ; | |
91 | privat e PkgInfo pkginfoOpt ; | |
92 | ||
93 | protec ted Lower( Context co ntext) { | |
94 | co ntext.put( lowerKey, this); | |
95 | na mes = Name s.instance (context); | |
96 | lo g = Log.in stance(con text); | |
97 | sy ms = Symta b.instance (context); | |
98 | rs = Resolve .instance( context); | |
99 | ch k = Check. instance(c ontext); | |
100 | at tr = Attr. instance(c ontext); | |
101 | ma ke = TreeM aker.insta nce(contex t); | |
102 | wr iter = Cla ssWriter.i nstance(co ntext); | |
103 | re ader = Cla ssReader.i nstance(co ntext); | |
104 | cf older = Co nstFold.in stance(con text); | |
105 | ta rget = Tar get.instan ce(context ); | |
106 | so urce = Sou rce.instan ce(context ); | |
107 | ty peEnvs = T ypeEnvs.in stance(con text); | |
108 | al lowEnums = source.al lowEnums() ; | |
109 | do llarAssert ionsDisabl ed = names . | |
110 | fromStri ng(target. syntheticN ameChar() + "asserti onsDisable d"); | |
111 | cl assDollar = names. | |
112 | fromStri ng("class" + target. syntheticN ameChar()) ; | |
113 | ||
114 | ty pes = Type s.instance (context); | |
115 | Op tions opti ons = Opti ons.instan ce(context ); | |
116 | de bugLower = options.i sSet("debu glower"); | |
117 | pk ginfoOpt = PkgInfo.g et(options ); | |
118 | } | |
119 | ||
120 | /** Th e currentl y enclosin g class. | |
121 | */ | |
122 | ClassS ymbol curr entClass; | |
123 | ||
124 | /** A queue of a ll transla ted classe s. | |
125 | */ | |
126 | ListBu ffer<JCTre e> transla ted; | |
127 | ||
128 | /** En vironment for symbol lookup, s et by tran slateTopLe velClass. | |
129 | */ | |
130 | Env<At trContext> attrEnv; | |
131 | ||
132 | /** A hash table mapping s yntax tree s to their ending so urce posit ions. | |
133 | */ | |
134 | EndPos Table endP osTable; | |
135 | ||
136 | /********* ********** ********** ********** ********** ********** ********** ***** | |
137 | * Global mappings | |
138 | ********* ********** ********** ********** ********** ********** ********** ****/ | |
139 | ||
140 | /** A hash table mapping l ocal class es to thei r definiti ons. | |
141 | */ | |
142 | Map<Cl assSymbol, JCClassDe cl> classd efs; | |
143 | ||
144 | /** A hash table mapping l ocal class es to a li st of prun ed trees. | |
145 | */ | |
146 | public Map<Class Symbol, Li st<JCTree> > prunedTr ee = new W eakHashMap <ClassSymb ol, List<J CTree>>(); | |
147 | ||
148 | /** A hash table mapping v irtual acc essed symb ols in out er subclas ses | |
149 | * to the actua lly referr ed symbol in supercl asses. | |
150 | */ | |
151 | Map<Sy mbol,Symbo l> actualS ymbols; | |
152 | ||
153 | /** Th e current method def inition. | |
154 | */ | |
155 | JCMeth odDecl cur rentMethod Def; | |
156 | ||
157 | /** Th e current method sym bol. | |
158 | */ | |
159 | Method Symbol cur rentMethod Sym; | |
160 | ||
161 | /** Th e currentl y enclosin g outermos t class de finition. | |
162 | */ | |
163 | JCClas sDecl oute rmostClass Def; | |
164 | ||
165 | /** Th e currentl y enclosin g outermos t member d efinition. | |
166 | */ | |
167 | JCTree outermost MemberDef; | |
168 | ||
169 | /** A map from l ocal varia ble symbol s to their translati on (as per LambdaToM ethod). | |
170 | * Thi s is requi red when a capturing local cla ss is crea ted from a lambda (i n which | |
171 | * cas e the capt ured symbo ls should be replace d with the translate d lambda s ymbols). | |
172 | */ | |
173 | Map<Sy mbol, Symb ol> lambda Translatio nMap = nul l; | |
174 | ||
175 | /** A navigator class for assembling a mapping from loca l class sy mbols | |
176 | * to class def inition tr ees. | |
177 | * Th ere is onl y one case ; all othe r cases si mply trave rse down t he tree. | |
178 | */ | |
179 | class ClassMap e xtends Tre eScanner { | |
180 | ||
181 | /* * All enco untered cl ass defs a re entered into clas sdefs tabl e. | |
182 | * / | |
183 | pu blic void visitClass Def(JCClas sDecl tree ) { | |
184 | classdef s.put(tree .sym, tree ); | |
185 | super.vi sitClassDe f(tree); | |
186 | } | |
187 | } | |
188 | ClassM ap classMa p = new Cl assMap(); | |
189 | ||
190 | /** Ma p a class symbol to its defini tion. | |
191 | * @p aram c The class symbol of which we w ant to det ermine the definitio n. | |
192 | */ | |
193 | JCClas sDecl clas sDef(Class Symbol c) { | |
194 | // First loo kup the cl ass in the classdefs table. | |
195 | JC ClassDecl def = clas sdefs.get( c); | |
196 | if (def == n ull && out ermostMemb erDef != n ull) { | |
197 | // If th is fails, traverse o utermost m ember defi nition, en tering all | |
198 | // local classes i nto classd efs, and t ry again. | |
199 | classMap .scan(oute rmostMembe rDef); | |
200 | def = cl assdefs.ge t(c); | |
201 | } | |
202 | if (def == n ull) { | |
203 | // If th is fails, traverse o utermost c lass defin ition, ent ering all | |
204 | // local classes i nto classd efs, and t ry again. | |
205 | classMap .scan(oute rmostClass Def); | |
206 | def = cl assdefs.ge t(c); | |
207 | } | |
208 | re turn def; | |
209 | } | |
210 | ||
211 | /** A hash table mapping c lass symbo ls to list s of free variables. | |
212 | * ac cessed by them. Only free vari ables of t he method immediatel y containi ng | |
213 | * a class are associated with that class. | |
214 | */ | |
215 | Map<Cl assSymbol, List<VarSy mbol>> fre evarCache; | |
216 | ||
217 | /** A navigator class for collecting the free variables accessed | |
218 | * fr om a local class. Th ere is onl y one case ; all othe r cases si mply | |
219 | * tr averse dow n the tree . This cla ss doesn't deal with the speci fic | |
220 | * of Lower - i t's an abs tract visi tor that i s meant to be reused in | |
221 | * or der to sha re the loc al variabl e capture logic. | |
222 | */ | |
223 | abstra ct class B asicFreeVa rCollector extends T reeScanner { | |
224 | ||
225 | /* * Add all free varia bles of cl ass c to f vs list | |
226 | * unless t hey are al ready ther e. | |
227 | * / | |
228 | ab stract voi d addFreeV ars(ClassS ymbol c); | |
229 | ||
230 | /* * If tree refers to a variable in owner of local c lass, add it to | |
231 | * free var iables lis t. | |
232 | * / | |
233 | pu blic void visitIdent (JCIdent t ree) { | |
234 | visitSym bol(tree.s ym); | |
235 | } | |
236 | // where | |
237 | ab stract voi d visitSym bol(Symbol _sym); | |
238 | ||
239 | /* * If tree refers to a class in stance cre ation expr ession | |
240 | * add all free varia bles of th e freshly created cl ass. | |
241 | * / | |
242 | pu blic void visitNewCl ass(JCNewC lass tree) { | |
243 | ClassSym bol c = (C lassSymbol )tree.cons tructor.ow ner; | |
244 | addFreeV ars(c); | |
245 | super.vi sitNewClas s(tree); | |
246 | } | |
247 | ||
248 | /* * If tree refers to a supercla ss constru ctor call, | |
249 | * add all free varia bles of th e supercla ss. | |
250 | * / | |
251 | pu blic void visitApply (JCMethodI nvocation tree) { | |
252 | if (Tree Info.name( tree.meth) == names. _super) { | |
253 | addF reeVars((C lassSymbol ) TreeInfo .symbol(tr ee.meth).o wner); | |
254 | } | |
255 | super.vi sitApply(t ree); | |
256 | } | |
257 | } | |
258 | ||
259 | /** | |
260 | * Low er-specifi c subclass of {@code BasicFree VarCollect or}. | |
261 | */ | |
262 | class FreeVarCol lector ext ends Basic FreeVarCol lector { | |
263 | ||
264 | /* * The owne r of the l ocal class . | |
265 | * / | |
266 | Sy mbol owner ; | |
267 | ||
268 | /* * The loca l class. | |
269 | * / | |
270 | Cl assSymbol clazz; | |
271 | ||
272 | /* * The list of owner' s variable s accessed from with in the loc al class, | |
273 | * without any duplic ates. | |
274 | * / | |
275 | Li st<VarSymb ol> fvs; | |
276 | ||
277 | Fr eeVarColle ctor(Class Symbol cla zz) { | |
278 | this.cla zz = clazz ; | |
279 | this.own er = clazz .owner; | |
280 | this.fvs = List.ni l(); | |
281 | } | |
282 | ||
283 | /* * Add free variable to fvs lis t unless i t is alrea dy there. | |
284 | * / | |
285 | pr ivate void addFreeVa r(VarSymbo l v) { | |
286 | for (Lis t<VarSymbo l> l = fvs ; l.nonEmp ty(); l = l.tail) | |
287 | if ( l.head == v) return; | |
288 | fvs = fv s.prepend( v); | |
289 | } | |
290 | ||
291 | @O verride | |
292 | vo id addFree Vars(Class Symbol c) { | |
293 | List<Var Symbol> fv s = freeva rCache.get (c); | |
294 | if (fvs != null) { | |
295 | for (List<VarS ymbol> l = fvs; l.no nEmpty(); l = l.tail ) { | |
296 | addFreeVar (l.head); | |
297 | } | |
298 | } | |
299 | } | |
300 | ||
301 | @O verride | |
302 | vo id visitSy mbol(Symbo l _sym) { | |
303 | Symbol s ym = _sym; | |
304 | if (sym. kind == VA R || sym.k ind == MTH ) { | |
305 | whil e (sym != null && sy m.owner != owner) | |
306 | sym = prox ies.lookup (proxyName (sym.name) ).sym; | |
307 | if ( sym != nul l && sym.o wner == ow ner) { | |
308 | VarSymbol v = (VarSy mbol)sym; | |
309 | if (v.getC onstValue( ) == null) { | |
310 | addFre eVar(v); | |
311 | } | |
312 | } el se { | |
313 | if (outerT hisStack.h ead != nul l && | |
314 | outerT hisStack.h ead != _sy m) | |
315 | visitS ymbol(oute rThisStack .head); | |
316 | } | |
317 | } | |
318 | } | |
319 | ||
320 | /* * If tree refers to a class in stance cre ation expr ession | |
321 | * add all free varia bles of th e freshly created cl ass. | |
322 | * / | |
323 | pu blic void visitNewCl ass(JCNewC lass tree) { | |
324 | ClassSym bol c = (C lassSymbol )tree.cons tructor.ow ner; | |
325 | if (tree .encl == n ull && | |
326 | c.ha sOuterInst ance() && | |
327 | oute rThisStack .head != n ull) | |
328 | visi tSymbol(ou terThisSta ck.head); | |
329 | super.vi sitNewClas s(tree); | |
330 | } | |
331 | ||
332 | /* * If tree refers to a qualifie d this or super expr ession | |
333 | * for anyt hing but t he current class, ad d the oute r this | |
334 | * stack as a free va riable. | |
335 | * / | |
336 | pu blic void visitSelec t(JCFieldA ccess tree ) { | |
337 | if ((tre e.name == names._thi s || tree. name == na mes._super ) && | |
338 | tree .selected. type.tsym != clazz & & | |
339 | oute rThisStack .head != n ull) | |
340 | visi tSymbol(ou terThisSta ck.head); | |
341 | super.vi sitSelect( tree); | |
342 | } | |
343 | ||
344 | /* * If tree refers to a supercla ss constru ctor call, | |
345 | * add all free varia bles of th e supercla ss. | |
346 | * / | |
347 | pu blic void visitApply (JCMethodI nvocation tree) { | |
348 | if (Tree Info.name( tree.meth) == names. _super) { | |
349 | Symb ol constru ctor = Tre eInfo.symb ol(tree.me th); | |
350 | Clas sSymbol c = (ClassSy mbol)const ructor.own er; | |
351 | if ( c.hasOuter Instance() && | |
352 | !tree.meth .hasTag(SE LECT) && | |
353 | outerThisS tack.head != null) | |
354 | visitSymbo l(outerThi sStack.hea d); | |
355 | } | |
356 | super.vi sitApply(t ree); | |
357 | } | |
358 | } | |
359 | ||
360 | ClassS ymbol owne rToCopyFre eVarsFrom( ClassSymbo l c) { | |
361 | if (!c.isLoc al()) { | |
362 | return n ull; | |
363 | } | |
364 | Sy mbol curre ntOwner = c.owner; | |
365 | wh ile ((curr entOwner.o wner.kind & TYP) != 0 && curre ntOwner.is Local()) { | |
366 | currentO wner = cur rentOwner. owner; | |
367 | } | |
368 | if ((current Owner.owne r.kind & ( VAR | MTH) ) != 0 && c.isSubCla ss(current Owner, typ es)) { | |
369 | return ( ClassSymbo l)currentO wner; | |
370 | } | |
371 | re turn null; | |
372 | } | |
373 | ||
374 | /** Re turn the v ariables a ccessed fr om within a local cl ass, which | |
375 | * ar e declared in the lo cal class' owner. | |
376 | * (i n reverse order of f irst acces s). | |
377 | */ | |
378 | List<V arSymbol> freevars(C lassSymbol c) { | |
379 | Li st<VarSymb ol> fvs = freevarCac he.get(c); | |
380 | if (fvs != n ull) { | |
381 | return f vs; | |
382 | } | |
383 | if ((c.owner .kind & (V AR | MTH)) != 0) { | |
384 | FreeVarC ollector c ollector = new FreeV arCollecto r(c); | |
385 | collecto r.scan(cla ssDef(c)); | |
386 | fvs = co llector.fv s; | |
387 | freevarC ache.put(c , fvs); | |
388 | return f vs; | |
389 | } else { | |
390 | ClassSym bol owner = ownerToC opyFreeVar sFrom(c); | |
391 | if (owne r != null) { | |
392 | fvs = freevarC ache.get(o wner); | |
393 | free varCache.p ut(c, fvs) ; | |
394 | retu rn fvs; | |
395 | } else { | |
396 | retu rn List.ni l(); | |
397 | } | |
398 | } | |
399 | } | |
400 | ||
401 | Map<Ty peSymbol,E numMapping > enumSwit chMap = ne w LinkedHa shMap<Type Symbol,Enu mMapping>( ); | |
402 | ||
403 | EnumMa pping mapF orEnum(Dia gnosticPos ition pos, TypeSymbo l enumClas s) { | |
404 | En umMapping map = enum SwitchMap. get(enumCl ass); | |
405 | if (map == n ull) | |
406 | enumSwit chMap.put( enumClass, map = new EnumMappi ng(pos, en umClass)); | |
407 | re turn map; | |
408 | } | |
409 | ||
410 | /** Th is map giv es a trans lation tab le to be u sed for en um | |
411 | * sw itches. | |
412 | * | |
413 | * <p >For each enum that appears as the type of a switc h | |
414 | * ex pression, we maintai n an EnumM apping to assist in the | |
415 | * tr anslation, as exempl ified by t he followi ng example : | |
416 | * | |
417 | * <p >we transl ate | |
418 | * <p re> | |
419 | * swit ch(colorEx pression) { | |
420 | * case red: stmt 1; | |
421 | * case green: st mt2; | |
422 | * } | |
423 | * </ pre> | |
424 | * in to | |
425 | * <p re> | |
426 | * swit ch(Outer$0 .$EnumMap$ Color[colo rExpressio n.ordinal( )]) { | |
427 | * case 1: stmt1; | |
428 | * case 2: stmt2 | |
429 | * } | |
430 | * </ pre> | |
431 | * wi th the aux iliary tab le initial ized as fo llows: | |
432 | * <p re> | |
433 | * clas s Outer$0 { | |
434 | * synthetic final int[ ] $EnumMap $Color = n ew int[Col or.values( ).length]; | |
435 | * static { | |
436 | * try { $EnumMap$C olor[red.o rdinal()] = 1; } cat ch (NoSuch FieldError ex) {} | |
437 | * try { $EnumMap$C olor[green .ordinal() ] = 2; } c atch (NoSu chFieldErr or ex) {} | |
438 | * } | |
439 | * } | |
440 | * </ pre> | |
441 | * cl ass EnumMa pping prov ides mappi ng data an d support methods fo r this tra nslation. | |
442 | */ | |
443 | class EnumMappin g { | |
444 | En umMapping( Diagnostic Position p os, TypeSy mbol forEn um) { | |
445 | this.for Enum = for Enum; | |
446 | this.val ues = new LinkedHash Map<VarSym bol,Intege r>(); | |
447 | this.pos = pos; | |
448 | Name var Name = nam es | |
449 | .fro mString(ta rget.synth eticNameCh ar() + | |
450 | "S witchMap" + | |
451 | ta rget.synth eticNameCh ar() + | |
452 | wr iter.xClas sName(forE num.type). toString() | |
453 | .r eplace('/' , '.') | |
454 | .r eplace('.' , target.s yntheticNa meChar())) ; | |
455 | ClassSym bol outerC acheClass = outerCac heClass(); | |
456 | this.map Var = new VarSymbol( STATIC | S YNTHETIC | FINAL, | |
457 | varName, | |
458 | new ArrayT ype(syms.i ntType, sy ms.arrayCl ass), | |
459 | outerCache Class); | |
460 | enterSyn thetic(pos , mapVar, outerCache Class.memb ers()); | |
461 | } | |
462 | ||
463 | Di agnosticPo sition pos = null; | |
464 | ||
465 | // the next value to u se | |
466 | in t next = 1 ; // 0 (un used map e lements) g o to the d efault lab el | |
467 | ||
468 | // the enum for which this is a map | |
469 | fi nal TypeSy mbol forEn um; | |
470 | ||
471 | // the field containin g the map | |
472 | fi nal VarSym bol mapVar ; | |
473 | ||
474 | // the mappe d values | |
475 | fi nal Map<Va rSymbol,In teger> val ues; | |
476 | ||
477 | JC Literal fo rConstant( VarSymbol v) { | |
478 | Integer result = v alues.get( v); | |
479 | if (resu lt == null ) | |
480 | valu es.put(v, result = n ext++); | |
481 | return m ake.Litera l(result); | |
482 | } | |
483 | ||
484 | // generate the field initialize r for the map | |
485 | vo id transla te() { | |
486 | make.at( pos.getSta rtPosition ()); | |
487 | JCClassD ecl owner = classDef ((ClassSym bol)mapVar .owner); | |
488 | ||
489 | // synth etic stati c final in t[] $Switc hMap$Color = new int [Color.val ues().leng th]; | |
490 | MethodSy mbol value sMethod = lookupMeth od(pos, | |
491 | names.v alues, | |
492 | forEnum .type, | |
493 | List.<T ype>nil()) ; | |
494 | JCExpres sion size = make // Color.valu es().lengt h | |
495 | .Sel ect(make.A pp(make.Qu alIdent(va luesMethod )), | |
496 | syms.l engthVar); | |
497 | JCExpres sion mapVa rInit = ma ke | |
498 | .New Array(make .Type(syms .intType), List.of(s ize), null ) | |
499 | .set Type(new A rrayType(s yms.intTyp e, syms.ar rayClass)) ; | |
500 | ||
501 | // try { $SwitchMa p$Color[re d.ordinal( )] = 1; } catch (jav a.lang.NoS uchFieldEr ror ex) {} | |
502 | ListBuff er<JCState ment> stmt s = new Li stBuffer<J CStatement >(); | |
503 | Symbol o rdinalMeth od = looku pMethod(po s, | |
504 | na mes.ordina l, | |
505 | fo rEnum.type , | |
506 | Li st.<Type>n il()); | |
507 | List<JCC atch> catc her = List .<JCCatch> nil() | |
508 | .pre pend(make. Catch(make .VarDef(ne w VarSymbo l(PARAMETE R, names.e x, | |
509 | syms.noS uchFieldEr rorType, | |
510 | syms.noS ymbol), | |
511 | nu ll), | |
512 | make .Block(0, List.<JCSt atement>ni l()))); | |
513 | for (Map .Entry<Var Symbol,Int eger> e : values.ent rySet()) { | |
514 | VarS ymbol enum erator = e .getKey(); | |
515 | Inte ger mapped Value = e. getValue() ; | |
516 | JCEx pression a ssign = ma ke | |
517 | .Assign(ma ke.Indexed (mapVar, | |
518 | make.App( make.Selec t(make.Qua lIdent(enu merator), | |
519 | ordinalM ethod))), | |
520 | ma ke.Literal (mappedVal ue)) | |
521 | .setType(s yms.intTyp e); | |
522 | JCSt atement ex ec = make. Exec(assig n); | |
523 | JCSt atement _t ry = make. Try(make.B lock(0, Li st.of(exec )), catche r, null); | |
524 | stmt s.append(_ try); | |
525 | } | |
526 | ||
527 | owner.de fs = owner .defs | |
528 | .pre pend(make. Block(STAT IC, stmts. toList())) | |
529 | .pre pend(make. VarDef(map Var, mapVa rInit)); | |
530 | } | |
531 | } | |
532 | ||
533 | ||
534 | /********* ********** ********** ********** ********** ********** ********** ***** | |
535 | * Tree bu ilding blo cks | |
536 | ********* ********** ********** ********** ********** ********** ********** ****/ | |
537 | ||
538 | /** Eq uivalent t o make.at( pos.getSta rtPosition ()) with s ide effect of cachin g | |
539 | * po s as make_ pos, for u se in diag nostics. | |
540 | **/ | |
541 | TreeMa ker make_a t(Diagnost icPosition pos) { | |
542 | ma ke_pos = p os; | |
543 | re turn make. at(pos); | |
544 | } | |
545 | ||
546 | /** Ma ke an attr ibuted tre e represen ting a lit eral. This will be a n | |
547 | * Id ent node i n the case of boolea n literals , a Litera l node in all | |
548 | * ot her cases. | |
549 | * @p aram type The literal's type. | |
550 | * @p aram value The literal's value. | |
551 | */ | |
552 | JCExpr ession mak eLit(Type type, Obje ct value) { | |
553 | re turn make. Literal(ty pe.getTag( ), value). setType(ty pe.constTy pe(value)) ; | |
554 | } | |
555 | ||
556 | /** Ma ke an attr ibuted tre e represen ting null. | |
557 | */ | |
558 | JCExpr ession mak eNull() { | |
559 | re turn makeL it(syms.bo tType, nul l); | |
560 | } | |
561 | ||
562 | /** Ma ke an attr ibuted cla ss instanc e creation expressio n. | |
563 | * @p aram ctype The cl ass type. | |
564 | * @p aram args The co nstructor arguments. | |
565 | */ | |
566 | JCNewC lass makeN ewClass(Ty pe ctype, List<JCExp ression> a rgs) { | |
567 | JC NewClass t ree = make .NewClass( null, | |
568 | null, ma ke.QualIde nt(ctype.t sym), args , null); | |
569 | tr ee.constru ctor = rs. resolveCon structor( | |
570 | make_pos , attrEnv, ctype, Tr eeInfo.typ es(args), List.<Type >nil()); | |
571 | tr ee.type = ctype; | |
572 | re turn tree; | |
573 | } | |
574 | ||
575 | /** Ma ke an attr ibuted una ry express ion. | |
576 | * @p aram optag The op erators tr ee tag. | |
577 | * @p aram arg The op erator's a rgument. | |
578 | */ | |
579 | JCUnar y makeUnar y(JCTree.T ag optag, JCExpressi on arg) { | |
580 | JC Unary tree = make.Un ary(optag, arg); | |
581 | tr ee.operato r = rs.res olveUnaryO perator( | |
582 | make_pos , optag, a ttrEnv, ar g.type); | |
583 | tr ee.type = tree.opera tor.type.g etReturnTy pe(); | |
584 | re turn tree; | |
585 | } | |
586 | ||
587 | /** Ma ke an attr ibuted bin ary expres sion. | |
588 | * @p aram optag The op erators tr ee tag. | |
589 | * @p aram lhs The op erator's l eft argume nt. | |
590 | * @p aram rhs The op erator's r ight argum ent. | |
591 | */ | |
592 | JCBina ry makeBin ary(JCTree .Tag optag , JCExpres sion lhs, JCExpressi on rhs) { | |
593 | JC Binary tre e = make.B inary(opta g, lhs, rh s); | |
594 | tr ee.operato r = rs.res olveBinary Operator( | |
595 | make_pos , optag, a ttrEnv, lh s.type, rh s.type); | |
596 | tr ee.type = tree.opera tor.type.g etReturnTy pe(); | |
597 | re turn tree; | |
598 | } | |
599 | ||
600 | /** Ma ke an attr ibuted ass ignop expr ession. | |
601 | * @p aram optag The op erators tr ee tag. | |
602 | * @p aram lhs The op erator's l eft argume nt. | |
603 | * @p aram rhs The op erator's r ight argum ent. | |
604 | */ | |
605 | JCAssi gnOp makeA ssignop(JC Tree.Tag o ptag, JCTr ee lhs, JC Tree rhs) { | |
606 | JC AssignOp t ree = make .Assignop( optag, lhs , rhs); | |
607 | tr ee.operato r = rs.res olveBinary Operator( | |
608 | make_pos , tree.get Tag().noAs signOp(), attrEnv, l hs.type, r hs.type); | |
609 | tr ee.type = lhs.type; | |
610 | re turn tree; | |
611 | } | |
612 | ||
613 | /** Co nvert tree into stri ng object, unless it has alrea dy a | |
614 | * re ference ty pe.. | |
615 | */ | |
616 | JCExpr ession mak eString(JC Expression tree) { | |
617 | if (!tree.ty pe.isPrimi tiveOrVoid ()) { | |
618 | return t ree; | |
619 | } else { | |
620 | Symbol v alueOfSym = lookupMe thod(tree. pos(), | |
621 | names .valueOf, | |
622 | syms. stringType , | |
623 | List. of(tree.ty pe)); | |
624 | return m ake.App(ma ke.QualIde nt(valueOf Sym), List .of(tree)) ; | |
625 | } | |
626 | } | |
627 | ||
628 | /** Cr eate an em pty anonym ous class definition and enter and compl ete | |
629 | * it s symbol. Return the class def inition's symbol. | |
630 | * an d create | |
631 | * @p aram flags The cl ass symbol 's flags | |
632 | * @p aram owner The cl ass symbol 's owner | |
633 | */ | |
634 | JCClas sDecl make EmptyClass (long flag s, ClassSy mbol owner ) { | |
635 | re turn makeE mptyClass( flags, own er, null, true); | |
636 | } | |
637 | ||
638 | JCClas sDecl make EmptyClass (long flag s, ClassSy mbol owner , Name fla tname, | |
639 | boolean addToDefs) { | |
640 | // Create cl ass symbol . | |
641 | Cl assSymbol c = reader .defineCla ss(names.e mpty, owne r); | |
642 | if (flatname != null) { | |
643 | c.flatna me = flatn ame; | |
644 | } else { | |
645 | c.flatna me = chk.l ocalClassN ame(c); | |
646 | } | |
647 | c. sourcefile = owner.s ourcefile; | |
648 | c. completer = null; | |
649 | c. members_fi eld = new Scope(c); | |
650 | c. flags_fiel d = flags; | |
651 | Cl assType ct ype = (Cla ssType) c. type; | |
652 | ct ype.supert ype_field = syms.obj ectType; | |
653 | ct ype.interf aces_field = List.ni l(); | |
654 | ||
655 | JC ClassDecl odef = cla ssDef(owne r); | |
656 | ||
657 | // Enter cla ss symbol in owner s cope and c ompiled ta ble. | |
658 | en terSynthet ic(odef.po s(), c, ow ner.member s()); | |
659 | ch k.compiled .put(c.fla tname, c); | |
660 | ||
661 | // Create cl ass defini tion tree. | |
662 | JC ClassDecl cdef = mak e.ClassDef ( | |
663 | make.Mod ifiers(fla gs), names .empty, | |
664 | List.<JC TypeParame ter>nil(), | |
665 | null, Li st.<JCExpr ession>nil (), List.< JCTree>nil ()); | |
666 | cd ef.sym = c ; | |
667 | cd ef.type = c.type; | |
668 | ||
669 | // Append cl ass defini tion tree to owner's definitio ns. | |
670 | if (addToDef s) odef.de fs = odef. defs.prepe nd(cdef); | |
671 | re turn cdef; | |
672 | } | |
673 | ||
674 | /********* ********** ********** ********** ********** ********** ********** ***** | |
675 | * Symbol manipulati on utiliti es | |
676 | ********* ********** ********** ********** ********** ********** ********** ****/ | |
677 | ||
678 | /** En ter a synt hetic symb ol in a gi ven scope, but compl ain if the re was alr eady one t here. | |
679 | * @p aram pos P osition fo r error re porting. | |
680 | * @p aram sym T he symbol. | |
681 | * @p aram s T he scope. | |
682 | */ | |
683 | privat e void ent erSyntheti c(Diagnost icPosition pos, Symb ol sym, Sc ope s) { | |
684 | s. enter(sym) ; | |
685 | } | |
686 | ||
687 | /** Cr eate a fre sh synthet ic name wi thin a giv en scope - the uniqu e name is | |
688 | * ob tained by appending '$' chars at the end of the na me until n o match | |
689 | * is found. | |
690 | * | |
691 | * @pa ram name b ase name | |
692 | * @pa ram s scop e in which the name has to be unique | |
693 | * @re turn fresh synthetic name | |
694 | */ | |
695 | privat e Name mak eSynthetic Name(Name name, Scop e s) { | |
696 | do { | |
697 | name = n ame.append ( | |
698 | target.syn theticName Char(), | |
699 | names.empt y); | |
700 | } while (loo kupSynthet ic(name, s ) != null) ; | |
701 | re turn name; | |
702 | } | |
703 | ||
704 | /** Ch eck whethe r syntheti c symbols generated during low ering conf lict | |
705 | * wi th user-de fined symb ols. | |
706 | * | |
707 | * @p aram trans latedTrees lowered c lass trees | |
708 | */ | |
709 | void c heckConfli cts(List<J CTree> tra nslatedTre es) { | |
710 | fo r (JCTree t : transl atedTrees) { | |
711 | t.accept (conflicts Checker); | |
712 | } | |
713 | } | |
714 | ||
715 | JCTree .Visitor c onflictsCh ecker = ne w TreeScan ner() { | |
716 | ||
717 | Ty peSymbol c urrentClas s; | |
718 | ||
719 | @O verride | |
720 | pu blic void visitMetho dDef(JCMet hodDecl th at) { | |
721 | chk.chec kConflicts (that.pos( ), that.sy m, current Class); | |
722 | super.vi sitMethodD ef(that); | |
723 | } | |
724 | ||
725 | @O verride | |
726 | pu blic void visitVarDe f(JCVariab leDecl tha t) { | |
727 | if (that .sym.owner .kind == T YP) { | |
728 | chk. checkConfl icts(that. pos(), tha t.sym, cur rentClass) ; | |
729 | } | |
730 | super.vi sitVarDef( that); | |
731 | } | |
732 | ||
733 | @O verride | |
734 | pu blic void visitClass Def(JCClas sDecl that ) { | |
735 | TypeSymb ol prevCur rentClass = currentC lass; | |
736 | currentC lass = tha t.sym; | |
737 | try { | |
738 | supe r.visitCla ssDef(that ); | |
739 | } | |
740 | finally { | |
741 | curr entClass = prevCurre ntClass; | |
742 | } | |
743 | } | |
744 | }; | |
745 | ||
746 | /** Lo ok up a sy nthetic na me in a gi ven scope. | |
747 | * @p aram s Th e scope. | |
748 | * @p aram name Th e name. | |
749 | */ | |
750 | privat e Symbol l ookupSynth etic(Name name, Scop e s) { | |
751 | Sy mbol sym = s.lookup( name).sym; | |
752 | re turn (sym= =null || ( sym.flags( )&SYNTHETI C)==0) ? n ull : sym; | |
753 | } | |
754 | ||
755 | /** Lo ok up a me thod in a given scop e. | |
756 | */ | |
757 | privat e MethodSy mbol looku pMethod(Di agnosticPo sition pos , Name nam e, Type qu al, List<T ype> args) { | |
758 | re turn rs.re solveInter nalMethod( pos, attrE nv, qual, name, args , List.<Ty pe>nil()); | |
759 | } | |
760 | ||
761 | /** Lo ok up a co nstructor. | |
762 | */ | |
763 | privat e MethodSy mbol looku pConstruct or(Diagnos ticPositio n pos, Typ e qual, Li st<Type> a rgs) { | |
764 | re turn rs.re solveInter nalConstru ctor(pos, attrEnv, q ual, args, null); | |
765 | } | |
766 | ||
767 | /** Lo ok up a fi eld. | |
768 | */ | |
769 | privat e VarSymbo l lookupFi eld(Diagno sticPositi on pos, Ty pe qual, N ame name) { | |
770 | re turn rs.re solveInter nalField(p os, attrEn v, qual, n ame); | |
771 | } | |
772 | ||
773 | /** An on inner c lasses are used as a ccess cons tructor ta gs. | |
774 | * acc essConstru ctorTag wi ll use an existing a non class if one is available, | |
775 | * and synthethi se a class (with mak eEmptyClas s) if one is not ava ilable. | |
776 | * How ever, ther e is a sma ll possibi lity that an existin g class wi ll not | |
777 | * be generated as expecte d if it is inside a conditiona l with a c onstant | |
778 | * exp ression. I f that is found to b e the case , create a n empty cl ass tree h ere. | |
779 | */ | |
780 | privat e void che ckAccessCo nstructorT ags() { | |
781 | fo r (List<Cl assSymbol> l = acces sConstrTag s; l.nonEm pty(); l = l.tail) { | |
782 | ClassSym bol c = l. head; | |
783 | if (isTr anslatedCl assAvailab le(c)) | |
784 | cont inue; | |
785 | // Creat e class de finition t ree. | |
786 | JCClassD ecl cdec = makeEmpty Class(STAT IC | SYNTH ETIC, | |
787 | c.outermos tClass(), c.flatname , false); | |
788 | swapAcce ssConstruc torTag(c, cdec.sym); | |
789 | translat ed.append( cdec); | |
790 | } | |
791 | } | |
792 | // whe re | |
793 | privat e boolean isTranslat edClassAva ilable(Cla ssSymbol c ) { | |
794 | fo r (JCTree tree: tran slated) { | |
795 | if (tree .hasTag(CL ASSDEF) | |
796 | && ((JCCla ssDecl) tr ee).sym == c) { | |
797 | retu rn true; | |
798 | } | |
799 | } | |
800 | re turn false ; | |
801 | } | |
802 | ||
803 | void s wapAccessC onstructor Tag(ClassS ymbol oldC Tag, Class Symbol new CTag) { | |
804 | fo r (MethodS ymbol meth odSymbol : accessCon strs.value s()) { | |
805 | Assert.c heck(metho dSymbol.ty pe.hasTag( METHOD)); | |
806 | MethodTy pe oldMeth odType = | |
807 | (MethodTyp e)methodSy mbol.type; | |
808 | if (oldM ethodType. argtypes.h ead.tsym = = oldCTag) | |
809 | meth odSymbol.t ype = | |
810 | types.crea teMethodTy peWithPara meters(old MethodType , | |
811 | oldMet hodType.ge tParameter Types().ta il | |
812 | .p repend(new CTag.erasu re(types)) ); | |
813 | } | |
814 | } | |
815 | ||
816 | /********* ********** ********** ********** ********** ********** ********** ***** | |
817 | * Access methods | |
818 | ********* ********** ********** ********** ********** ********** ********** ****/ | |
819 | ||
820 | /** Ac cess codes for deref erencing, assignment , | |
821 | * an d pre/post increment /decrement . | |
822 | * Ac cess codes for assig nment oper ations are determine d by metho d accessCo de | |
823 | * be low. | |
824 | * | |
825 | * Al l access c odes for a ccesses to the curre nt class a re even. | |
826 | * If a member of the sup erclass sh ould be ac cessed ins tead (beca use | |
827 | * ac cess was v ia a quali fied super ), add one to the co rrespondin g code | |
828 | * fo r the curr ent class, making th e number o dd. | |
829 | * Th is numberi ng scheme is used by the backe nd to deci de whether | |
830 | * to issue an invokevirt ual or inv okespecial call. | |
831 | * | |
832 | * @s ee Gen#vis itSelect(J CFieldAcce ss tree) | |
833 | */ | |
834 | privat e static f inal int | |
835 | DE REFcode = 0, | |
836 | AS SIGNcode = 2, | |
837 | PR EINCcode = 4, | |
838 | PR EDECcode = 6, | |
839 | PO STINCcode = 8, | |
840 | PO STDECcode = 10, | |
841 | FI RSTASGOPco de = 12; | |
842 | ||
843 | /** Nu mber of ac cess codes | |
844 | */ | |
845 | privat e static f inal int N CODES = ac cessCode(B yteCodes.l ushrl) + 2 ; | |
846 | ||
847 | /** A mapping fr om symbols to their access num bers. | |
848 | */ | |
849 | privat e Map<Symb ol,Integer > accessNu ms; | |
850 | ||
851 | /** A mapping fr om symbols to an arr ay of acce ss symbols , indexed by | |
852 | * ac cess code. | |
853 | */ | |
854 | privat e Map<Symb ol,MethodS ymbol[]> a ccessSyms; | |
855 | ||
856 | /** A mapping fr om (constr uctor) sym bols to ac cess const ructor sym bols. | |
857 | */ | |
858 | privat e Map<Symb ol,MethodS ymbol> acc essConstrs ; | |
859 | ||
860 | /** A list of al l class sy mbols used for acces s construc tor tags. | |
861 | */ | |
862 | privat e List<Cla ssSymbol> accessCons trTags; | |
863 | ||
864 | /** A queue for all access ed symbols . | |
865 | */ | |
866 | privat e ListBuff er<Symbol> accessed; | |
867 | ||
868 | /** Ma p bytecode of binary operation to access code of c orrespondi ng | |
869 | * as signment o peration. This is al ways an ev en number. | |
870 | */ | |
871 | privat e static i nt accessC ode(int by tecode) { | |
872 | if (ByteCode s.iadd <= bytecode & & bytecode <= ByteCo des.lxor) | |
873 | return ( bytecode - iadd) * 2 + FIRSTAS GOPcode; | |
874 | el se if (byt ecode == B yteCodes.s tring_add) | |
875 | return ( ByteCodes. lxor + 1 - iadd) * 2 + FIRSTAS GOPcode; | |
876 | el se if (Byt eCodes.ish ll <= byte code && by tecode <= ByteCodes. lushrl) | |
877 | return ( bytecode - ishll + B yteCodes.l xor + 2 - iadd) * 2 + FIRSTASG OPcode; | |
878 | el se | |
879 | return - 1; | |
880 | } | |
881 | ||
882 | /** re turn acces s code for identifie r, | |
883 | * @p aram tree The tr ee represe nting the identifier use. | |
884 | * @p aram enclO p The cl osest encl osing oper ation node of tree, | |
885 | * null i f tree is not a subt ree of an operation. | |
886 | */ | |
887 | privat e static i nt accessC ode(JCTree tree, JCT ree enclOp ) { | |
888 | if (enclOp = = null) | |
889 | return D EREFcode; | |
890 | el se if (enc lOp.hasTag (ASSIGN) & & | |
891 | tre e == TreeI nfo.skipPa rens(((JCA ssign) enc lOp).lhs)) | |
892 | return A SSIGNcode; | |
893 | el se if (enc lOp.getTag ().isIncOr DecUnaryOp () && | |
894 | tre e == TreeI nfo.skipPa rens(((JCU nary) encl Op).arg)) | |
895 | return m apTagToUna ryOpCode(e nclOp.getT ag()); | |
896 | el se if (enc lOp.getTag ().isAssig nop() && | |
897 | tre e == TreeI nfo.skipPa rens(((JCA ssignOp) e nclOp).lhs )) | |
898 | return a ccessCode( ((Operator Symbol) (( JCAssignOp ) enclOp). operator). opcode); | |
899 | el se | |
900 | return D EREFcode; | |
901 | } | |
902 | ||
903 | /** Re turn binar y operator that corr esponds to given acc ess code. | |
904 | */ | |
905 | privat e Operator Symbol bin aryAccessO perator(in t acode) { | |
906 | fo r (Scope.E ntry e = s yms.predef Class.memb ers().elem s; | |
907 | e != nu ll; | |
908 | e = e.s ibling) { | |
909 | if (e.sy m instance of Operato rSymbol) { | |
910 | Oper atorSymbol op = (Ope ratorSymbo l)e.sym; | |
911 | if ( accessCode (op.opcode ) == acode ) return o p; | |
912 | } | |
913 | } | |
914 | re turn null; | |
915 | } | |
916 | ||
917 | /** Re turn tree tag for as signment o peration c orrespondi ng | |
918 | * to given bin ary operat or. | |
919 | */ | |
920 | privat e static J CTree.Tag treeTag(Op eratorSymb ol operato r) { | |
921 | sw itch (oper ator.opcod e) { | |
922 | ca se ByteCod es.ior: ca se ByteCod es.lor: | |
923 | return B ITOR_ASG; | |
924 | ca se ByteCod es.ixor: c ase ByteCo des.lxor: | |
925 | return B ITXOR_ASG; | |
926 | ca se ByteCod es.iand: c ase ByteCo des.land: | |
927 | return B ITAND_ASG; | |
928 | ca se ByteCod es.ishl: c ase ByteCo des.lshl: | |
929 | ca se ByteCod es.ishll: case ByteC odes.lshll : | |
930 | return S L_ASG; | |
931 | ca se ByteCod es.ishr: c ase ByteCo des.lshr: | |
932 | ca se ByteCod es.ishrl: case ByteC odes.lshrl : | |
933 | return S R_ASG; | |
934 | ca se ByteCod es.iushr: case ByteC odes.lushr : | |
935 | ca se ByteCod es.iushrl: case Byte Codes.lush rl: | |
936 | return U SR_ASG; | |
937 | ca se ByteCod es.iadd: c ase ByteCo des.ladd: | |
938 | ca se ByteCod es.fadd: c ase ByteCo des.dadd: | |
939 | ca se ByteCod es.string_ add: | |
940 | return P LUS_ASG; | |
941 | ca se ByteCod es.isub: c ase ByteCo des.lsub: | |
942 | ca se ByteCod es.fsub: c ase ByteCo des.dsub: | |
943 | return M INUS_ASG; | |
944 | ca se ByteCod es.imul: c ase ByteCo des.lmul: | |
945 | ca se ByteCod es.fmul: c ase ByteCo des.dmul: | |
946 | return M UL_ASG; | |
947 | ca se ByteCod es.idiv: c ase ByteCo des.ldiv: | |
948 | ca se ByteCod es.fdiv: c ase ByteCo des.ddiv: | |
949 | return D IV_ASG; | |
950 | ca se ByteCod es.imod: c ase ByteCo des.lmod: | |
951 | ca se ByteCod es.fmod: c ase ByteCo des.dmod: | |
952 | return M OD_ASG; | |
953 | de fault: | |
954 | throw ne w Assertio nError(); | |
955 | } | |
956 | } | |
957 | ||
958 | /** Th e name of the access method wi th number `anum' and access co de `acode' . | |
959 | */ | |
960 | Name a ccessName( int anum, int acode) { | |
961 | re turn names .fromStrin g( | |
962 | "access" + target. syntheticN ameChar() + anum + a code / 10 + acode % 10); | |
963 | } | |
964 | ||
965 | /** Re turn acces s symbol f or a priva te or prot ected symb ol from an inner cla ss. | |
966 | * @p aram sym The accessed p rivate sym bol. | |
967 | * @p aram tree The accessing tree. | |
968 | * @p aram enclO p The closest en closing op eration no de of tree , | |
969 | * null if tree i s not a su btree of a n operatio n. | |
970 | * @p aram protA ccess Is a ccess to a protected symbol in another | |
971 | * pack age? | |
972 | * @p aram refSu per Is a ccess via a (qualifi ed) C.supe r? | |
973 | */ | |
974 | Method Symbol acc essSymbol( Symbol sym , JCTree t ree, JCTre e enclOp, | |
975 | boolean pr otAccess, boolean re fSuper) { | |
976 | Cl assSymbol accOwner = refSuper && protAcc ess | |
977 | // For a ccess via qualified super (T.s uper.x), p lace the | |
978 | // acces s symbol o n T. | |
979 | ? (Class Symbol)((J CFieldAcce ss) tree). selected.t ype.tsym | |
980 | // Other wise prete nd that th e owner of an access ed | |
981 | // prote cted symbo l is the e nclosing c lass of th e current | |
982 | // class which is a subclass of the sy mbol's own er. | |
983 | : access Class(sym, protAcces s, tree); | |
984 | ||
985 | Sy mbol vsym = sym; | |
986 | if (sym.owne r != accOw ner) { | |
987 | vsym = s ym.clone(a ccOwner); | |
988 | actualSy mbols.put( vsym, sym) ; | |
989 | } | |
990 | ||
991 | In teger anum // The access nu mber of th e access m ethod. | |
992 | = access Nums.get(v sym); | |
993 | if (anum == null) { | |
994 | anum = a ccessed.le ngth(); | |
995 | accessNu ms.put(vsy m, anum); | |
996 | accessSy ms.put(vsy m, new Met hodSymbol[ NCODES]); | |
997 | accessed .append(vs ym); | |
998 | // Syste m.out.prin tln("acces sing " + v sym + " in " + vsym. location() ); | |
999 | } | |
1000 | ||
1001 | in t acode; // The access co de of the access met hod. | |
1002 | Li st<Type> a rgtypes; // The argument types of t he access method. | |
1003 | Ty pe restype ; // The result ty pe of the access met hod. | |
1004 | Li st<Type> t hrown; // The thrown ex ceptions o f the acce ss method. | |
1005 | sw itch (vsym .kind) { | |
1006 | ca se VAR: | |
1007 | acode = accessCode (tree, enc lOp); | |
1008 | if (acod e >= FIRST ASGOPcode) { | |
1009 | Oper atorSymbol operator = binaryAc cessOperat or(acode); | |
1010 | if ( operator.o pcode == s tring_add) | |
1011 | argtypes = List.of(s yms.object Type); | |
1012 | else | |
1013 | argtypes = operator. type.getPa rameterTyp es().tail; | |
1014 | } else i f (acode = = ASSIGNco de) | |
1015 | argt ypes = Lis t.of(vsym. erasure(ty pes)); | |
1016 | else | |
1017 | argt ypes = Lis t.nil(); | |
1018 | restype = vsym.era sure(types ); | |
1019 | thrown = List.nil( ); | |
1020 | break; | |
1021 | ca se MTH: | |
1022 | acode = DEREFcode; | |
1023 | argtypes = vsym.er asure(type s).getPara meterTypes (); | |
1024 | restype = vsym.era sure(types ).getRetur nType(); | |
1025 | thrown = vsym.type .getThrown Types(); | |
1026 | break; | |
1027 | de fault: | |
1028 | throw ne w Assertio nError(); | |
1029 | } | |
1030 | ||
1031 | // For refer ences via qualified super, inc rement aco de by one, | |
1032 | // making it odd. | |
1033 | if (protAcce ss && refS uper) acod e++; | |
1034 | ||
1035 | // Instance access met hods get i nstance as first par ameter. | |
1036 | // For prote cted symbo ls this ne eds to be the instan ce as a me mber | |
1037 | // of the ty pe contain ing the ac cessed sym bol, not t he class | |
1038 | // containin g the acce ss method. | |
1039 | if ((vsym.fl ags() & ST ATIC) == 0 ) { | |
1040 | argtypes = argtype s.prepend( vsym.owner .erasure(t ypes)); | |
1041 | } | |
1042 | Me thodSymbol [] accesso rs = acces sSyms.get( vsym); | |
1043 | Me thodSymbol accessor = accessor s[acode]; | |
1044 | if (accessor == null) { | |
1045 | accessor = new Met hodSymbol( | |
1046 | STAT IC | SYNTH ETIC, | |
1047 | acce ssName(anu m.intValue (), acode) , | |
1048 | new MethodType (argtypes, restype, thrown, sy ms.methodC lass), | |
1049 | accO wner); | |
1050 | enterSyn thetic(tre e.pos(), a ccessor, a ccOwner.me mbers()); | |
1051 | accessor s[acode] = accessor; | |
1052 | } | |
1053 | re turn acces sor; | |
1054 | } | |
1055 | ||
1056 | /** Th e qualifie r to be us ed for acc essing a s ymbol in a n outer cl ass. | |
1057 | * Th is is eith er C.sym o r C.this.s ym, depend ing on whe ther or no t | |
1058 | * sy m is stati c. | |
1059 | * @p aram sym The acces sed symbol . | |
1060 | */ | |
1061 | JCExpr ession acc essBase(Di agnosticPo sition pos , Symbol s ym) { | |
1062 | re turn (sym. flags() & STATIC) != 0 | |
1063 | ? access (make.at(p os.getStar tPosition( )).QualIde nt(sym.own er)) | |
1064 | : makeOw nerThis(po s, sym, tr ue); | |
1065 | } | |
1066 | ||
1067 | /** Do we need a n access m ethod to r eference p rivate sym bol? | |
1068 | */ | |
1069 | boolea n needsPri vateAccess (Symbol sy m) { | |
1070 | if ((sym.fla gs() & PRI VATE) == 0 || sym.ow ner == cur rentClass) { | |
1071 | return f alse; | |
1072 | } else if (s ym.name == names.ini t && sym.o wner.isLoc al()) { | |
1073 | // priva te constru ctor in lo cal class: relax pro tection | |
1074 | sym.flag s_field &= ~PRIVATE; | |
1075 | return f alse; | |
1076 | } else { | |
1077 | return t rue; | |
1078 | } | |
1079 | } | |
1080 | ||
1081 | /** Do we need a n access m ethod to r eference s ymbol in o ther packa ge? | |
1082 | */ | |
1083 | boolea n needsPro tectedAcce ss(Symbol sym, JCTre e tree) { | |
1084 | if ((sym.fla gs() & PRO TECTED) == 0 || | |
1085 | sym.owne r.owner == currentCl ass.owner || // fast special c ase | |
1086 | sym.pack ge() == cu rrentClass .packge()) | |
1087 | return f alse; | |
1088 | if (!current Class.isSu bClass(sym .owner, ty pes)) | |
1089 | return t rue; | |
1090 | if ((sym.fla gs() & STA TIC) != 0 || | |
1091 | !tree.ha sTag(SELEC T) || | |
1092 | TreeInfo .name(((JC FieldAcces s) tree).s elected) = = names._s uper) | |
1093 | return f alse; | |
1094 | re turn !((JC FieldAcces s) tree).s elected.ty pe.tsym.is SubClass(c urrentClas s, types); | |
1095 | } | |
1096 | ||
1097 | /** Th e class in which an access met hod for gi ven symbol goes. | |
1098 | * @p aram sym The access sym bol | |
1099 | * @p aram protA ccess Is a ccess to a protected symbol in another | |
1100 | * pack age? | |
1101 | */ | |
1102 | ClassS ymbol acce ssClass(Sy mbol sym, boolean pr otAccess, JCTree tre e) { | |
1103 | if (protAcce ss) { | |
1104 | Symbol q ualifier = null; | |
1105 | ClassSym bol c = cu rrentClass ; | |
1106 | if (tree .hasTag(SE LECT) && ( sym.flags( ) & STATIC ) == 0) { | |
1107 | qual ifier = (( JCFieldAcc ess) tree) .selected. type.tsym; | |
1108 | whil e (!qualif ier.isSubC lass(c, ty pes)) { | |
1109 | c = c.owne r.enclClas s(); | |
1110 | } | |
1111 | retu rn c; | |
1112 | } else { | |
1113 | whil e (!c.isSu bClass(sym .owner, ty pes)) { | |
1114 | c = c.owne r.enclClas s(); | |
1115 | } | |
1116 | } | |
1117 | return c ; | |
1118 | } else { | |
1119 | // the s ymbol is p rivate | |
1120 | return s ym.owner.e nclClass() ; | |
1121 | } | |
1122 | } | |
1123 | ||
1124 | privat e void add PrunedInfo (JCTree tr ee) { | |
1125 | Li st<JCTree> infoList = prunedTr ee.get(cur rentClass) ; | |
1126 | in foList = ( infoList = = null) ? List.of(tr ee) : info List.prepe nd(tree); | |
1127 | pr unedTree.p ut(current Class, inf oList); | |
1128 | } | |
1129 | ||
1130 | /** En sure that identifier is access ible, retu rn tree ac cessing th e identifi er. | |
1131 | * @p aram sym The ac cessed sym bol. | |
1132 | * @p aram tree The tr ee referri ng to the symbol. | |
1133 | * @p aram enclO p The cl osest encl osing oper ation node of tree, | |
1134 | * null i f tree is not a subt ree of an operation. | |
1135 | * @p aram refSu per Is acc ess via a (qualified ) C.super? | |
1136 | */ | |
1137 | JCExpr ession acc ess(Symbol sym, JCEx pression t ree, JCExp ression en clOp, bool ean refSup er) { | |
1138 | // Access a free varia ble via it s proxy, o r its prox y's proxy | |
1139 | wh ile (sym.k ind == VAR && sym.ow ner.kind = = MTH && | |
1140 | sym.owne r.enclClas s() != cur rentClass) { | |
1141 | // A con stant is r eplaced by its const ant value. | |
1142 | Object c v = ((VarS ymbol)sym) .getConstV alue(); | |
1143 | if (cv ! = null) { | |
1144 | make .at(tree.p os); | |
1145 | retu rn makeLit (sym.type, cv); | |
1146 | } | |
1147 | // Other wise repla ce the var iable by i ts proxy. | |
1148 | sym = pr oxies.look up(proxyNa me(sym.nam e)).sym; | |
1149 | Assert.c heck(sym ! = null && (sym.flags _field & F INAL) != 0 ); | |
1150 | tree = m ake.at(tre e.pos).Ide nt(sym); | |
1151 | } | |
1152 | JC Expression base = (t ree.hasTag (SELECT)) ? ((JCFiel dAccess) t ree).selec ted : null ; | |
1153 | sw itch (sym. kind) { | |
1154 | ca se TYP: | |
1155 | if (sym. owner.kind != PCK) { | |
1156 | // C onvert typ e idents t o | |
1157 | // < flat name> or <packa ge name> . <flat nam e> | |
1158 | Name flatname = Convert. shortName( sym.flatNa me()); | |
1159 | whil e (base != null && | |
1160 | TreeInf o.symbol(b ase) != nu ll && | |
1161 | TreeInf o.symbol(b ase).kind != PCK) { | |
1162 | base = (ba se.hasTag( SELECT)) | |
1163 | ? ((JC FieldAcces s) base).s elected | |
1164 | : null ; | |
1165 | } | |
1166 | if ( tree.hasTa g(IDENT)) { | |
1167 | ((JCIdent) tree).nam e = flatna me; | |
1168 | } el se if (bas e == null) { | |
1169 | tree = mak e.at(tree. pos).Ident (sym); | |
1170 | ((JCIdent) tree).nam e = flatna me; | |
1171 | } el se { | |
1172 | ((JCFieldA ccess) tre e).selecte d = base; | |
1173 | ((JCFieldA ccess) tre e).name = flatname; | |
1174 | } | |
1175 | } | |
1176 | break; | |
1177 | ca se MTH: ca se VAR: | |
1178 | if (sym. owner.kind == TYP) { | |
1179 | ||
1180 | // A ccess meth ods are re quired for | |
1181 | // - private members, | |
1182 | // - protecte d members in a super class of a n | |
1183 | // enclosin g class co ntained in another p ackage. | |
1184 | // - all non- private me mbers acce ssed via a qualified super. | |
1185 | bool ean protAc cess = ref Super && ! needsPriva teAccess(s ym) | |
1186 | || needsPr otectedAcc ess(sym, t ree); | |
1187 | bool ean accReq = protAcc ess || nee dsPrivateA ccess(sym) ; | |
1188 | ||
1189 | // A base has to be supp lied for | |
1190 | // - simple i dentifiers accessing variables in outer classes. | |
1191 | bool ean baseRe q = | |
1192 | base == nu ll && | |
1193 | sym.owner != syms.pr edefClass && | |
1194 | !sym.isMem berOf(curr entClass, types); | |
1195 | ||
1196 | if ( accReq || baseReq) { | |
1197 | make.at(tr ee.pos); | |
1198 | ||
1199 | // Constan ts are rep laced by t heir const ant value. | |
1200 | if (sym.ki nd == VAR) { | |
1201 | Object cv = ((Va rSymbol)sy m).getCons tValue(); | |
1202 | if (cv != null) { | |
1203 | ad dPrunedInf o(tree); | |
1204 | re turn makeL it(sym.typ e, cv); | |
1205 | } | |
1206 | } | |
1207 | ||
1208 | // Private variables and metho ds are rep laced by c alls | |
1209 | // to thei r access m ethods. | |
1210 | if (accReq ) { | |
1211 | List<J CExpressio n> args = List.nil() ; | |
1212 | if ((s ym.flags() & STATIC) == 0) { | |
1213 | // Instance access met hods get i nstance | |
1214 | // as first parameter. | |
1215 | if (base == null) | |
1216 | base = m akeOwnerTh is(tree.po s(), sym, true); | |
1217 | ar gs = args. prepend(ba se); | |
1218 | ba se = null; // so w e don't du plicate co de | |
1219 | } | |
1220 | Symbol access = accessSymb ol(sym, tr ee, | |
1221 | enclOp, protAcces s, | |
1222 | refSupe r); | |
1223 | JCExpr ession rec eiver = ma ke.Select( | |
1224 | ba se != null ? base : make.QualI dent(acces s.owner), | |
1225 | ac cess); | |
1226 | return make.App( receiver, args); | |
1227 | ||
1228 | // Other a ccesses to members o f outer cl asses get a | |
1229 | // qualifi er. | |
1230 | } else if (baseReq) { | |
1231 | return make.at(t ree.pos).S elect( | |
1232 | ac cessBase(t ree.pos(), sym), sym ).setType( tree.type) ; | |
1233 | } | |
1234 | } | |
1235 | } else i f (sym.own er.kind == MTH && la mbdaTransl ationMap ! = null) { | |
1236 | //sy m is a loc al variabl e - check the lambda translati on map to | |
1237 | //se e if sym h as been tr anslated t o somethin g else in the curren t | |
1238 | //sc ope (by La mbdaToMeth od) | |
1239 | Symb ol transla tedSym = l ambdaTrans lationMap. get(sym); | |
1240 | if ( translated Sym != nul l) { | |
1241 | tree = mak e.at(tree. pos).Ident (translate dSym); | |
1242 | } | |
1243 | } | |
1244 | } | |
1245 | re turn tree; | |
1246 | } | |
1247 | ||
1248 | /** En sure that identifier is access ible, retu rn tree ac cessing th e identifi er. | |
1249 | * @p aram tree The id entifier t ree. | |
1250 | */ | |
1251 | JCExpr ession acc ess(JCExpr ession tre e) { | |
1252 | Sy mbol sym = TreeInfo. symbol(tre e); | |
1253 | re turn sym = = null ? t ree : acce ss(sym, tr ee, null, false); | |
1254 | } | |
1255 | ||
1256 | /** Re turn acces s construc tor for a private co nstructor, | |
1257 | * or the const ructor its elf, if no access co nstructor is needed. | |
1258 | * @p aram pos The p osition to report di agnostics, if any. | |
1259 | * @p aram const r The p rivate con structor. | |
1260 | */ | |
1261 | Symbol accessCon structor(D iagnosticP osition po s, Symbol constr) { | |
1262 | if (needsPri vateAccess (constr)) { | |
1263 | ClassSym bol accOwn er = const r.owner.en clClass(); | |
1264 | MethodSy mbol acons tr = acces sConstrs.g et(constr) ; | |
1265 | if (acon str == nul l) { | |
1266 | List <Type> arg types = co nstr.type. getParamet erTypes(); | |
1267 | if ( (accOwner. flags_fiel d & ENUM) != 0) | |
1268 | argtypes = argtypes | |
1269 | .prepe nd(syms.in tType) | |
1270 | .prepe nd(syms.st ringType); | |
1271 | acon str = new MethodSymb ol( | |
1272 | SYNTHETIC, | |
1273 | names.init , | |
1274 | new Method Type( | |
1275 | argtyp es.append( | |
1276 | ac cessConstr uctorTag() .erasure(t ypes)), | |
1277 | constr .type.getR eturnType( ), | |
1278 | constr .type.getT hrownTypes (), | |
1279 | syms.m ethodClass ), | |
1280 | accOwner); | |
1281 | ente rSynthetic (pos, acon str, accOw ner.member s()); | |
1282 | acce ssConstrs. put(constr , aconstr) ; | |
1283 | acce ssed.appen d(constr); | |
1284 | } | |
1285 | return a constr; | |
1286 | } else { | |
1287 | return c onstr; | |
1288 | } | |
1289 | } | |
1290 | ||
1291 | /** Re turn an an onymous cl ass nested in this t oplevel cl ass. | |
1292 | */ | |
1293 | ClassS ymbol acce ssConstruc torTag() { | |
1294 | Cl assSymbol topClass = currentCl ass.outerm ostClass() ; | |
1295 | Na me flatnam e = names. fromString ("" + topC lass.getQu alifiedNam e() + | |
1296 | target.sy ntheticNam eChar() + | |
1297 | "1"); | |
1298 | Cl assSymbol ctag = chk .compiled. get(flatna me); | |
1299 | if (ctag == null) | |
1300 | ctag = m akeEmptyCl ass(STATIC | SYNTHET IC, topCla ss).sym; | |
1301 | // keep a re cord of al l tags, to verify th at all are generated as requir ed | |
1302 | ac cessConstr Tags = acc essConstrT ags.prepen d(ctag); | |
1303 | re turn ctag; | |
1304 | } | |
1305 | ||
1306 | /** Ad d all requ ired acces s methods for a priv ate symbol to enclos ing class. | |
1307 | * @p aram sym The s ymbol. | |
1308 | */ | |
1309 | void m akeAccessi ble(Symbol sym) { | |
1310 | JC ClassDecl cdef = cla ssDef(sym. owner.encl Class()); | |
1311 | if (cdef == null) Asse rt.error(" class def not found: " + sym + " in " + sym.owner) ; | |
1312 | if (sym.name == names. init) { | |
1313 | cdef.def s = cdef.d efs.prepen d( | |
1314 | acce ssConstruc torDef(cde f.pos, sym , accessCo nstrs.get( sym))); | |
1315 | } else { | |
1316 | MethodSy mbol[] acc essors = a ccessSyms. get(sym); | |
1317 | for (int i = 0; i < NCODES; i++) { | |
1318 | if ( accessors[ i] != null ) | |
1319 | cdef.defs = cdef.def s.prepend( | |
1320 | access Def(cdef.p os, sym, a ccessors[i ], i)); | |
1321 | } | |
1322 | } | |
1323 | } | |
1324 | ||
1325 | /** Ma ps unary o perator in teger code s to JCTre e.Tag obje cts | |
1326 | * @p aram unary OpCode the unary ope rator code | |
1327 | */ | |
1328 | privat e static T ag mapUnar yOpCodeToT ag(int una ryOpCode){ | |
1329 | sw itch (unar yOpCode){ | |
1330 | case PRE INCcode: | |
1331 | retu rn PREINC; | |
1332 | case PRE DECcode: | |
1333 | retu rn PREDEC; | |
1334 | case POS TINCcode: | |
1335 | retu rn POSTINC ; | |
1336 | case POS TDECcode: | |
1337 | retu rn POSTDEC ; | |
1338 | default: | |
1339 | retu rn NO_TAG; | |
1340 | } | |
1341 | } | |
1342 | ||
1343 | /** Ma ps JCTree. Tag object s to unary operator integer co des | |
1344 | * @p aram tag t he JCTree. Tag | |
1345 | */ | |
1346 | privat e static i nt mapTagT oUnaryOpCo de(Tag tag ){ | |
1347 | sw itch (tag) { | |
1348 | case PRE INC: | |
1349 | retu rn PREINCc ode; | |
1350 | case PRE DEC: | |
1351 | retu rn PREDECc ode; | |
1352 | case POS TINC: | |
1353 | retu rn POSTINC code; | |
1354 | case POS TDEC: | |
1355 | retu rn POSTDEC code; | |
1356 | default: | |
1357 | retu rn -1; | |
1358 | } | |
1359 | } | |
1360 | ||
1361 | /** Co nstruct de finition o f an acces s method. | |
1362 | * @p aram pos The source cod e position of the de finition. | |
1363 | * @p aram vsym The private or protected symbol. | |
1364 | * @p aram acces sor The access met hod for th e symbol. | |
1365 | * @p aram acode The access cod e. | |
1366 | */ | |
1367 | JCTree accessDef (int pos, Symbol vsy m, MethodS ymbol acce ssor, int acode) { | |
1368 | // Sy stem.err.p rintln("ac cess " + v sym + " wi th " + acc essor);//D EBUG | |
1369 | cu rrentClass = vsym.ow ner.enclCl ass(); | |
1370 | ma ke.at(pos) ; | |
1371 | JC MethodDecl md = make .MethodDef (accessor, null); | |
1372 | ||
1373 | // Find actu al symbol | |
1374 | Sy mbol sym = actualSym bols.get(v sym); | |
1375 | if (sym == n ull) sym = vsym; | |
1376 | ||
1377 | JC Expression ref; // T he tree re ferencing the privat e symbol. | |
1378 | Li st<JCExpre ssion> arg s; // A ny additio nal argume nts to be passed alo ng. | |
1379 | if ((sym.fla gs() & STA TIC) != 0) { | |
1380 | ref = ma ke.Ident(s ym); | |
1381 | args = m ake.Idents (md.params ); | |
1382 | } else { | |
1383 | JCExpres sion site = make.Ide nt(md.para ms.head); | |
1384 | if (acod e % 2 != 0 ) { | |
1385 | //od d access c odes repre sent quali fied super accesses - need to | |
1386 | //em it referen ce to the direct sup erclass, e ven if the refered | |
1387 | //me mber is fr om an indi rect super class (JLS 13.1) | |
1388 | site .setType(t ypes.erasu re(types.s upertype(v sym.owner. enclClass( ).type))); | |
1389 | } | |
1390 | ref = ma ke.Select( site, sym) ; | |
1391 | args = m ake.Idents (md.params .tail); | |
1392 | } | |
1393 | JC Statement stat; // Th e statemen t accessin g the priv ate symbol . | |
1394 | if (sym.kind == VAR) { | |
1395 | // Norma lize out a ll odd acc ess codes by taking floor modu lo 2: | |
1396 | int acod e1 = acode - (acode & 1); | |
1397 | ||
1398 | JCExpres sion expr; // T he access method's r eturn valu e. | |
1399 | switch ( acode1) { | |
1400 | case DER EFcode: | |
1401 | expr = ref; | |
1402 | brea k; | |
1403 | case ASS IGNcode: | |
1404 | expr = make.As sign(ref, args.head) ; | |
1405 | brea k; | |
1406 | case PRE INCcode: c ase POSTIN Ccode: cas e PREDECco de: case P OSTDECcode : | |
1407 | expr = makeUna ry(mapUnar yOpCodeToT ag(acode1) , ref); | |
1408 | brea k; | |
1409 | default: | |
1410 | expr = make.As signop( | |
1411 | treeTag(bi naryAccess Operator(a code1)), r ef, args.h ead); | |
1412 | ((JC AssignOp) expr).oper ator = bin aryAccessO perator(ac ode1); | |
1413 | } | |
1414 | stat = m ake.Return (expr.setT ype(sym.ty pe)); | |
1415 | } else { | |
1416 | stat = m ake.Call(m ake.App(re f, args)); | |
1417 | } | |
1418 | md .body = ma ke.Block(0 , List.of( stat)); | |
1419 | ||
1420 | // Make sure all param eters, res ult types and thrown exception s | |
1421 | // are acces sible. | |
1422 | fo r (List<JC VariableDe cl> l = md .params; l .nonEmpty( ); l = l.t ail) | |
1423 | l.head.v artype = a ccess(l.he ad.vartype ); | |
1424 | md .restype = access(md .restype); | |
1425 | fo r (List<JC Expression > l = md.t hrown; l.n onEmpty(); l = l.tai l) | |
1426 | l.head = access(l. head); | |
1427 | ||
1428 | re turn md; | |
1429 | } | |
1430 | ||
1431 | /** Co nstruct de finition o f an acces s construc tor. | |
1432 | * @p aram pos The source cod e position of the de finition. | |
1433 | * @p aram const r The private co nstructor. | |
1434 | * @p aram acces sor The access met hod for th e construc tor. | |
1435 | */ | |
1436 | JCTree accessCon structorDe f(int pos, Symbol co nstr, Meth odSymbol a ccessor) { | |
1437 | ma ke.at(pos) ; | |
1438 | JC MethodDecl md = make .MethodDef (accessor, | |
1439 | ac cessor.ext ernalType( types), | |
1440 | nu ll); | |
1441 | JC Ident call ee = make. Ident(name s._this); | |
1442 | ca llee.sym = constr; | |
1443 | ca llee.type = constr.t ype; | |
1444 | md .body = | |
1445 | make.Blo ck(0, List .<JCStatem ent>of( | |
1446 | make .Call( | |
1447 | make.App( | |
1448 | callee , | |
1449 | make.I dents(md.p arams.reve rse().tail .reverse() ))))); | |
1450 | re turn md; | |
1451 | } | |
1452 | ||
1453 | /********* ********** ********** ********** ********** ********** ********** ***** | |
1454 | * Free va riables pr oxies and this$n | |
1455 | ********* ********** ********** ********** ********** ********** ********** ****/ | |
1456 | ||
1457 | /** A scope cont aining all free vari able proxi es for cur rently tra nslated | |
1458 | * cl ass, as we ll as its this$n sym bol (if ne eded). | |
1459 | * Pr oxy scopes are neste d in the s ame way cl asses are. | |
1460 | * In side a con structor, proxies an d any this $n symbol are duplic ated | |
1461 | * in an additi onal inner most scope , where th ey represe nt the con structor | |
1462 | * pa rameters. | |
1463 | */ | |
1464 | Scope proxies; | |
1465 | ||
1466 | /** A scope cont aining all unnamed r esource va riables/sa ved | |
1467 | * ex ception va riables fo r translat ed TWR blo cks | |
1468 | */ | |
1469 | Scope twrVars; | |
1470 | ||
1471 | /** A stack cont aining the this$n fi eld of the currently translate d | |
1472 | * cl asses (if needed) in innermost first ord er. | |
1473 | * In side a con structor, proxies an d any this $n symbol are duplic ated | |
1474 | * in an additi onal inner most scope , where th ey represe nt the con structor | |
1475 | * pa rameters. | |
1476 | */ | |
1477 | List<V arSymbol> outerThisS tack; | |
1478 | ||
1479 | /** Th e name of a free var iable prox y. | |
1480 | */ | |
1481 | Name p roxyName(N ame name) { | |
1482 | re turn names .fromStrin g("val" + target.syn theticName Char() + n ame); | |
1483 | } | |
1484 | ||
1485 | /** Pr oxy defini tions for all free v ariables i n given li st, in rev erse order . | |
1486 | * @p aram pos The source cod e position of the de finition. | |
1487 | * @p aram freev ars The free varia bles. | |
1488 | * @p aram owner The class in w hich the d efinitions go. | |
1489 | */ | |
1490 | List<J CVariableD ecl> freev arDefs(int pos, List <VarSymbol > freevars , Symbol o wner) { | |
1491 | re turn freev arDefs(pos , freevars , owner, 0 ); | |
1492 | } | |
1493 | ||
1494 | List<J CVariableD ecl> freev arDefs(int pos, List <VarSymbol > freevars , Symbol o wner, | |
1495 | long add itionalFla gs) { | |
1496 | lo ng flags = FINAL | S YNTHETIC | additiona lFlags; | |
1497 | if (owner.ki nd == TYP && | |
1498 | target.u sePrivateS yntheticFi elds()) | |
1499 | flags |= PRIVATE; | |
1500 | Li st<JCVaria bleDecl> d efs = List .nil(); | |
1501 | fo r (List<Va rSymbol> l = freevar s; l.nonEm pty(); l = l.tail) { | |
1502 | VarSymbo l v = l.he ad; | |
1503 | VarSymbo l proxy = new VarSym bol( | |
1504 | flag s, proxyNa me(v.name) , v.erasur e(types), owner); | |
1505 | proxies. enter(prox y); | |
1506 | JCVariab leDecl vd = make.at( pos).VarDe f(proxy, n ull); | |
1507 | vd.varty pe = acces s(vd.varty pe); | |
1508 | defs = d efs.prepen d(vd); | |
1509 | } | |
1510 | re turn defs; | |
1511 | } | |
1512 | ||
1513 | /** Th e name of a this$n f ield | |
1514 | * @p aram type The clas s referenc ed by the this$n fie ld | |
1515 | */ | |
1516 | Name o uterThisNa me(Type ty pe, Symbol owner) { | |
1517 | Ty pe t = typ e.getEnclo singType() ; | |
1518 | in t nestingL evel = 0; | |
1519 | wh ile (t.has Tag(CLASS) ) { | |
1520 | t = t.ge tEnclosing Type(); | |
1521 | nestingL evel++; | |
1522 | } | |
1523 | Na me result = names.fr omString(" this" + ta rget.synth eticNameCh ar() + nes tingLevel) ; | |
1524 | wh ile (owner .kind == T YP && ((Cl assSymbol) owner).mem bers().loo kup(result ).scope != null) | |
1525 | result = names.fro mString(re sult.toStr ing() + ta rget.synth eticNameCh ar()); | |
1526 | re turn resul t; | |
1527 | } | |
1528 | ||
1529 | privat e VarSymbo l makeOute rThisVarSy mbol(Symbo l owner, l ong flags) { | |
1530 | if (owner.ki nd == TYP && | |
1531 | target.u sePrivateS yntheticFi elds()) | |
1532 | flags |= PRIVATE; | |
1533 | Ty pe target = types.er asure(owne r.enclClas s().type.g etEnclosin gType()); | |
1534 | Va rSymbol ou terThis = | |
1535 | new VarS ymbol(flag s, outerTh isName(tar get, owner ), target, owner); | |
1536 | ou terThisSta ck = outer ThisStack. prepend(ou terThis); | |
1537 | re turn outer This; | |
1538 | } | |
1539 | ||
1540 | privat e JCVariab leDecl mak eOuterThis VarDecl(in t pos, Var Symbol sym ) { | |
1541 | JC VariableDe cl vd = ma ke.at(pos) .VarDef(sy m, null); | |
1542 | vd .vartype = access(vd .vartype); | |
1543 | re turn vd; | |
1544 | } | |
1545 | ||
1546 | /** De finition f or this$n field. | |
1547 | * @p aram pos The source cod e position of the de finition. | |
1548 | * @p aram owner The method in which the definition goes. | |
1549 | */ | |
1550 | JCVari ableDecl o uterThisDe f(int pos, MethodSym bol owner) { | |
1551 | Cl assSymbol c = owner. enclClass( ); | |
1552 | bo olean isMa ndated = | |
1553 | // Anony mous const ructors | |
1554 | (owner.i sConstruct or() && ow ner.isAnon ymous()) | | | |
1555 | // Const ructors of non-priva te inner m ember clas ses | |
1556 | (owner.i sConstruct or() && c. isInner() && | |
1557 | !c.isPr ivate() && !c.isStat ic()); | |
1558 | lo ng flags = | |
1559 | FINAL | (isMandate d ? MANDAT ED : SYNTH ETIC) | PA RAMETER; | |
1560 | Va rSymbol ou terThis = makeOuterT hisVarSymb ol(owner, flags); | |
1561 | ow ner.extraP arams = ow ner.extraP arams.prep end(outerT his); | |
1562 | re turn makeO uterThisVa rDecl(pos, outerThis ); | |
1563 | } | |
1564 | ||
1565 | /** De finition f or this$n field. | |
1566 | * @p aram pos The source cod e position of the de finition. | |
1567 | * @p aram owner The class in w hich the d efinition goes. | |
1568 | */ | |
1569 | JCVari ableDecl o uterThisDe f(int pos, ClassSymb ol owner) { | |
1570 | Va rSymbol ou terThis = makeOuterT hisVarSymb ol(owner, FINAL | SY NTHETIC); | |
1571 | re turn makeO uterThisVa rDecl(pos, outerThis ); | |
1572 | } | |
1573 | ||
1574 | /** Re turn a lis t of trees that load the free variables in given l ist, | |
1575 | * in reverse o rder. | |
1576 | * @p aram pos Th e source c ode positi on to be u sed for th e trees. | |
1577 | * @p aram freev ars Th e list of free varia bles. | |
1578 | */ | |
1579 | List<J CExpressio n> loadFre evars(Diag nosticPosi tion pos, List<VarSy mbol> free vars) { | |
1580 | Li st<JCExpre ssion> arg s = List.n il(); | |
1581 | fo r (List<Va rSymbol> l = freevar s; l.nonEm pty(); l = l.tail) | |
1582 | args = a rgs.prepen d(loadFree var(pos, l .head)); | |
1583 | re turn args; | |
1584 | } | |
1585 | //where | |
1586 | JC Expression loadFreev ar(Diagnos ticPositio n pos, Var Symbol v) { | |
1587 | return a ccess(v, m ake.at(pos ).Ident(v) , null, fa lse); | |
1588 | } | |
1589 | ||
1590 | /** Co nstruct a tree simul ating the expression {@code C. this}. | |
1591 | * @p aram pos T he source code posit ion to be used for t he tree. | |
1592 | * @p aram c T he qualifi er class. | |
1593 | */ | |
1594 | JCExpr ession mak eThis(Diag nosticPosi tion pos, TypeSymbol c) { | |
1595 | if (currentC lass == c) { | |
1596 | // in th is case, ` this' work s fine | |
1597 | return m ake.at(pos ).This(c.e rasure(typ es)); | |
1598 | } else { | |
1599 | // need to go via this$n | |
1600 | return m akeOuterTh is(pos, c) ; | |
1601 | } | |
1602 | } | |
1603 | ||
1604 | /** | |
1605 | * Opt ionally re place a tr y statemen t with the desugarin g of a | |
1606 | * try -with-reso urces stat ement. Th e canonica l desugari ng of | |
1607 | * | |
1608 | * try ResourceS pecificati on | |
1609 | * B lock | |
1610 | * | |
1611 | * is | |
1612 | * | |
1613 | * { | |
1614 | * f inal Varia bleModifie rs_minus_f inal R #re source = E xpression; | |
1615 | * T hrowable # primaryExc eption = n ull; | |
1616 | * | |
1617 | * t ry Resourc eSpecifica tiontail | |
1618 | * Block | |
1619 | * c atch (Thro wable #t) { | |
1620 | * #primaryE xception = t; | |
1621 | * throw #t; | |
1622 | * } finally { | |
1623 | * if (#reso urce != nu ll) { | |
1624 | * if (#pr imaryExcep tion != nu ll) { | |
1625 | * try { | |
1626 | * #re source.clo se(); | |
1627 | * } cat ch(Throwab le #suppre ssedExcept ion) { | |
1628 | * #pr imaryExcep tion.addSu ppressed(# suppressed Exception) ; | |
1629 | * } | |
1630 | * } else { | |
1631 | * #reso urce.close (); | |
1632 | * } | |
1633 | * } | |
1634 | * } | |
1635 | * | |
1636 | * @pa ram tree The try st atement to inspect. | |
1637 | * @re turn A a d esugared t ry-with-re sources tr ee, or the original | |
1638 | * try block if there are no resourc es to mana ge. | |
1639 | */ | |
1640 | JCTree makeTwrTr y(JCTry tr ee) { | |
1641 | ma ke_at(tree .pos()); | |
1642 | tw rVars = tw rVars.dup( ); | |
1643 | JC Block twrB lock = mak eTwrBlock( tree.resou rces, tree .body, | |
1644 | tree .finallyCa nCompleteN ormally, 0 ); | |
1645 | if (tree.cat chers.isEm pty() && t ree.finali zer == nul l) | |
1646 | result = translate (twrBlock) ; | |
1647 | el se | |
1648 | result = translate (make.Try( twrBlock, tree.catch ers, tree. finalizer) ); | |
1649 | tw rVars = tw rVars.leav e(); | |
1650 | re turn resul t; | |
1651 | } | |
1652 | ||
1653 | privat e JCBlock makeTwrBlo ck(List<JC Tree> reso urces, JCB lock block , | |
1654 | boolean finallyCan CompleteNo rmally, in t depth) { | |
1655 | if (resource s.isEmpty( )) | |
1656 | return b lock; | |
1657 | ||
1658 | // Add resou rce declar ation or e xpression to block s tatements | |
1659 | Li stBuffer<J CStatement > stats = new ListBu ffer<JCSta tement>(); | |
1660 | JC Tree resou rce = reso urces.head ; | |
1661 | JC Expression expr = nu ll; | |
1662 | if (resource instanceo f JCVariab leDecl) { | |
1663 | JCVariab leDecl var = (JCVari ableDecl) resource; | |
1664 | expr = m ake.Ident( var.sym).s etType(res ource.type ); | |
1665 | stats.ad d(var); | |
1666 | } else { | |
1667 | Assert.c heck(resou rce instan ceof JCExp ression); | |
1668 | VarSymbo l syntheti cTwrVar = | |
1669 | new VarS ymbol(SYNT HETIC | FI NAL, | |
1670 | make SyntheticN ame(names. fromString ("twrVar" + | |
1671 | depth), twrVars), | |
1672 | (res ource.type .hasTag(BO T)) ? | |
1673 | syms .autoClose ableType : resource. type, | |
1674 | curr entMethodS ym); | |
1675 | twrVars. enter(synt heticTwrVa r); | |
1676 | JCVariab leDecl syn theticTwrV arDecl = | |
1677 | make .VarDef(sy ntheticTwr Var, (JCEx pression)r esource); | |
1678 | expr = ( JCExpressi on)make.Id ent(synthe ticTwrVar) ; | |
1679 | stats.ad d(syntheti cTwrVarDec l); | |
1680 | } | |
1681 | ||
1682 | // Add prima ryExceptio n declarat ion | |
1683 | Va rSymbol pr imaryExcep tion = | |
1684 | new VarS ymbol(SYNT HETIC, | |
1685 | make SyntheticN ame(names. fromString ("primaryE xception" + | |
1686 | dept h), twrVar s), | |
1687 | syms .throwable Type, | |
1688 | curr entMethodS ym); | |
1689 | tw rVars.ente r(primaryE xception); | |
1690 | JC VariableDe cl primary ExceptionT reeDecl = make.VarDe f(primaryE xception, makeNull() ); | |
1691 | st ats.add(pr imaryExcep tionTreeDe cl); | |
1692 | ||
1693 | // Create ca tch clause that save s exceptio n and then rethrows it | |
1694 | Va rSymbol pa ram = | |
1695 | new VarS ymbol(FINA L|SYNTHETI C, | |
1696 | name s.fromStri ng("t" + | |
1697 | target. syntheticN ameChar()) , | |
1698 | syms .throwable Type, | |
1699 | curr entMethodS ym); | |
1700 | JC VariableDe cl paramTr ee = make. VarDef(par am, null); | |
1701 | JC Statement assign = m ake.Assign ment(prima ryExceptio n, make.Id ent(param) ); | |
1702 | JC Statement rethrowSta t = make.T hrow(make. Ident(para m)); | |
1703 | JC Block catc hBlock = m ake.Block( 0L, List.< JCStatemen t>of(assig n, rethrow Stat)); | |
1704 | JC Catch catc hClause = make.Catch (paramTree , catchBlo ck); | |
1705 | ||
1706 | in t oldPos = make.pos; | |
1707 | ma ke.at(Tree Info.endPo s(block)); | |
1708 | JC Block fina llyClause = makeTwrF inallyClau se(primary Exception, expr); | |
1709 | ma ke.at(oldP os); | |
1710 | JC Try outerT ry = make. Try(makeTw rBlock(res ources.tai l, block, | |
1711 | fina llyCanComp leteNormal ly, depth + 1), | |
1712 | List.< JCCatch>of (catchClau se), | |
1713 | finall yClause); | |
1714 | ou terTry.fin allyCanCom pleteNorma lly = fina llyCanComp leteNormal ly; | |
1715 | st ats.add(ou terTry); | |
1716 | JC Block newB lock = mak e.Block(0L , stats.to List()); | |
1717 | re turn newBl ock; | |
1718 | } | |
1719 | ||
1720 | privat e JCBlock makeTwrFin allyClause (Symbol pr imaryExcep tion, JCEx pression r esource) { | |
1721 | // primaryEx ception.ad dSuppresse d(catchExc eption); | |
1722 | Va rSymbol ca tchExcepti on = | |
1723 | new VarS ymbol(SYNT HETIC, mak e.paramNam e(2), | |
1724 | syms .throwable Type, | |
1725 | curr entMethodS ym); | |
1726 | JC Statement addSuppres sionStatem ent = | |
1727 | make.Exe c(makeCall (make.Iden t(primaryE xception), | |
1728 | names.add Suppressed , | |
1729 | List.<JCE xpression> of(make.Id ent(catchE xception)) )); | |
1730 | ||
1731 | // try { res ource.clos e(); } cat ch (e) { p rimaryExce ption.addS uppressed( e); } | |
1732 | JC Block tryB lock = | |
1733 | make.Blo ck(0L, Lis t.<JCState ment>of(ma keResource CloseInvoc ation(reso urce))); | |
1734 | JC VariableDe cl catchEx ceptionDec l = make.V arDef(catc hException , null); | |
1735 | JC Block catc hBlock = m ake.Block( 0L, List.< JCStatemen t>of(addSu ppressionS tatement)) ; | |
1736 | Li st<JCCatch > catchCla uses = Lis t.<JCCatch >of(make.C atch(catch ExceptionD ecl, catch Block)); | |
1737 | JC Try tryTre e = make.T ry(tryBloc k, catchCl auses, nul l); | |
1738 | tr yTree.fina llyCanComp leteNormal ly = true; | |
1739 | ||
1740 | // if (prima ryExceptio n != null) {try...} else resou rceClose; | |
1741 | JC If closeIf Statement = make.If( makeNonNul lCheck(mak e.Ident(pr imaryExcep tion)), | |
1742 | tryTree, | |
1743 | makeResour ceCloseInv ocation(re source)); | |
1744 | ||
1745 | // if (#reso urce != nu ll) { if ( primaryExc eption ... } | |
1746 | re turn make. Block(0L, | |
1747 | List .<JCStatem ent>of(mak e.If(makeN onNullChec k(resource ), | |
1748 | close IfStatemen t, | |
1749 | null) )); | |
1750 | } | |
1751 | ||
1752 | privat e JCStatem ent makeRe sourceClos eInvocatio n(JCExpres sion resou rce) { | |
1753 | // convert t o AutoClos eable if n eeded | |
1754 | if (types.as Super(reso urce.type, syms.auto CloseableT ype.tsym) == null) { | |
1755 | resource = (JCExpr ession) co nvert(reso urce, syms .autoClose ableType); | |
1756 | } | |
1757 | ||
1758 | // create re source.clo se() metho d invocati on | |
1759 | JC Expression resourceC lose = mak eCall(reso urce, | |
1760 | name s.close, | |
1761 | List .<JCExpres sion>nil() ); | |
1762 | re turn make. Exec(resou rceClose); | |
1763 | } | |
1764 | ||
1765 | privat e JCExpres sion makeN onNullChec k(JCExpres sion expre ssion) { | |
1766 | re turn makeB inary(NE, expression , makeNull ()); | |
1767 | } | |
1768 | ||
1769 | /** Co nstruct a tree that represents the outer instance | |
1770 | * {@ code C.thi s}. Never pick the c urrent `th is'. | |
1771 | * @p aram pos T he source code posit ion to be used for t he tree. | |
1772 | * @p aram c T he qualifi er class. | |
1773 | */ | |
1774 | JCExpr ession mak eOuterThis (Diagnosti cPosition pos, TypeS ymbol c) { | |
1775 | Li st<VarSymb ol> ots = outerThisS tack; | |
1776 | if (ots.isEm pty()) { | |
1777 | log.erro r(pos, "no .encl.inst ance.of.ty pe.in.scop e", c); | |
1778 | Assert.e rror(); | |
1779 | return m akeNull(); | |
1780 | } | |
1781 | Va rSymbol ot = ots.hea d; | |
1782 | JC Expression tree = ac cess(make. at(pos).Id ent(ot)); | |
1783 | Ty peSymbol o tc = ot.ty pe.tsym; | |
1784 | wh ile (otc ! = c) { | |
1785 | do { | |
1786 | ots = ots.tail ; | |
1787 | if ( ots.isEmpt y()) { | |
1788 | log.error( pos, | |
1789 | "no.encl.i nstance.of .type.in.s cope", | |
1790 | c); | |
1791 | Assert.err or(); // s hould have been caug ht in Attr | |
1792 | return tre e; | |
1793 | } | |
1794 | ot = ots.head; | |
1795 | } while (ot.owner != otc); | |
1796 | if (otc. owner.kind != PCK && !otc.hasO uterInstan ce()) { | |
1797 | chk. earlyRefEr ror(pos, c ); | |
1798 | Asse rt.error() ; // shoul d have bee n caught i n Attr | |
1799 | retu rn makeNul l(); | |
1800 | } | |
1801 | tree = a ccess(make .at(pos).S elect(tree , ot)); | |
1802 | otc = ot .type.tsym ; | |
1803 | } | |
1804 | re turn tree; | |
1805 | } | |
1806 | ||
1807 | /** Co nstruct a tree that represents the close st outer i nstance | |
1808 | * {@ code C.thi s} such th at the giv en symbol is a membe r of C. | |
1809 | * @p aram pos T he source code posit ion to be used for t he tree. | |
1810 | * @p aram sym T he accesse d symbol. | |
1811 | * @p aram preci seMatch s hould we a ccept a ty pe that is a subtype of | |
1812 | * s ym's owner , even if it doesn't contain s ym | |
1813 | * d ue to hidi ng, overri ding, or n on-inherit ance | |
1814 | * d ue to prot ection? | |
1815 | */ | |
1816 | JCExpr ession mak eOwnerThis (Diagnosti cPosition pos, Symbo l sym, boo lean preci seMatch) { | |
1817 | Sy mbol c = s ym.owner; | |
1818 | if (preciseM atch ? sym .isMemberO f(currentC lass, type s) | |
1819 | : cur rentClass. isSubClass (sym.owner , types)) { | |
1820 | // in th is case, ` this' work s fine | |
1821 | return m ake.at(pos ).This(c.e rasure(typ es)); | |
1822 | } else { | |
1823 | // need to go via this$n | |
1824 | return m akeOwnerTh isN(pos, s ym, precis eMatch); | |
1825 | } | |
1826 | } | |
1827 | ||
1828 | /** | |
1829 | * Sim ilar to ma keOwnerThi s but will never pic k "this". | |
1830 | */ | |
1831 | JCExpr ession mak eOwnerThis N(Diagnost icPosition pos, Symb ol sym, bo olean prec iseMatch) { | |
1832 | Sy mbol c = s ym.owner; | |
1833 | Li st<VarSymb ol> ots = outerThisS tack; | |
1834 | if (ots.isEm pty()) { | |
1835 | log.erro r(pos, "no .encl.inst ance.of.ty pe.in.scop e", c); | |
1836 | Assert.e rror(); | |
1837 | return m akeNull(); | |
1838 | } | |
1839 | Va rSymbol ot = ots.hea d; | |
1840 | JC Expression tree = ac cess(make. at(pos).Id ent(ot)); | |
1841 | Ty peSymbol o tc = ot.ty pe.tsym; | |
1842 | wh ile (!(pre ciseMatch ? sym.isMe mberOf(otc , types) : otc.isSub Class(sym. owner, typ es))) { | |
1843 | do { | |
1844 | ots = ots.tail ; | |
1845 | if ( ots.isEmpt y()) { | |
1846 | log.error( pos, | |
1847 | "no.en cl.instanc e.of.type. in.scope", | |
1848 | c); | |
1849 | Assert.err or(); | |
1850 | return tre e; | |
1851 | } | |
1852 | ot = ots.head; | |
1853 | } while (ot.owner != otc); | |
1854 | tree = a ccess(make .at(pos).S elect(tree , ot)); | |
1855 | otc = ot .type.tsym ; | |
1856 | } | |
1857 | re turn tree; | |
1858 | } | |
1859 | ||
1860 | /** Re turn tree simulating the assig nment {@co de this.na me = name} , where | |
1861 | * na me is the name of a free varia ble. | |
1862 | */ | |
1863 | JCStat ement init Field(int pos, Name name) { | |
1864 | Sc ope.Entry e = proxie s.lookup(n ame); | |
1865 | Sy mbol rhs = e.sym; | |
1866 | As sert.check (rhs.owner .kind == M TH); | |
1867 | Sy mbol lhs = e.next(). sym; | |
1868 | As sert.check (rhs.owner .owner == lhs.owner) ; | |
1869 | ma ke.at(pos) ; | |
1870 | re turn | |
1871 | make.Exe c( | |
1872 | make .Assign( | |
1873 | make.Selec t(make.Thi s(lhs.owne r.erasure( types)), l hs), | |
1874 | make.Ident (rhs)).set Type(lhs.e rasure(typ es))); | |
1875 | } | |
1876 | ||
1877 | /** Re turn tree simulating the assig nment {@co de this.th is$n = thi s$n}. | |
1878 | */ | |
1879 | JCStat ement init OuterThis( int pos) { | |
1880 | Va rSymbol rh s = outerT hisStack.h ead; | |
1881 | As sert.check (rhs.owner .kind == M TH); | |
1882 | Va rSymbol lh s = outerT hisStack.t ail.head; | |
1883 | As sert.check (rhs.owner .owner == lhs.owner) ; | |
1884 | ma ke.at(pos) ; | |
1885 | re turn | |
1886 | make.Exe c( | |
1887 | make .Assign( | |
1888 | make.Selec t(make.Thi s(lhs.owne r.erasure( types)), l hs), | |
1889 | make.Ident (rhs)).set Type(lhs.e rasure(typ es))); | |
1890 | } | |
1891 | ||
1892 | /********* ********** ********** ********** ********** ********** ********** ***** | |
1893 | * Code fo r .class | |
1894 | ********* ********** ********** ********** ********** ********** ********** ****/ | |
1895 | ||
1896 | /** Re turn the s ymbol of a class to contain a cache of | |
1897 | * co mpiler-gen erated sta tics such as class$ and the | |
1898 | * $a ssertionsD isabled fl ag. We cr eate an an onymous ne sted class | |
1899 | * (u nless one already ex ists) and return its symbol. However, | |
1900 | * fo r backward compatibi lity in 1. 4 and earl ier we use the | |
1901 | * to p-level cl ass itself . | |
1902 | */ | |
1903 | privat e ClassSym bol outerC acheClass( ) { | |
1904 | Cl assSymbol clazz = ou termostCla ssDef.sym; | |
1905 | if ((clazz.f lags() & I NTERFACE) == 0 && | |
1906 | !target. useInnerCa cheClass() ) return c lazz; | |
1907 | Sc ope s = cl azz.member s(); | |
1908 | fo r (Scope.E ntry e = s .elems; e != null; e = e.sibli ng) | |
1909 | if (e.sy m.kind == TYP && | |
1910 | e.sy m.name == names.empt y && | |
1911 | (e.s ym.flags() & INTERFA CE) == 0) return (Cl assSymbol) e.sym; | |
1912 | re turn makeE mptyClass( STATIC | S YNTHETIC, clazz).sym ; | |
1913 | } | |
1914 | ||
1915 | /** Re turn symbo l for "cla ss$" metho d. If ther e is no me thod defin ition | |
1916 | * fo r class$, construct one as fol lows: | |
1917 | * | |
1918 | * class clas s$(String x0) { | |
1919 | * try { | |
1920 | * return Class.for Name(x0); | |
1921 | * } catch (ClassNotF oundExcept ion x1) { | |
1922 | * throw new NoClas sDefFoundE rror(x1.ge tMessage() ); | |
1923 | * } | |
1924 | * } | |
1925 | */ | |
1926 | privat e MethodSy mbol class DollarSym( Diagnostic Position p os) { | |
1927 | Cl assSymbol outerCache Class = ou terCacheCl ass(); | |
1928 | Me thodSymbol classDoll arSym = | |
1929 | (MethodS ymbol)look upSyntheti c(classDol lar, | |
1930 | outerCac heClass.me mbers()); | |
1931 | if (classDol larSym == null) { | |
1932 | classDol larSym = n ew MethodS ymbol( | |
1933 | STAT IC | SYNTH ETIC, | |
1934 | clas sDollar, | |
1935 | new MethodType ( | |
1936 | List.of(sy ms.stringT ype), | |
1937 | types.eras ure(syms.c lassType), | |
1938 | List.<Type >nil(), | |
1939 | syms.metho dClass), | |
1940 | oute rCacheClas s); | |
1941 | enterSyn thetic(pos , classDol larSym, ou terCacheCl ass.member s()); | |
1942 | ||
1943 | JCMethod Decl md = make.Metho dDef(class DollarSym, null); | |
1944 | try { | |
1945 | md.b ody = clas sDollarSym Body(pos, md); | |
1946 | } catch (Completio nFailure e x) { | |
1947 | md.b ody = make .Block(0, List.<JCSt atement>ni l()); | |
1948 | chk. completion Error(pos, ex); | |
1949 | } | |
1950 | JCClassD ecl outerC acheClassD ef = class Def(outerC acheClass) ; | |
1951 | outerCac heClassDef .defs = ou terCacheCl assDef.def s.prepend( md); | |
1952 | } | |
1953 | re turn class DollarSym; | |
1954 | } | |
1955 | ||
1956 | /** Ge nerate cod e for clas s$(String name). */ | |
1957 | JCBloc k classDol larSymBody (Diagnosti cPosition pos, JCMet hodDecl md ) { | |
1958 | Me thodSymbol classDoll arSym = md .sym; | |
1959 | Cl assSymbol outerCache Class = (C lassSymbol )classDoll arSym.owne r; | |
1960 | ||
1961 | JC Block retu rnResult; | |
1962 | ||
1963 | // in 1.4.2 and above, we use | |
1964 | // Class.for Name(Strin g name, bo olean init , ClassLoa der loader ); | |
1965 | // which req uires we c ache the c urrent loa der in cl$ | |
1966 | if (target.c lassLitera lsNoInit() ) { | |
1967 | // clsym = "privat e static C lassLoader cl$" | |
1968 | VarSymbo l clsym = new VarSym bol(STATIC |SYNTHETIC , | |
1969 | names. fromString ("cl" + ta rget.synth eticNameCh ar()), | |
1970 | syms.c lassLoader Type, | |
1971 | outerC acheClass) ; | |
1972 | enterSyn thetic(pos , clsym, o uterCacheC lass.membe rs()); | |
1973 | ||
1974 | // emit "private s tatic Clas sLoader cl $;" | |
1975 | JCVariab leDecl cld ef = make. VarDef(cls ym, null); | |
1976 | JCClassD ecl outerC acheClassD ef = class Def(outerC acheClass) ; | |
1977 | outerCac heClassDef .defs = ou terCacheCl assDef.def s.prepend( cldef); | |
1978 | ||
1979 | // newca che := "ne w cache$1[ 0]" | |
1980 | JCNewArr ay newcach e = make. | |
1981 | NewA rray(make. Type(outer CacheClass .type), | |
1982 | List. <JCExpress ion>of(mak e.Literal( INT, 0).se tType(syms .intType)) , | |
1983 | null) ; | |
1984 | newcache .type = ne w ArrayTyp e(types.er asure(oute rCacheClas s.type), | |
1985 | syms.arr ayClass); | |
1986 | ||
1987 | // forNa meSym := j ava.lang.C lass.forNa me( | |
1988 | // S tring s,bo olean init ,ClassLoad er loader) | |
1989 | Symbol f orNameSym = lookupMe thod(make_ pos, names .forName, | |
1990 | types .erasure(s yms.classT ype), | |
1991 | List. of(syms.st ringType, | |
1992 | syms.bo oleanType, | |
1993 | syms.cl assLoaderT ype)); | |
1994 | // clval ue := "(cl $ == null) ? | |
1995 | // $newc ache.getCl ass().getC omponentTy pe().getCl assLoader( ) : cl$" | |
1996 | JCExpres sion clval ue = | |
1997 | make .Condition al( | |
1998 | makeBinary (EQ, make. Ident(clsy m), makeNu ll()), | |
1999 | make.Assig n( | |
2000 | make.I dent(clsym ), | |
2001 | makeCa ll( | |
2002 | ma keCall(mak eCall(newc ache, | |
2003 | name s.getClass , | |
2004 | List .<JCExpres sion>nil() ), | |
2005 | nam es.getComp onentType, | |
2006 | Lis t.<JCExpre ssion>nil( )), | |
2007 | na mes.getCla ssLoader, | |
2008 | Li st.<JCExpr ession>nil ())).setTy pe(syms.cl assLoaderT ype), | |
2009 | make.Ident (clsym)).s etType(sym s.classLoa derType); | |
2010 | ||
2011 | // retur nResult := "{ return Class.for Name(param 1, false, cl$); }" | |
2012 | List<JCE xpression> args = Li st.of(make .Ident(md. params.hea d.sym), | |
2013 | make Lit(syms.b ooleanType , 0), | |
2014 | clva lue); | |
2015 | returnRe sult = mak e. | |
2016 | Bloc k(0, List. <JCStateme nt>of(make . | |
2017 | Call(make. // return | |
2018 | App(m ake. | |
2019 | I dent(forNa meSym), ar gs)))); | |
2020 | } else { | |
2021 | // forNa meSym := j ava.lang.C lass.forNa me(String s) | |
2022 | Symbol f orNameSym = lookupMe thod(make_ pos, | |
2023 | names .forName, | |
2024 | types .erasure(s yms.classT ype), | |
2025 | List. of(syms.st ringType)) ; | |
2026 | // retur nResult := "{ return Class.for Name(param 1); }" | |
2027 | returnRe sult = mak e. | |
2028 | Bloc k(0, List. of(make. | |
2029 | Call (make. // return | |
2030 | App(make. | |
2031 | QualId ent(forNam eSym), | |
2032 | List.< JCExpressi on>of(make . | |
2033 | Iden t(md.param s. | |
2034 | head.sym )))))); | |
2035 | } | |
2036 | ||
2037 | // catchPara m := Class NotFoundEx ception e1 | |
2038 | Va rSymbol ca tchParam = | |
2039 | new VarS ymbol(SYNT HETIC, mak e.paramNam e(1), | |
2040 | syms .classNotF oundExcept ionType, | |
2041 | clas sDollarSym ); | |
2042 | ||
2043 | JC Statement rethrow; | |
2044 | if (target.h asInitCaus e()) { | |
2045 | // rethr ow = "thro w new NoCl assDefFoun dError().i nitCause(e ); | |
2046 | JCExpres sion throw Expr = | |
2047 | make Call(makeN ewClass(sy ms.noClass DefFoundEr rorType, | |
2048 | Li st.<JCExpr ession>nil ()), | |
2049 | names .initCause , | |
2050 | List. <JCExpress ion>of(mak e.Ident(ca tchParam)) ); | |
2051 | rethrow = make.Thr ow(throwEx pr); | |
2052 | } else { | |
2053 | // getMe ssageSym : = ClassNot FoundExcep tion.getMe ssage() | |
2054 | Symbol g etMessageS ym = looku pMethod(ma ke_pos, | |
2055 | na mes.getMes sage, | |
2056 | sy ms.classNo tFoundExce ptionType, | |
2057 | Li st.<Type>n il()); | |
2058 | // rethr ow = "thro w new NoCl assDefFoun dError(e.g etMessage( ));" | |
2059 | rethrow = make. | |
2060 | Thro w(makeNewC lass(syms. noClassDef FoundError Type, | |
2061 | List .<JCExpres sion>of(ma ke.App(mak e.Select(m ake.Ident( catchParam ), | |
2062 | g etMessageS ym), | |
2063 | Lis t.<JCExpre ssion>nil( ))))); | |
2064 | } | |
2065 | ||
2066 | // rethrowSt mt := "( $ rethrow )" | |
2067 | JC Block reth rowStmt = make.Block (0, List.o f(rethrow) ); | |
2068 | ||
2069 | // catchBloc k := "catc h ($catchP aram) $ret hrowStmt" | |
2070 | JC Catch catc hBlock = m ake.Catch( make.VarDe f(catchPar am, null), | |
2071 | re throwStmt) ; | |
2072 | ||
2073 | // tryCatch := "try $r eturnResul t $catchBl ock" | |
2074 | JC Statement tryCatch = make.Try( returnResu lt, | |
2075 | List.of(ca tchBlock), null); | |
2076 | ||
2077 | re turn make. Block(0, L ist.of(try Catch)); | |
2078 | } | |
2079 | // whe re | |
2080 | /* * Create a n attribut ed tree of the form left.name( ). */ | |
2081 | pr ivate JCMe thodInvoca tion makeC all(JCExpr ession lef t, Name na me, List<J CExpressio n> args) { | |
2082 | Assert.c heckNonNul l(left.typ e); | |
2083 | Symbol f uncsym = l ookupMetho d(make_pos , name, le ft.type, | |
2084 | TreeInfo .types(arg s)); | |
2085 | return m ake.App(ma ke.Select( left, func sym), args ); | |
2086 | } | |
2087 | ||
2088 | /** Th e Name Of The variab le to cach e T.class values. | |
2089 | * @p aram sig The si gnature of type T. | |
2090 | */ | |
2091 | privat e Name cac heName(Str ing sig) { | |
2092 | St ringBuilde r buf = ne w StringBu ilder(); | |
2093 | if (sig.star tsWith("[" )) { | |
2094 | buf = bu f.append(" array"); | |
2095 | while (s ig.startsW ith("[")) { | |
2096 | buf = buf.appe nd(target. syntheticN ameChar()) ; | |
2097 | sig = sig.subs tring(1); | |
2098 | } | |
2099 | if (sig. startsWith ("L")) { | |
2100 | sig = sig.subs tring(0, s ig.length( ) - 1); | |
2101 | } | |
2102 | } else { | |
2103 | buf = bu f.append(" class" + t arget.synt heticNameC har()); | |
2104 | } | |
2105 | bu f = buf.ap pend(sig.r eplace('.' , target.s yntheticNa meChar())) ; | |
2106 | re turn names .fromStrin g(buf.toSt ring()); | |
2107 | } | |
2108 | ||
2109 | /** Th e variable symbol th at caches T.class va lues. | |
2110 | * If none exis ts yet, cr eate a def inition. | |
2111 | * @p aram sig The si gnature of type T. | |
2112 | * @p aram pos The po sition to report dia gnostics, if any. | |
2113 | */ | |
2114 | privat e VarSymbo l cacheSym (Diagnosti cPosition pos, Strin g sig) { | |
2115 | Cl assSymbol outerCache Class = ou terCacheCl ass(); | |
2116 | Na me cname = cacheName (sig); | |
2117 | Va rSymbol ca cheSym = | |
2118 | (VarSymb ol)lookupS ynthetic(c name, oute rCacheClas s.members( )); | |
2119 | if (cacheSym == null) { | |
2120 | cacheSym = new Var Symbol( | |
2121 | STAT IC | SYNTH ETIC, cnam e, types.e rasure(sym s.classTyp e), outerC acheClass) ; | |
2122 | enterSyn thetic(pos , cacheSym , outerCac heClass.me mbers()); | |
2123 | ||
2124 | JCVariab leDecl cac heDef = ma ke.VarDef( cacheSym, null); | |
2125 | JCClassD ecl outerC acheClassD ef = class Def(outerC acheClass) ; | |
2126 | outerCac heClassDef .defs = ou terCacheCl assDef.def s.prepend( cacheDef); | |
2127 | } | |
2128 | re turn cache Sym; | |
2129 | } | |
2130 | ||
2131 | /** Th e tree sim ulating a T.class ex pression. | |
2132 | * @p aram clazz The tree ident ifying typ e T. | |
2133 | */ | |
2134 | privat e JCExpres sion class Of(JCTree clazz) { | |
2135 | re turn class OfType(cla zz.type, c lazz.pos() ); | |
2136 | } | |
2137 | ||
2138 | privat e JCExpres sion class OfType(Typ e type, Di agnosticPo sition pos ) { | |
2139 | sw itch (type .getTag()) { | |
2140 | ca se BYTE: c ase SHORT: case CHAR : case INT : case LON G: case FL OAT: | |
2141 | ca se DOUBLE: case BOOL EAN: case VOID: | |
2142 | // repla ce with <B oxedClass> .TYPE | |
2143 | ClassSym bol c = ty pes.boxedC lass(type) ; | |
2144 | Symbol t ypeSym = | |
2145 | rs.a ccessBase( | |
2146 | rs.findIde ntInType(a ttrEnv, c. type, name s.TYPE, VA R), | |
2147 | pos, c.typ e, names.T YPE, true) ; | |
2148 | if (type Sym.kind = = VAR) | |
2149 | ((Va rSymbol)ty peSym).get ConstValue (); // ens ure initia lizer is e valuated | |
2150 | return m ake.QualId ent(typeSy m); | |
2151 | ca se CLASS: case ARRAY : | |
2152 | if (targ et.hasClas sLiterals( )) { | |
2153 | VarS ymbol sym = new VarS ymbol( | |
2154 | STATIC | PUBLIC | FINAL, n ames._clas s, | |
2155 | syms.c lassType, type.tsym) ; | |
2156 | retu rn make_at (pos).Sele ct(make.Ty pe(type), sym); | |
2157 | } | |
2158 | // repla ce with <c ache == nu ll ? cache = class$( tsig) : ca che> | |
2159 | // where | |
2160 | // - <t sig> is t he type si gnature of T, | |
2161 | // - <c ache> is t he cache v ariable fo r tsig. | |
2162 | String s ig = | |
2163 | writ er.xClassN ame(type). toString() .replace(' /', '.'); | |
2164 | Symbol c s = cacheS ym(pos, si g); | |
2165 | return m ake_at(pos ).Conditio nal( | |
2166 | make Binary(EQ, make.Iden t(cs), mak eNull()), | |
2167 | make .Assign( | |
2168 | make.Ident (cs), | |
2169 | make.App( | |
2170 | make.I dent(class DollarSym( pos)), | |
2171 | List.< JCExpressi on>of(make .Literal(C LASS, sig) | |
2172 | .set Type(syms. stringType )))) | |
2173 | .set Type(types .erasure(s yms.classT ype)), | |
2174 | make .Ident(cs) ).setType( types.eras ure(syms.c lassType)) ; | |
2175 | de fault: | |
2176 | throw ne w Assertio nError(); | |
2177 | } | |
2178 | } | |
2179 | ||
2180 | /********* ********** ********** ********** ********** ********** ********** ***** | |
2181 | * Code fo r enabling /disabling assertion s. | |
2182 | ********* ********** ********** ********** ********** ********** ********** ****/ | |
2183 | ||
2184 | privat e ClassSym bol assert ionsDisabl edClassCac he; | |
2185 | ||
2186 | /**Use d to creat e an auxil iary class to hold $ assertions Disabled f or interfa ces. | |
2187 | */ | |
2188 | privat e ClassSym bol assert ionsDisabl edClass() { | |
2189 | if (assertio nsDisabled ClassCache != null) return ass ertionsDis abledClass Cache; | |
2190 | ||
2191 | as sertionsDi sabledClas sCache = m akeEmptyCl ass(STATIC | SYNTHET IC, outerm ostClassDe f.sym).sym ; | |
2192 | ||
2193 | re turn asser tionsDisab ledClassCa che; | |
2194 | } | |
2195 | ||
2196 | // Thi s code is not partic ularly rob ust if the user has | |
2197 | // pre viously de clared a m ember name d '$assert ionsDisabl ed'. | |
2198 | // The same faul ty idiom a lso appear s in the t ranslation of | |
2199 | // cla ss literal s above. We should report an error if a | |
2200 | // pre vious decl aration is not synth etic. | |
2201 | ||
2202 | privat e JCExpres sion asser tFlagTest( Diagnostic Position p os) { | |
2203 | // Outermost class may be either true clas s or an in terface. | |
2204 | Cl assSymbol outermostC lass = out ermostClas sDef.sym; | |
2205 | ||
2206 | // only class es can hol d a non-pu blic field , look for a usable one: | |
2207 | Cl assSymbol container = !current Class.isIn terface() ? currentC lass : | |
2208 | asse rtionsDisa bledClass( ); | |
2209 | ||
2210 | Va rSymbol as sertDisabl edSym = | |
2211 | (VarSymb ol)lookupS ynthetic(d ollarAsser tionsDisab led, | |
2212 | c ontainer.m embers()); | |
2213 | if (assertDi sabledSym == null) { | |
2214 | assertDi sabledSym = | |
2215 | new VarSymbol( STATIC | F INAL | SYN THETIC, | |
2216 | dollarAsse rtionsDisa bled, | |
2217 | syms.boole anType, | |
2218 | container) ; | |
2219 | enterSyn thetic(pos , assertDi sabledSym, container .members() ); | |
2220 | Symbol d esiredAsse rtionStatu sSym = loo kupMethod( pos, | |
2221 | names.desi redAsserti onStatus, | |
2222 | types.eras ure(syms.c lassType), | |
2223 | List.<Type >nil()); | |
2224 | JCClassD ecl contai nerDef = c lassDef(co ntainer); | |
2225 | make_at( containerD ef.pos()); | |
2226 | JCExpres sion notSt atus = mak eUnary(NOT , make.App (make.Sele ct( | |
2227 | classOfTyp e(types.er asure(oute rmostClass .type), | |
2228 | containe rDef.pos() ), | |
2229 | desiredAss ertionStat usSym))); | |
2230 | JCVariab leDecl ass ertDisable dDef = mak e.VarDef(a ssertDisab ledSym, | |
2231 | notStatus ); | |
2232 | containe rDef.defs = containe rDef.defs. prepend(as sertDisabl edDef); | |
2233 | ||
2234 | if (curr entClass.i sInterface ()) { | |
2235 | //ne ed to load the asser tions enab led/disabl ed state w hile | |
2236 | //in itializing the inter face: | |
2237 | JCCl assDecl cu rrentClass Def = clas sDef(curre ntClass); | |
2238 | make _at(curren tClassDef. pos()); | |
2239 | JCSt atement du mmy = make .If(make.Q ualIdent(a ssertDisab ledSym), m ake.Skip() , null); | |
2240 | JCBl ock clinit = make.Bl ock(STATIC , List.<JC Statement> of(dummy)) ; | |
2241 | curr entClassDe f.defs = c urrentClas sDef.defs. prepend(cl init); | |
2242 | } | |
2243 | } | |
2244 | ma ke_at(pos) ; | |
2245 | re turn makeU nary(NOT, make.Ident (assertDis abledSym)) ; | |
2246 | } | |
2247 | ||
2248 | ||
2249 | /********* ********** ********** ********** ********** ********** ********** ***** | |
2250 | * Buildin g blocks f or let exp ressions | |
2251 | ********* ********** ********** ********** ********** ********** ********** ****/ | |
2252 | ||
2253 | interf ace TreeBu ilder { | |
2254 | JC Tree build (JCTree ar g); | |
2255 | } | |
2256 | ||
2257 | /** Co nstruct an expressio n using th e builder, with the given rval | |
2258 | * ex pression a s an argum ent to the builder. However, the rval | |
2259 | * ex pression m ust be com puted only once, eve n if used multiple | |
2260 | * ti mes in the result of the build er. We do that by | |
2261 | * co nstructing a "let" e xpression that saves the rvalu e into a | |
2262 | * te mporary va riable and then uses the tempo rary varia ble in | |
2263 | * pl ace of the expressio n built by the build er. The c omplete | |
2264 | * re sulting ex pression i s of the f orm | |
2265 | * <p re> | |
2266 | * (let <b>TY PE</b> <b> TEMP</b> = <b>RVAL</ b>; | |
2267 | * in (<b>BU ILDER</b>( <b>TEMP</b >))) | |
2268 | * </ pre> | |
2269 | * wh ere <code> <b>TEMP</b ></code> i s a newly declared v ariable | |
2270 | * in the let e xpression. | |
2271 | */ | |
2272 | JCTree abstractR val(JCTree rval, Typ e type, Tr eeBuilder builder) { | |
2273 | rv al = TreeI nfo.skipPa rens(rval) ; | |
2274 | sw itch (rval .getTag()) { | |
2275 | ca se LITERAL : | |
2276 | return b uilder.bui ld(rval); | |
2277 | ca se IDENT: | |
2278 | JCIdent id = (JCId ent) rval; | |
2279 | if ((id. sym.flags( ) & FINAL) != 0 && i d.sym.owne r.kind == MTH) | |
2280 | retu rn builder .build(rva l); | |
2281 | } | |
2282 | Va rSymbol va r = | |
2283 | new VarS ymbol(FINA L|SYNTHETI C, | |
2284 | name s.fromStri ng( | |
2285 | target.s yntheticNa meChar() | |
2286 | + "" + r val.hashCo de()), | |
2287 | ty pe, | |
2288 | cu rrentMetho dSym); | |
2289 | rv al = conve rt(rval,ty pe); | |
2290 | JC VariableDe cl def = m ake.VarDef (var, (JCE xpression) rval); // XXX cast | |
2291 | JC Tree built = builder .build(mak e.Ident(va r)); | |
2292 | JC Tree res = make.LetE xpr(def, b uilt); | |
2293 | re s.type = b uilt.type; | |
2294 | re turn res; | |
2295 | } | |
2296 | ||
2297 | // sam e as above , with the type of t he tempora ry variabl e computed | |
2298 | JCTree abstractR val(JCTree rval, Tre eBuilder b uilder) { | |
2299 | re turn abstr actRval(rv al, rval.t ype, build er); | |
2300 | } | |
2301 | ||
2302 | // sam e as above , but for an express ion that m ay be used as either | |
2303 | // an rvalue or an lvalue. This req uires spec ial handli ng for | |
2304 | // Sel ect expres sions, whe re we plac e the left -hand-side of the | |
2305 | // sel ect in a t emporary, and for In dexed expr essions, w here we | |
2306 | // pla ce both th e indexed expression and the i ndex value in temps. | |
2307 | JCTree abstractL val(JCTree lval, fin al TreeBui lder build er) { | |
2308 | lv al = TreeI nfo.skipPa rens(lval) ; | |
2309 | sw itch (lval .getTag()) { | |
2310 | ca se IDENT: | |
2311 | return b uilder.bui ld(lval); | |
2312 | ca se SELECT: { | |
2313 | final JC FieldAcces s s = (JCF ieldAccess )lval; | |
2314 | JCTree s elected = TreeInfo.s kipParens( s.selected ); | |
2315 | Symbol l id = TreeI nfo.symbol (s.selecte d); | |
2316 | if (lid != null && lid.kind == TYP) re turn build er.build(l val); | |
2317 | return a bstractRva l(s.select ed, new Tr eeBuilder( ) { | |
2318 | public JCT ree build( final JCTr ee selecte d) { | |
2319 | return builder.b uild(make. Select((JC Expression )selected, s.sym)); | |
2320 | } | |
2321 | }); | |
2322 | } | |
2323 | ca se INDEXED : { | |
2324 | final JC ArrayAcces s i = (JCA rrayAccess )lval; | |
2325 | return a bstractRva l(i.indexe d, new Tre eBuilder() { | |
2326 | public JCT ree build( final JCTr ee indexed ) { | |
2327 | return abstractR val(i.inde x, syms.in tType, new TreeBuild er() { | |
2328 | public J CTree buil d(final JC Tree index ) { | |
2329 | JCTr ee newLval = make.In dexed((JCE xpression) indexed, | |
2330 | (JCExp ression)in dex); | |
2331 | newL val.setTyp e(i.type); | |
2332 | retu rn builder .build(new Lval); | |
2333 | } | |
2334 | }) ; | |
2335 | } | |
2336 | }); | |
2337 | } | |
2338 | ca se TYPECAS T: { | |
2339 | return a bstractLva l(((JCType Cast)lval) .expr, bui lder); | |
2340 | } | |
2341 | } | |
2342 | th row new As sertionErr or(lval); | |
2343 | } | |
2344 | ||
2345 | // eva luate and discard th e first ex pression, then evalu ate the se cond. | |
2346 | JCTree makeComma (final JCT ree expr1, final JCT ree expr2) { | |
2347 | re turn abstr actRval(ex pr1, new T reeBuilder () { | |
2348 | publ ic JCTree build(fina l JCTree d iscarded) { | |
2349 | return exp r2; | |
2350 | } | |
2351 | }); | |
2352 | } | |
2353 | ||
2354 | /********* ********** ********** ********** ********** ********** ********** ***** | |
2355 | * Transla tion metho ds | |
2356 | ********* ********** ********** ********** ********** ********** ********** ****/ | |
2357 | ||
2358 | /** Vi sitor argu ment: encl osing oper ator node. | |
2359 | */ | |
2360 | privat e JCExpres sion enclO p; | |
2361 | ||
2362 | /** Vi sitor meth od: Transl ate a sing le node. | |
2363 | * At tach the s ource posi tion from the old tr ee to its replacemen t tree. | |
2364 | */ | |
2365 | @Overr ide | |
2366 | public <T extend s JCTree> T translat e(T tree) { | |
2367 | if (tree == null) { | |
2368 | return n ull; | |
2369 | } else { | |
2370 | make_at( tree.pos() ); | |
2371 | T result = super.t ranslate(t ree); | |
2372 | if (endP osTable != null && r esult != t ree) { | |
2373 | endP osTable.re placeTree( tree, resu lt); | |
2374 | } | |
2375 | return r esult; | |
2376 | } | |
2377 | } | |
2378 | ||
2379 | /** Vi sitor meth od: Transl ate a sing le node, b oxing or u nboxing if needed. | |
2380 | */ | |
2381 | public <T extend s JCTree> T translat e(T tree, Type type) { | |
2382 | re turn (tree == null) ? null : b oxIfNeeded (translate (tree), ty pe); | |
2383 | } | |
2384 | ||
2385 | /** Vi sitor meth od: Transl ate tree. | |
2386 | */ | |
2387 | public <T extend s JCTree> T translat e(T tree, JCExpressi on enclOp) { | |
2388 | JC Expression prevEnclO p = this.e nclOp; | |
2389 | th is.enclOp = enclOp; | |
2390 | T res = tran slate(tree ); | |
2391 | th is.enclOp = prevEncl Op; | |
2392 | re turn res; | |
2393 | } | |
2394 | ||
2395 | /** Vi sitor meth od: Transl ate list o f trees. | |
2396 | */ | |
2397 | public <T extend s JCTree> List<T> tr anslate(Li st<T> tree s, JCExpre ssion encl Op) { | |
2398 | JC Expression prevEnclO p = this.e nclOp; | |
2399 | th is.enclOp = enclOp; | |
2400 | Li st<T> res = translat e(trees); | |
2401 | th is.enclOp = prevEncl Op; | |
2402 | re turn res; | |
2403 | } | |
2404 | ||
2405 | /** Vi sitor meth od: Transl ate list o f trees. | |
2406 | */ | |
2407 | public <T extend s JCTree> List<T> tr anslate(Li st<T> tree s, Type ty pe) { | |
2408 | if (trees == null) ret urn null; | |
2409 | fo r (List<T> l = trees ; l.nonEmp ty(); l = l.tail) | |
2410 | l.head = translate (l.head, t ype); | |
2411 | re turn trees ; | |
2412 | } | |
2413 | ||
2414 | public void visi tTopLevel( JCCompilat ionUnit tr ee) { | |
2415 | if (needPack ageInfoCla ss(tree)) { | |
2416 | Name nam e = names. package_in fo; | |
2417 | long fla gs = Flags .ABSTRACT | Flags.IN TERFACE; | |
2418 | if (targ et.isPacka geInfoSynt hetic()) | |
2419 | // p ackage-inf o is marke d SYNTHETI C in JDK 1 .6 and lat er release s | |
2420 | flag s = flags | Flags.SY NTHETIC; | |
2421 | JCClassD ecl packag eAnnotatio nsClass | |
2422 | = ma ke.ClassDe f(make.Mod ifiers(fla gs, | |
2423 | tre e.packageA nnotations ), | |
2424 | name, Li st.<JCType Parameter> nil(), | |
2425 | null, Li st.<JCExpr ession>nil (), List.< JCTree>nil ()); | |
2426 | ClassSym bol c = tr ee.packge. package_in fo; | |
2427 | c.flags_ field |= f lags; | |
2428 | c.setAtt ributes(tr ee.packge) ; | |
2429 | ClassTyp e ctype = (ClassType ) c.type; | |
2430 | ctype.su pertype_fi eld = syms .objectTyp e; | |
2431 | ctype.in terfaces_f ield = Lis t.nil(); | |
2432 | packageA nnotations Class.sym = c; | |
2433 | ||
2434 | translat ed.append( packageAnn otationsCl ass); | |
2435 | } | |
2436 | } | |
2437 | // whe re | |
2438 | privat e boolean needPackag eInfoClass (JCCompila tionUnit t ree) { | |
2439 | sw itch (pkgi nfoOpt) { | |
2440 | case ALW AYS: | |
2441 | retu rn true; | |
2442 | case LEG ACY: | |
2443 | retu rn tree.pa ckageAnnot ations.non Empty(); | |
2444 | case NON EMPTY: | |
2445 | for (Attribute .Compound a : | |
2446 | tree. packge.get Declaratio nAttribute s()) { | |
2447 | Attribute. RetentionP olicy p = types.getR etention(a ); | |
2448 | if (p != A ttribute.R etentionPo licy.SOURC E) | |
2449 | return true; | |
2450 | } | |
2451 | retu rn false; | |
2452 | } | |
2453 | th row new As sertionErr or(); | |
2454 | } | |
2455 | ||
2456 | public void visi tClassDef( JCClassDec l tree) { | |
2457 | En v<AttrCont ext> prevE nv = attrE nv; | |
2458 | Cl assSymbol currentCla ssPrev = c urrentClas s; | |
2459 | Me thodSymbol currentMe thodSymPre v = curren tMethodSym ; | |
2460 | ||
2461 | cu rrentClass = tree.sy m; | |
2462 | cu rrentMetho dSym = nul l; | |
2463 | at trEnv = ty peEnvs.rem ove(curren tClass); | |
2464 | if (attrEnv == null) | |
2465 | attrEnv = prevEnv; | |
2466 | ||
2467 | cl assdefs.pu t(currentC lass, tree ); | |
2468 | ||
2469 | pr oxies = pr oxies.dup( currentCla ss); | |
2470 | Li st<VarSymb ol> prevOu terThisSta ck = outer ThisStack; | |
2471 | ||
2472 | // If this i s an enum definition | |
2473 | if ((tree.mo ds.flags & ENUM) != 0 && | |
2474 | (types.s upertype(c urrentClas s.type).ts ym.flags() & ENUM) = = 0) | |
2475 | visitEnu mDef(tree) ; | |
2476 | ||
2477 | // If this i s a nested class, de fine a thi s$n field for | |
2478 | // it and ad d to proxi es. | |
2479 | JC VariableDe cl otdef = null; | |
2480 | if (currentC lass.hasOu terInstanc e()) | |
2481 | otdef = outerThisD ef(tree.po s, current Class); | |
2482 | ||
2483 | // If this i s a local class, def ine proxie s for all its free v ariables. | |
2484 | Li st<JCVaria bleDecl> f vdefs = fr eevarDefs( | |
2485 | tree.pos , freevars (currentCl ass), curr entClass); | |
2486 | ||
2487 | // Recursive ly transla te supercl ass, inter faces. | |
2488 | tr ee.extendi ng = trans late(tree. extending) ; | |
2489 | tr ee.impleme nting = tr anslate(tr ee.impleme nting); | |
2490 | ||
2491 | if (currentC lass.isLoc al()) { | |
2492 | ClassSym bol encl = currentCl ass.owner. enclClass( ); | |
2493 | if (encl .trans_loc al == null ) { | |
2494 | encl .trans_loc al = List. nil(); | |
2495 | } | |
2496 | encl.tra ns_local = encl.tran s_local.pr epend(curr entClass); | |
2497 | } | |
2498 | ||
2499 | // Recursive ly transla te members , taking i nto accoun t that new members | |
2500 | // might be created du ring the t ranslation and prepe nded to th e member | |
2501 | // list `tre e.defs'. | |
2502 | Li st<JCTree> seen = Li st.nil(); | |
2503 | wh ile (tree. defs != se en) { | |
2504 | List<JCT ree> unsee n = tree.d efs; | |
2505 | for (Lis t<JCTree> l = unseen ; l.nonEmp ty() && l != seen; l = l.tail) { | |
2506 | JCTr ee outermo stMemberDe fPrev = ou termostMem berDef; | |
2507 | if ( outermostM emberDefPr ev == null ) outermos tMemberDef = l.head; | |
2508 | l.he ad = trans late(l.hea d); | |
2509 | oute rmostMembe rDef = out ermostMemb erDefPrev; | |
2510 | } | |
2511 | seen = u nseen; | |
2512 | } | |
2513 | ||
2514 | // Convert a protected modifier to public, mask stat ic modifie r. | |
2515 | if ((tree.mo ds.flags & PROTECTED ) != 0) tr ee.mods.fl ags |= PUB LIC; | |
2516 | tr ee.mods.fl ags &= Cla ssFlags; | |
2517 | ||
2518 | // Convert n ame to fla t represen tation, re placing '. ' by '$'. | |
2519 | tr ee.name = Convert.sh ortName(cu rrentClass .flatName( )); | |
2520 | ||
2521 | // Add this$ n and free variables proxy def initions t o class. | |
2522 | ||
2523 | fo r (List<JC VariableDe cl> l = fv defs; l.no nEmpty(); l = l.tail ) { | |
2524 | tree.def s = tree.d efs.prepen d(l.head); | |
2525 | enterSyn thetic(tre e.pos(), l .head.sym, currentCl ass.member s()); | |
2526 | } | |
2527 | if (currentC lass.hasOu terInstanc e()) { | |
2528 | tree.def s = tree.d efs.prepen d(otdef); | |
2529 | enterSyn thetic(tre e.pos(), o tdef.sym, currentCla ss.members ()); | |
2530 | } | |
2531 | ||
2532 | pr oxies = pr oxies.leav e(); | |
2533 | ou terThisSta ck = prevO uterThisSt ack; | |
2534 | ||
2535 | // Append tr anslated t ree to `tr anslated' queue. | |
2536 | tr anslated.a ppend(tree ); | |
2537 | ||
2538 | at trEnv = pr evEnv; | |
2539 | cu rrentClass = current ClassPrev; | |
2540 | cu rrentMetho dSym = cur rentMethod SymPrev; | |
2541 | ||
2542 | // Return em pty block {} as a pl aceholder for an inn er class. | |
2543 | re sult = mak e_at(tree. pos()).Blo ck(SYNTHET IC, List.< JCStatemen t>nil()); | |
2544 | } | |
2545 | ||
2546 | /** Tr anslate an enum clas s. */ | |
2547 | privat e void vis itEnumDef( JCClassDec l tree) { | |
2548 | ma ke_at(tree .pos()); | |
2549 | ||
2550 | // add the s upertype, if needed | |
2551 | if (tree.ext ending == null) | |
2552 | tree.ext ending = m ake.Type(t ypes.super type(tree. type)); | |
2553 | ||
2554 | // classOfTy pe adds a cache fiel d to tree. defs unles s | |
2555 | // target.ha sClassLite rals(). | |
2556 | JC Expression e_class = classOfTy pe(tree.sy m.type, tr ee.pos()). | |
2557 | setType( types.eras ure(syms.c lassType)) ; | |
2558 | ||
2559 | // process e ach enumer ation cons tant, addi ng implici t construc tor parame ters | |
2560 | in t nextOrdi nal = 0; | |
2561 | Li stBuffer<J CExpressio n> values = new List Buffer<JCE xpression> (); | |
2562 | Li stBuffer<J CTree> enu mDefs = ne w ListBuff er<JCTree> (); | |
2563 | Li stBuffer<J CTree> oth erDefs = n ew ListBuf fer<JCTree >(); | |
2564 | fo r (List<JC Tree> defs = tree.de fs; | |
2565 | defs.no nEmpty(); | |
2566 | defs=de fs.tail) { | |
2567 | if (defs.h ead.hasTag (
|
|
2568 | JCVa riableDecl var = (JC VariableDe cl)defs.he ad; | |
2569 | visi tEnumConst antDef(var , nextOrdi nal++); | |
2570 | valu es.append( make.QualI dent(var.s ym)); | |
2571 | enum Defs.appen d(var); | |
2572 | } else { | |
2573 | othe rDefs.appe nd(defs.he ad); | |
2574 | } | |
2575 | } | |
2576 | ||
2577 | // private s tatic fina l T[] #VAL UES = { a, b, c }; | |
2578 | Na me valuesN ame = name s.fromStri ng(target. syntheticN ameChar() + "VALUES" ); | |
2579 | wh ile (tree. sym.member s().lookup (valuesNam e).scope ! = null) // avoid nam e clash | |
2580 | valuesNa me = names .fromStrin g(valuesNa me + "" + target.syn theticName Char()); | |
2581 | Ty pe arrayTy pe = new A rrayType(t ypes.erasu re(tree.ty pe), syms. arrayClass ); | |
2582 | Va rSymbol va luesVar = new VarSym bol(PRIVAT E|FINAL|ST ATIC|SYNTH ETIC, | |
2583 | values Name, | |
2584 | arrayT ype, | |
2585 | tree.t ype.tsym); | |
2586 | JC NewArray n ewArray = make.NewAr ray(make.T ype(types. erasure(tr ee.type)), | |
2587 | List.<JC Expression >nil(), | |
2588 | values.t oList()); | |
2589 | ne wArray.typ e = arrayT ype; | |
2590 | en umDefs.app end(make.V arDef(valu esVar, new Array)); | |
2591 | tr ee.sym.mem bers().ent er(valuesV ar); | |
2592 | ||
2593 | Sy mbol value sSym = loo kupMethod( tree.pos() , names.va lues, | |
2594 | tree.type, List.<Typ e>nil()); | |
2595 | Li st<JCState ment> valu esBody; | |
2596 | if (useClone ()) { | |
2597 | // retur n (T[]) $V ALUES.clon e(); | |
2598 | JCTypeCa st valuesR esult = | |
2599 | make .TypeCast( valuesSym. type.getRe turnType() , | |
2600 | make.App(m ake.Select (make.Iden t(valuesVa r), | |
2601 | syms.arra yCloneMeth od))); | |
2602 | valuesBo dy = List. <JCStateme nt>of(make .Return(va luesResult )); | |
2603 | } else { | |
2604 | // templ ate: T[] $ result = n ew T[$valu es.length] ; | |
2605 | Name res ultName = names.from String(tar get.synthe ticNameCha r() + "res ult"); | |
2606 | while (t ree.sym.me mbers().lo okup(resul tName).sco pe != null ) // avoid name clas h | |
2607 | resu ltName = n ames.fromS tring(resu ltName + " " + target .synthetic NameChar() ); | |
2608 | VarSymbo l resultVa r = new Va rSymbol(FI NAL|SYNTHE TIC, | |
2609 | re sultName, | |
2610 | ar rayType, | |
2611 | va luesSym); | |
2612 | JCNewArr ay resultA rray = mak e.NewArray (make.Type (types.era sure(tree. type)), | |
2613 | List.o f(make.Sel ect(make.I dent(value sVar), sym s.lengthVa r)), | |
2614 | null); | |
2615 | resultAr ray.type = arrayType ; | |
2616 | JCVariab leDecl dec l = make.V arDef(resu ltVar, res ultArray); | |
2617 | ||
2618 | // templ ate: Syste m.arraycop y($VALUES, 0, $resul t, 0, $VAL UES.length ); | |
2619 | if (syst emArraycop yMethod == null) { | |
2620 | syst emArraycop yMethod = | |
2621 | new Method Symbol(PUB LIC | STAT IC, | |
2622 | nam es.fromStr ing("array copy"), | |
2623 | new MethodTyp e(List.<Ty pe>of(syms .objectTyp e, | |
2624 | syms.intTy pe, | |
2625 | syms.objec tType, | |
2626 | syms.intTy pe, | |
2627 | syms.intTy pe), | |
2628 | syms.voi dType, | |
2629 | List.<Ty pe>nil(), | |
2630 | syms.met hodClass), | |
2631 | sym s.systemTy pe.tsym); | |
2632 | } | |
2633 | JCStatem ent copy = | |
2634 | make .Exec(make .App(make. Select(mak e.Ident(sy ms.systemT ype.tsym), | |
2635 | sys temArrayco pyMethod), | |
2636 | List .of(make.I dent(value sVar), mak e.Literal( 0), | |
2637 | make.I dent(resul tVar), mak e.Literal( 0), | |
2638 | make.S elect(make .Ident(val uesVar), s yms.length Var)))); | |
2639 | ||
2640 | // templ ate: retur n $result; | |
2641 | JCStatem ent ret = make.Retur n(make.Ide nt(resultV ar)); | |
2642 | valuesBo dy = List. <JCStateme nt>of(decl , copy, re t); | |
2643 | } | |
2644 | ||
2645 | JC MethodDecl valuesDef = | |
2646 | make.Me thodDef((M ethodSymbo l)valuesSy m, make.Bl ock(0, val uesBody)); | |
2647 | ||
2648 | en umDefs.app end(values Def); | |
2649 | ||
2650 | if (debugLow er) | |
2651 | System.e rr.println (tree.sym + ".values Def = " + valuesDef) ; | |
2652 | ||
2653 | /* * The temp late for t he followi ng code is : | |
2654 | * | |
2655 | * publi c static E valueOf(S tring name ) { | |
2656 | * r eturn (E)E num.valueO f(E.class, name); | |
2657 | * } | |
2658 | * | |
2659 | * where E is tree.sy m | |
2660 | * / | |
2661 | Me thodSymbol valueOfSy m = lookup Method(tre e.pos(), | |
2662 | names .valueOf, | |
2663 | tree. sym.type, | |
2664 | List. of(syms.st ringType)) ; | |
2665 | As sert.check ((valueOfS ym.flags() & STATIC) != 0); | |
2666 | Va rSymbol na meArgSym = valueOfSy m.params.h ead; | |
2667 | JC Ident name Val = make .Ident(nam eArgSym); | |
2668 | JC Statement enum_Value Of = | |
2669 | make.Ret urn(make.T ypeCast(tr ee.sym.typ e, | |
2670 | ma keCall(mak e.Ident(sy ms.enumSym ), | |
2671 | nam es.valueOf , | |
2672 | Lis t.of(e_cla ss, nameVa l)))); | |
2673 | JC MethodDecl valueOf = make.Meth odDef(valu eOfSym, | |
2674 | make.Bl ock(0, Lis t.of(enum_ ValueOf))) ; | |
2675 | na meVal.sym = valueOf. params.hea d.sym; | |
2676 | if (debugLow er) | |
2677 | System.e rr.println (tree.sym + ".valueO f = " + va lueOf); | |
2678 | en umDefs.app end(valueO f); | |
2679 | ||
2680 | en umDefs.app endList(ot herDefs.to List()); | |
2681 | tr ee.defs = enumDefs.t oList(); | |
2682 | } | |
2683 | // where | |
2684 | pr ivate Meth odSymbol s ystemArray copyMethod ; | |
2685 | pr ivate bool ean useClo ne() { | |
2686 | try { | |
2687 | Scop e.Entry e = syms.obj ectType.ts ym.members ().lookup( names.clon e); | |
2688 | retu rn (e.sym != null); | |
2689 | } | |
2690 | catch (C ompletionF ailure e) { | |
2691 | retu rn false; | |
2692 | } | |
2693 | } | |
2694 | ||
2695 | /** Tr anslate an enumerati on constan t and its initialize r. */ | |
2696 | privat e void vis itEnumCons tantDef(JC VariableDe cl var, in t ordinal) { | |
2697 | JC NewClass v arDef = (J CNewClass) var.init; | |
2698 | va rDef.args = varDef.a rgs. | |
2699 | prepend( makeLit(sy ms.intType , ordinal) ). | |
2700 | prepend( makeLit(sy ms.stringT ype, var.n ame.toStri ng())); | |
2701 | } | |
2702 | ||
2703 | public void visi tMethodDef (JCMethodD ecl tree) { | |
2704 | if (tree.nam e == names .init && ( currentCla ss.flags_f ield&ENUM) != 0) { | |
2705 | // Add " String $en um$name, i nt $enum$o rdinal" to the begin ning of th e | |
2706 | // argum ent list f or each co nstructor of an enum . | |
2707 | JCVariab leDecl nam eParam = m ake_at(tre e.pos()). | |
2708 | Para m(names.fr omString(t arget.synt heticNameC har() + | |
2709 | " enum" + ta rget.synth eticNameCh ar() + "na me"), | |
2710 | syms.str ingType, t ree.sym); | |
2711 | namePara m.mods.fla gs |= SYNT HETIC; nam eParam.sym .flags_fie ld |= SYNT HETIC; | |
2712 | JCVariab leDecl ord Param = ma ke. | |
2713 | Para m(names.fr omString(t arget.synt heticNameC har() + | |
2714 | " enum" + ta rget.synth eticNameCh ar() + | |
2715 | " ordinal"), | |
2716 | syms.int Type, tree .sym); | |
2717 | ordParam .mods.flag s |= SYNTH ETIC; ordP aram.sym.f lags_field |= SYNTHE TIC; | |
2718 | ||
2719 | tree.par ams = tree .params.pr epend(ordP aram).prep end(namePa ram); | |
2720 | ||
2721 | MethodSy mbol m = t ree.sym; | |
2722 | m.extraP arams = m. extraParam s.prepend( ordParam.s ym); | |
2723 | m.extraP arams = m. extraParam s.prepend( nameParam. sym); | |
2724 | Type old erasure = m.erasure( types); | |
2725 | m.erasur e_field = new Method Type( | |
2726 | olde rasure.get ParameterT ypes().pre pend(syms. intType).p repend(sym s.stringTy pe), | |
2727 | olde rasure.get ReturnType (), | |
2728 | olde rasure.get ThrownType s(), | |
2729 | syms .methodCla ss); | |
2730 | } | |
2731 | ||
2732 | JC MethodDecl prevMetho dDef = cur rentMethod Def; | |
2733 | Me thodSymbol prevMetho dSym = cur rentMethod Sym; | |
2734 | tr y { | |
2735 | currentM ethodDef = tree; | |
2736 | currentM ethodSym = tree.sym; | |
2737 | visitMet hodDefInte rnal(tree) ; | |
2738 | } finally { | |
2739 | currentM ethodDef = prevMetho dDef; | |
2740 | currentM ethodSym = prevMetho dSym; | |
2741 | } | |
2742 | } | |
2743 | //wher e | |
2744 | privat e void vis itMethodDe fInternal( JCMethodDe cl tree) { | |
2745 | if (tree.nam e == names .init && | |
2746 | (current Class.isIn ner() || c urrentClas s.isLocal( ))) { | |
2747 | // We ar e seeing a construct or of an i nner class . | |
2748 | MethodSy mbol m = t ree.sym; | |
2749 | ||
2750 | // Push a new prox y scope fo r construc tor parame ters. | |
2751 | // and c reate defi nitions fo r any this $n and pro xy paramet ers. | |
2752 | proxies = proxies. dup(m); | |
2753 | List<Var Symbol> pr evOuterThi sStack = o uterThisSt ack; | |
2754 | List<Var Symbol> fv s = freeva rs(current Class); | |
2755 | JCVariab leDecl otd ef = null; | |
2756 | if (curr entClass.h asOuterIns tance()) | |
2757 | otde f = outerT hisDef(tre e.pos, m); | |
2758 | List<JCV ariableDec l> fvdefs = freevarD efs(tree.p os, fvs, m , PARAMETE R); | |
2759 | ||
2760 | // Recur sively tra nslate res ult type, parameters and throw n list. | |
2761 | tree.res type = tra nslate(tre e.restype) ; | |
2762 | tree.par ams = tran slateVarDe fs(tree.pa rams); | |
2763 | tree.thr own = tran slate(tree .thrown); | |
2764 | ||
2765 | // when compiling stubs, don 't process body | |
2766 | if (tree .body == n ull) { | |
2767 | resu lt = tree; | |
2768 | retu rn; | |
2769 | } | |
2770 | ||
2771 | // Add t his$n (if needed) in front of and free v ariables b ehind | |
2772 | // const ructor par ameter lis t. | |
2773 | tree.par ams = tree .params.ap pendList(f vdefs); | |
2774 | if (curr entClass.h asOuterIns tance()) | |
2775 | tree .params = tree.param s.prepend( otdef); | |
2776 | ||
2777 | // If th is is an i nitial con structor, i.e., it d oes not st art with | |
2778 | // this( ...), inse rt initial izers for this$n and proxies | |
2779 | // befor e (pre-1.4 , after) t he call to superclas s construc tor. | |
2780 | JCStatem ent selfCa ll = trans late(tree. body.stats .head); | |
2781 | ||
2782 | List<JCS tatement> added = Li st.nil(); | |
2783 | if (fvs. nonEmpty() ) { | |
2784 | List <Type> add edargtypes = List.ni l(); | |
2785 | for (List<VarS ymbol> l = fvs; l.no nEmpty(); l = l.tail ) { | |
2786 | if (TreeIn fo.isIniti alConstruc tor(tree)) { | |
2787 | final Name pName = proxyNa me(l.head. name); | |
2788 | m.capt uredLocals = | |
2789 | m. capturedLo cals.appen d((VarSymb ol) | |
2790 | (proxies .lookup(pN ame).sym)) ; | |
2791 | added = added.pr epend( | |
2792 | init Field(tree .body.pos, pName)); | |
2793 | } | |
2794 | addedargty pes = adde dargtypes. prepend(l. head.erasu re(types)) ; | |
2795 | } | |
2796 | Type olderasur e = m.eras ure(types) ; | |
2797 | m.er asure_fiel d = new Me thodType( | |
2798 | olderasure .getParame terTypes() .appendLis t(addedarg types), | |
2799 | olderasure .getReturn Type(), | |
2800 | olderasure .getThrown Types(), | |
2801 | syms.metho dClass); | |
2802 | } | |
2803 | if (curr entClass.h asOuterIns tance() && | |
2804 | Tree Info.isIni tialConstr uctor(tree )) | |
2805 | { | |
2806 | adde d = added. prepend(in itOuterThi s(tree.bod y.pos)); | |
2807 | } | |
2808 | ||
2809 | // pop l ocal varia bles from proxy stac k | |
2810 | proxies = proxies. leave(); | |
2811 | ||
2812 | // recur sively tra nslate fol lowing loc al stateme nts and | |
2813 | // combi ne with th is- or sup er-call | |
2814 | List<JCS tatement> stats = tr anslate(tr ee.body.st ats.tail); | |
2815 | if (targ et.initial izeFieldsB eforeSuper ()) | |
2816 | tree .body.stat s = stats. prepend(se lfCall).pr ependList( added); | |
2817 | else | |
2818 | tree .body.stat s = stats. prependLis t(added).p repend(sel fCall); | |
2819 | ||
2820 | outerThi sStack = p revOuterTh isStack; | |
2821 | } else { | |
2822 | Map<Symb ol, Symbol > prevLamb daTranslat ionMap = | |
2823 | lambdaTran slationMap ; | |
2824 | try { | |
2825 | lamb daTranslat ionMap = ( tree.sym.f lags() & S YNTHETIC) != 0 && | |
2826 | tree.s ym.name.st artsWith(n ames.lambd a) ? | |
2827 | makeTr anslationM ap(tree) : null; | |
2828 | supe r.visitMet hodDef(tre e); | |
2829 | } finall y { | |
2830 | lamb daTranslat ionMap = p revLambdaT ranslation Map; | |
2831 | } | |
2832 | } | |
2833 | re sult = tre e; | |
2834 | } | |
2835 | //wher e | |
2836 | pr ivate Map< Symbol, Sy mbol> make Translatio nMap(JCMet hodDecl tr ee) { | |
2837 | Map<Symb ol, Symbol > translat ionMap = n ew HashMap <Symbol,Sy mbol>(); | |
2838 | for (JCV ariableDec l vd : tre e.params) { | |
2839 | Symb ol p = vd. sym; | |
2840 | if ( p != p.bas eSymbol()) { | |
2841 | translatio nMap.put(p .baseSymbo l(), p); | |
2842 | } | |
2843 | } | |
2844 | return t ranslation Map; | |
2845 | } | |
2846 | ||
2847 | public void visi tAnnotated Type(JCAnn otatedType tree) { | |
2848 | // No need t o retain t ype annota tions in t he tree | |
2849 | // tree.anno tations = translate( tree.annot ations); | |
2850 | tr ee.annotat ions = Lis t.nil(); | |
2851 | tr ee.underly ingType = translate( tree.under lyingType) ; | |
2852 | // but maint ain type a nnotations in the ty pe. | |
2853 | if (tree.typ e.isAnnota ted()) { | |
2854 | tree.typ e = tree.u nderlyingT ype.type.u nannotated Type().ann otatedType (tree.type .getAnnota tionMirror s()); | |
2855 | } else if (t ree.underl yingType.t ype.isAnno tated()) { | |
2856 | tree.typ e = tree.u nderlyingT ype.type; | |
2857 | } | |
2858 | re sult = tre e; | |
2859 | } | |
2860 | ||
2861 | public void visi tTypeCast( JCTypeCast tree) { | |
2862 | tr ee.clazz = translate (tree.claz z); | |
2863 | if (tree.typ e.isPrimit ive() != t ree.expr.t ype.isPrim itive()) | |
2864 | tree.exp r = transl ate(tree.e xpr, tree. type); | |
2865 | el se | |
2866 | tree.exp r = transl ate(tree.e xpr); | |
2867 | re sult = tre e; | |
2868 | } | |
2869 | ||
2870 | public void visi tNewClass( JCNewClass tree) { | |
2871 | Cl assSymbol c = (Class Symbol)tre e.construc tor.owner; | |
2872 | ||
2873 | // Box argum ents, if n ecessary | |
2874 | bo olean isEn um = (tree .construct or.owner.f lags() & E NUM) != 0; | |
2875 | Li st<Type> a rgTypes = tree.const ructor.typ e.getParam eterTypes( ); | |
2876 | if (isEnum) argTypes = argTypes. prepend(sy ms.intType ).prepend( syms.strin gType); | |
2877 | tr ee.args = boxArgs(ar gTypes, tr ee.args, t ree.vararg sElement); | |
2878 | tr ee.varargs Element = null; | |
2879 | ||
2880 | // If create d class is local, ad d free var iables aft er | |
2881 | // explicit constructo r argument s. | |
2882 | if (c.isLoca l()) { | |
2883 | tree.arg s = tree.a rgs.append List(loadF reevars(tr ee.pos(), freevars(c ))); | |
2884 | } | |
2885 | ||
2886 | // If an acc ess constr uctor is u sed, appen d null as a last arg ument. | |
2887 | Sy mbol const ructor = a ccessConst ructor(tre e.pos(), t ree.constr uctor); | |
2888 | if (construc tor != tre e.construc tor) { | |
2889 | tree.arg s = tree.a rgs.append (makeNull( )); | |
2890 | tree.con structor = construct or; | |
2891 | } | |
2892 | ||
2893 | // If create d class ha s an outer instance, and new i s qualifie d, pass | |
2894 | // qualifier as first argument. If new is not qualif ied, pass the | |
2895 | // correct o uter insta nce as fir st argumen t. | |
2896 | if (c.hasOut erInstance ()) { | |
2897 | JCExpres sion thisA rg; | |
2898 | if (tree .encl != n ull) { | |
2899 | this Arg = attr .makeNullC heck(trans late(tree. encl)); | |
2900 | this Arg.type = tree.encl .type; | |
2901 | } else i f (c.isLoc al()) { | |
2902 | // l ocal class | |
2903 | this Arg = make This(tree. pos(), c.t ype.getEnc losingType ().tsym); | |
2904 | } else { | |
2905 | // n ested clas s | |
2906 | this Arg = make OwnerThis( tree.pos() , c, false ); | |
2907 | } | |
2908 | tree.arg s = tree.a rgs.prepen d(thisArg) ; | |
2909 | } | |
2910 | tr ee.encl = null; | |
2911 | ||
2912 | // If we hav e an anony mous class , create i ts flat ve rsion, rat her | |
2913 | // than the class or i nterface f ollowing n ew. | |
2914 | if (tree.def != null) { | |
2915 | translat e(tree.def ); | |
2916 | tree.cla zz = acces s(make_at( tree.clazz .pos()).Id ent(tree.d ef.sym)); | |
2917 | tree.def = null; | |
2918 | } else { | |
2919 | tree.cla zz = acces s(c, tree. clazz, enc lOp, false ); | |
2920 | } | |
2921 | re sult = tre e; | |
2922 | } | |
2923 | ||
2924 | // Sim plify cond itionals w ith known constant c ontrolling expressio ns. | |
2925 | // Thi s allows u s to avoid generatin g supporti ng declara tions for | |
2926 | // the dead code , which wi ll not be eliminated during co de generat ion. | |
2927 | // Not e that Flo w.isFalse and Flow.i sTrue only return tr ue | |
2928 | // for constant expression s in the s ense of JL S 15.27, w hich | |
2929 | // are guarantee d to have no side-ef fects. Mo re aggress ive | |
2930 | // con stant prop agation wo uld requir e that we take care to | |
2931 | // pre serve poss ible side- effects in the condi tion expre ssion. | |
2932 | ||
2933 | /** Vi sitor meth od for con ditional e xpressions . | |
2934 | */ | |
2935 | @Overr ide | |
2936 | public void visi tCondition al(JCCondi tional tre e) { | |
2937 | JC Tree cond = tree.con d = transl ate(tree.c ond, syms. booleanTyp e); | |
2938 | if (cond.typ e.isTrue() ) { | |
2939 | result = convert(t ranslate(t ree.truepa rt, tree.t ype), tree .type); | |
2940 | addPrune dInfo(cond ); | |
2941 | } else if (c ond.type.i sFalse()) { | |
2942 | result = convert(t ranslate(t ree.falsep art, tree. type), tre e.type); | |
2943 | addPrune dInfo(cond ); | |
2944 | } else { | |
2945 | // Condi tion is no t a compil e-time con stant. | |
2946 | tree.tru epart = tr anslate(tr ee.truepar t, tree.ty pe); | |
2947 | tree.fal separt = t ranslate(t ree.falsep art, tree. type); | |
2948 | result = tree; | |
2949 | } | |
2950 | } | |
2951 | //where | |
2952 | privat e JCTree c onvert(JCT ree tree, Type pt) { | |
2953 | if (tree.typ e == pt || tree.type .hasTag(BO T)) | |
2954 | return t ree; | |
2955 | JC Tree resul t = make_a t(tree.pos ()).TypeCa st(make.Ty pe(pt), (J CExpressio n)tree); | |
2956 | re sult.type = (tree.ty pe.constVa lue() != n ull) ? cfo lder.coerc e(tree.typ e, pt) | |
2957 | : pt; | |
2958 | re turn resul t; | |
2959 | } | |
2960 | ||
2961 | /** Vi sitor meth od for if statements . | |
2962 | */ | |
2963 | public void visi tIf(JCIf t ree) { | |
2964 | JC Tree cond = tree.con d = transl ate(tree.c ond, syms. booleanTyp e); | |
2965 | if (cond.typ e.isTrue() ) { | |
2966 | result = translate (tree.then part); | |
2967 | addPrune dInfo(cond ); | |
2968 | } else if (c ond.type.i sFalse()) { | |
2969 | if (tree .elsepart != null) { | |
2970 | resu lt = trans late(tree. elsepart); | |
2971 | } else { | |
2972 | resu lt = make. Skip(); | |
2973 | } | |
2974 | addPrune dInfo(cond ); | |
2975 | } else { | |
2976 | // Condi tion is no t a compil e-time con stant. | |
2977 | tree.the npart = tr anslate(tr ee.thenpar t); | |
2978 | tree.els epart = tr anslate(tr ee.elsepar t); | |
2979 | result = tree; | |
2980 | } | |
2981 | } | |
2982 | ||
2983 | /** Vi sitor meth od for ass ert statem ents. Tran slate them away. | |
2984 | */ | |
2985 | public void visi tAssert(JC Assert tre e) { | |
2986 | Di agnosticPo sition det ailPos = ( tree.detai l == null) ? tree.po s() : tree .detail.po s(); | |
2987 | tr ee.cond = translate( tree.cond, syms.bool eanType); | |
2988 | if (!tree.co nd.type.is True()) { | |
2989 | JCExpres sion cond = assertFl agTest(tre e.pos()); | |
2990 | List<JCE xpression> exnArgs = (tree.det ail == nul l) ? | |
2991 | List .<JCExpres sion>nil() : List.of (translate (tree.deta il)); | |
2992 | if (!tre e.cond.typ e.isFalse( )) { | |
2993 | cond = makeBin ary | |
2994 | (AND, | |
2995 | cond, | |
2996 | makeUnary (NOT, tree .cond)); | |
2997 | } | |
2998 | result = | |
2999 | make .If(cond, | |
3000 | make_a t(tree). | |
3001 | Thr ow(makeNew Class(syms .assertion ErrorType, exnArgs)) , | |
3002 | null); | |
3003 | } else { | |
3004 | result = make.Skip (); | |
3005 | } | |
3006 | } | |
3007 | ||
3008 | public void visi tApply(JCM ethodInvoc ation tree ) { | |
3009 | Sy mbol meth = TreeInfo .symbol(tr ee.meth); | |
3010 | Li st<Type> a rgtypes = meth.type. getParamet erTypes(); | |
3011 | if (allowEnu ms && | |
3012 | meth.nam e==names.i nit && | |
3013 | meth.own er == syms .enumSym) | |
3014 | argtypes = argtype s.tail.tai l; | |
3015 | tr ee.args = boxArgs(ar gtypes, tr ee.args, t ree.vararg sElement); | |
3016 | tr ee.varargs Element = null; | |
3017 | Na me methNam e = TreeIn fo.name(tr ee.meth); | |
3018 | if (meth.nam e==names.i nit) { | |
3019 | // We ar e seeing a this(...) or super( ...) const ructor cal l. | |
3020 | // If an access co nstructor is used, a ppend null as a last argument. | |
3021 | Symbol c onstructor = accessC onstructor (tree.pos( ), meth); | |
3022 | if (cons tructor != meth) { | |
3023 | tree .args = tr ee.args.ap pend(makeN ull()); | |
3024 | Tree Info.setSy mbol(tree. meth, cons tructor); | |
3025 | } | |
3026 | ||
3027 | // If we are calli ng a const ructor of a local cl ass, add | |
3028 | // free variables after expl icit const ructor arg uments. | |
3029 | ClassSym bol c = (C lassSymbol )construct or.owner; | |
3030 | if (c.is Local()) { | |
3031 | tree .args = tr ee.args.ap pendList(l oadFreevar s(tree.pos (), freeva rs(c))); | |
3032 | } | |
3033 | ||
3034 | // If we are calli ng a const ructor of an enum cl ass, pass | |
3035 | // along the name and ordina l argument s | |
3036 | if ((c.f lags_field &ENUM) != 0 || c.get QualifiedN ame() == n ames.java_ lang_Enum) { | |
3037 | List <JCVariabl eDecl> par ams = curr entMethodD ef.params; | |
3038 | if ( currentMet hodSym.own er.hasOute rInstance( )) | |
3039 | params = p arams.tail ; // drop this$n | |
3040 | tree .args = tr ee.args | |
3041 | .prepend(m ake_at(tre e.pos()).I dent(param s.tail.hea d.sym)) // ordinal | |
3042 | .prepend(m ake.Ident( params.hea d.sym)); / / name | |
3043 | } | |
3044 | ||
3045 | // If we are calli ng a const ructor of a class wi th an oute r | |
3046 | // insta nce, and t he call | |
3047 | // is qu alified, p ass qualif ier as fir st argumen t in front of | |
3048 | // the e xplicit co nstructor arguments. If the ca ll | |
3049 | // is no t qualifie d, pass th e correct outer inst ance as | |
3050 | // first argument. | |
3051 | if (c.ha sOuterInst ance()) { | |
3052 | JCEx pression t hisArg; | |
3053 | if ( tree.meth. hasTag(SEL ECT)) { | |
3054 | thisArg = attr. | |
3055 | makeNu llCheck(tr anslate((( JCFieldAcc ess) tree. meth).sele cted)); | |
3056 | tree.meth = make.Ide nt(constru ctor); | |
3057 | ((JCIdent) tree.meth ).name = m ethName; | |
3058 | } el se if (c.i sLocal() | | methName == names. _this){ | |
3059 | // local c lass or th is() call | |
3060 | thisArg = makeThis(t ree.meth.p os(), c.ty pe.getEncl osingType( ).tsym); | |
3061 | } el se { | |
3062 | // super() call of n ested clas s - never pick 'this ' | |
3063 | thisArg = makeOwnerT hisN(tree. meth.pos() , c, false ); | |
3064 | } | |
3065 | tree .args = tr ee.args.pr epend(this Arg); | |
3066 | } | |
3067 | } else { | |
3068 | // We ar e seeing a normal me thod invoc ation; tra nslate thi s as usual . | |
3069 | tree.met h = transl ate(tree.m eth); | |
3070 | ||
3071 | // If th e translat ed method itself is an Apply t ree, we ar e | |
3072 | // seein g an acces s method i nvocation. In this c ase, appen d | |
3073 | // the m ethod argu ments to t he argumen ts of the access met hod. | |
3074 | if (tree .meth.hasT ag(APPLY)) { | |
3075 | JCMe thodInvoca tion app = (JCMethod Invocation )tree.meth ; | |
3076 | app. args = tre e.args.pre pendList(a pp.args); | |
3077 | resu lt = app; | |
3078 | retu rn; | |
3079 | } | |
3080 | } | |
3081 | re sult = tre e; | |
3082 | } | |
3083 | ||
3084 | List<J CExpressio n> boxArgs (List<Type > paramete rs, List<J CExpressio n> _args, Type varar gsElement) { | |
3085 | Li st<JCExpre ssion> arg s = _args; | |
3086 | if (paramete rs.isEmpty ()) return args; | |
3087 | bo olean anyC hanges = f alse; | |
3088 | Li stBuffer<J CExpressio n> result = new List Buffer<JCE xpression> (); | |
3089 | wh ile (param eters.tail .nonEmpty( )) { | |
3090 | JCExpres sion arg = translate (args.head , paramete rs.head); | |
3091 | anyChang es |= (arg != args.h ead); | |
3092 | result.a ppend(arg) ; | |
3093 | args = a rgs.tail; | |
3094 | paramete rs = param eters.tail ; | |
3095 | } | |
3096 | Ty pe paramet er = param eters.head ; | |
3097 | if (varargsE lement != null) { | |
3098 | anyChang es = true; | |
3099 | ListBuff er<JCExpre ssion> ele ms = new L istBuffer< JCExpressi on>(); | |
3100 | while (a rgs.nonEmp ty()) { | |
3101 | JCEx pression a rg = trans late(args. head, vara rgsElement ); | |
3102 | elem s.append(a rg); | |
3103 | args = args.ta il; | |
3104 | } | |
3105 | JCNewArr ay boxedAr gs = make. NewArray(m ake.Type(v arargsElem ent), | |
3106 | Lis t.<JCExpre ssion>nil( ), | |
3107 | ele ms.toList( )); | |
3108 | boxedArg s.type = n ew ArrayTy pe(varargs Element, s yms.arrayC lass); | |
3109 | result.a ppend(boxe dArgs); | |
3110 | } else { | |
3111 | if (args .length() != 1) thro w new Asse rtionError (args); | |
3112 | JCExpres sion arg = translate (args.head , paramete r); | |
3113 | anyChang es |= (arg != args.h ead); | |
3114 | result.a ppend(arg) ; | |
3115 | if (!any Changes) r eturn _arg s; | |
3116 | } | |
3117 | re turn resul t.toList() ; | |
3118 | } | |
3119 | ||
3120 | /** Ex pand a box ing or unb oxing conv ersion if needed. */ | |
3121 | @Suppr essWarning s("uncheck ed") // XX X unchecke d | |
3122 | <T ext ends JCTre e> T boxIf Needed(T t ree, Type type) { | |
3123 | bo olean have Primitive = tree.typ e.isPrimit ive(); | |
3124 | if (havePrim itive == t ype.isPrim itive()) | |
3125 | return t ree; | |
3126 | if (havePrim itive) { | |
3127 | Type unb oxedTarget = types.u nboxedType (type); | |
3128 | if (!unb oxedTarget .hasTag(NO NE)) { | |
3129 | if ( !types.isS ubtype(tre e.type, un boxedTarge t)) //e.g. Character c = 89; | |
3130 | tree.type = unboxedT arget.cons tType(tree .type.cons tValue()); | |
3131 | retu rn (T)boxP rimitive(( JCExpressi on)tree, t ype); | |
3132 | } else { | |
3133 | tree = (T)boxP rimitive(( JCExpressi on)tree); | |
3134 | } | |
3135 | } else { | |
3136 | tree = ( T)unbox((J CExpressio n)tree, ty pe); | |
3137 | } | |
3138 | re turn tree; | |
3139 | } | |
3140 | ||
3141 | /** Bo x up a sin gle primit ive expres sion. */ | |
3142 | JCExpr ession box Primitive( JCExpressi on tree) { | |
3143 | re turn boxPr imitive(tr ee, types. boxedClass (tree.type ).type); | |
3144 | } | |
3145 | ||
3146 | /** Bo x up a sin gle primit ive expres sion. */ | |
3147 | JCExpr ession box Primitive( JCExpressi on tree, T ype box) { | |
3148 | ma ke_at(tree .pos()); | |
3149 | if (target.b oxWithCons tructors() ) { | |
3150 | Symbol c tor = look upConstruc tor(tree.p os(), | |
3151 | box, | |
3152 | List.< Type>nil() | |
3153 | .prepe nd(tree.ty pe)); | |
3154 | return m ake.Create (ctor, Lis t.of(tree) ); | |
3155 | } else { | |
3156 | Symbol v alueOfSym = lookupMe thod(tree. pos(), | |
3157 | names .valueOf, | |
3158 | box, | |
3159 | List. <Type>nil( ) | |
3160 | .prep end(tree.t ype)); | |
3161 | return m ake.App(ma ke.QualIde nt(valueOf Sym), List .of(tree)) ; | |
3162 | } | |
3163 | } | |
3164 | ||
3165 | /** Un box an obj ect to a p rimitive v alue. */ | |
3166 | JCExpr ession unb ox(JCExpre ssion tree , Type pri mitive) { | |
3167 | Ty pe unboxed Type = typ es.unboxed Type(tree. type); | |
3168 | if (unboxedT ype.hasTag (NONE)) { | |
3169 | unboxedT ype = prim itive; | |
3170 | if (!unb oxedType.i sPrimitive ()) | |
3171 | thro w new Asse rtionError (unboxedTy pe); | |
3172 | make_at( tree.pos() ); | |
3173 | tree = m ake.TypeCa st(types.b oxedClass( unboxedTyp e).type, t ree); | |
3174 | } else { | |
3175 | // There must be a conversio n from unb oxedType t o primitiv e. | |
3176 | if (!typ es.isSubty pe(unboxed Type, prim itive)) | |
3177 | thro w new Asse rtionError (tree); | |
3178 | } | |
3179 | ma ke_at(tree .pos()); | |
3180 | Sy mbol value Sym = look upMethod(t ree.pos(), | |
3181 | u nboxedType .tsym.name .append(na mes.Value) , // x.int Value() | |
3182 | t ree.type, | |
3183 | L ist.<Type> nil()); | |
3184 | re turn make. App(make.S elect(tree , valueSym )); | |
3185 | } | |
3186 | ||
3187 | /** Vi sitor meth od for par enthesized expressio ns. | |
3188 | * If the subex pression h as changed , omit the parens. | |
3189 | */ | |
3190 | public void visi tParens(JC Parens tre e) { | |
3191 | JC Tree expr = translat e(tree.exp r); | |
3192 | re sult = ((e xpr == tre e.expr) ? tree : exp r); | |
3193 | } | |
3194 | ||
3195 | public void visi tIndexed(J CArrayAcce ss tree) { | |
3196 | tr ee.indexed = transla te(tree.in dexed); | |
3197 | tr ee.index = translate (tree.inde x, syms.in tType); | |
3198 | re sult = tre e; | |
3199 | } | |
3200 | ||
3201 | public void visi tAssign(JC Assign tre e) { | |
3202 | tr ee.lhs = t ranslate(t ree.lhs, t ree); | |
3203 | tr ee.rhs = t ranslate(t ree.rhs, t ree.lhs.ty pe); | |
3204 | ||
3205 | // If transl ated left hand side is an Appl y, we are | |
3206 | // seeing an access me thod invoc ation. In this case, append | |
3207 | // right han d side as last argum ent of the access me thod. | |
3208 | if (tree.lhs .hasTag(AP PLY)) { | |
3209 | JCMethod Invocation app = (JC MethodInvo cation)tre e.lhs; | |
3210 | app.args = List.of (tree.rhs) .prependLi st(app.arg s); | |
3211 | result = app; | |
3212 | } else { | |
3213 | result = tree; | |
3214 | } | |
3215 | } | |
3216 | ||
3217 | public void visi tAssignop( final JCAs signOp tre e) { | |
3218 | JC Tree lhsAc cess = acc ess(TreeIn fo.skipPar ens(tree.l hs)); | |
3219 | fi nal boolea n boxingRe q = !tree. lhs.type.i sPrimitive () && | |
3220 | tree.ope rator.type .getReturn Type().isP rimitive() ; | |
3221 | ||
3222 | if (boxingRe q || lhsAc cess.hasTa g(APPLY)) { | |
3223 | // boxin g required ; need to rewrite as x = (unbo x typeof x )(x op y); | |
3224 | // or if x == (typ eof x)z th en z = (un box typeof x)((typeo f x)z op y ) | |
3225 | // (but without re computing x) | |
3226 | JCTree n ewTree = a bstractLva l(tree.lhs , new Tree Builder() { | |
3227 | public JCT ree build( final JCTr ee lhs) { | |
3228 | JCTree .Tag newTa g = tree.g etTag().no AssignOp() ; | |
3229 | // Era sure (Tran sTypes) ca n change t he type of | |
3230 | // tre e.lhs. Ho wever, we can still get the | |
3231 | // une rased type of tree.l hs as it i s stored | |
3232 | // in tree.type in Attr. | |
3233 | Symbol newOperat or = rs.re solveBinar yOperator( tree.pos() , | |
3234 | newTag, | |
3235 | attrEnv, | |
3236 | tree.type, | |
3237 | tree.rhs.t ype); | |
3238 | JCExpr ession exp r = (JCExp ression)lh s; | |
3239 | if (ex pr.type != tree.type ) | |
3240 | ex pr = make. TypeCast(t ree.type, expr); | |
3241 | JCBina ry opResul t = make.B inary(newT ag, expr, tree.rhs); | |
3242 | opResu lt.operato r = newOpe rator; | |
3243 | opResu lt.type = newOperato r.type.get ReturnType (); | |
3244 | JCExpr ession new Rhs = boxi ngReq ? | |
3245 | ma ke.TypeCas t(types.un boxedType( tree.type) , opResult ) : | |
3246 | op Result; | |
3247 | return make.Assi gn((JCExpr ession)lhs , newRhs). setType(tr ee.type); | |
3248 | } | |
3249 | }); | |
3250 | result = translate (newTree); | |
3251 | return; | |
3252 | } | |
3253 | tr ee.lhs = t ranslate(t ree.lhs, t ree); | |
3254 | tr ee.rhs = t ranslate(t ree.rhs, t ree.operat or.type.ge tParameter Types().ta il.head); | |
3255 | ||
3256 | // If transl ated left hand side is an Appl y, we are | |
3257 | // seeing an access me thod invoc ation. In this case, append | |
3258 | // right han d side as last argum ent of the access me thod. | |
3259 | if (tree.lhs .hasTag(AP PLY)) { | |
3260 | JCMethod Invocation app = (JC MethodInvo cation)tre e.lhs; | |
3261 | // if op eration is a += on s trings, | |
3262 | // make sure to co nvert argu ment to st ring | |
3263 | JCExpres sion rhs = (((Operat orSymbol)t ree.operat or).opcode == string _add) | |
3264 | ? make String(tre e.rhs) | |
3265 | : tree .rhs; | |
3266 | app.args = List.of (rhs).prep endList(ap p.args); | |
3267 | result = app; | |
3268 | } else { | |
3269 | result = tree; | |
3270 | } | |
3271 | } | |
3272 | ||
3273 | /** Lo wer a tree of the fo rm e++ or e-- where e is an ob ject type */ | |
3274 | JCTree lowerBoxe dPostop(fi nal JCUnar y tree) { | |
3275 | // translate to tmp1=l val(e); tm p2=tmp1; t mp1 OP 1; tmp2 | |
3276 | // or | |
3277 | // translate to tmp1=l val(e); tm p2=tmp1; ( typeof tre e)tmp1 OP 1; tmp2 | |
3278 | // where OP is += or - = | |
3279 | fi nal boolea n cast = T reeInfo.sk ipParens(t ree.arg).h asTag(TYPE CAST); | |
3280 | re turn abstr actLval(tr ee.arg, ne w TreeBuil der() { | |
3281 | publ ic JCTree build(fina l JCTree t mp1) { | |
3282 | return abs tractRval( tmp1, tree .arg.type, new TreeB uilder() { | |
3283 | pu blic JCTre e build(fi nal JCTree tmp2) { | |
3284 | JCTree.T ag opcode = (tree.ha sTag(POSTI NC)) | |
3285 | ? PL US_ASG : M INUS_ASG; | |
3286 | JCTree l hs = cast | |
3287 | ? ma ke.TypeCas t(tree.arg .type, (JC Expression )tmp1) | |
3288 | : tm p1; | |
3289 | JCTree u pdate = ma keAssignop (opcode, | |
3290 | lhs, | |
3291 | make.Lite ral(1)); | |
3292 | return m akeComma(u pdate, tmp 2); | |
3293 | } | |
3294 | }); | |
3295 | } | |
3296 | }); | |
3297 | } | |
3298 | ||
3299 | public void visi tUnary(JCU nary tree) { | |
3300 | bo olean isUp dateOperat or = tree. getTag().i sIncOrDecU naryOp(); | |
3301 | if (isUpdate Operator & & !tree.ar g.type.isP rimitive() ) { | |
3302 | switch(t ree.getTag ()) { | |
3303 | case PRE INC: // + + e | |
3304 | // transla te to e += 1 | |
3305 | case PRE DEC: // - - e | |
3306 | // transla te to e -= 1 | |
3307 | { | |
3308 | JCTree.Tag opcode = (tree.hasT ag(PREINC) ) | |
3309 | ? PLUS _ASG : MIN US_ASG; | |
3310 | JCAssignOp newTree = makeAssig nop(opcode , | |
3311 | tree.arg , | |
3312 | make.Lit eral(1)); | |
3313 | result = t ranslate(n ewTree, tr ee.type); | |
3314 | return; | |
3315 | } | |
3316 | case POS TINC: // e ++ | |
3317 | case POS TDEC: // e -- | |
3318 | { | |
3319 | result = t ranslate(l owerBoxedP ostop(tree ), tree.ty pe); | |
3320 | return; | |
3321 | } | |
3322 | } | |
3323 | throw ne w Assertio nError(tre e); | |
3324 | } | |
3325 | ||
3326 | tr ee.arg = b oxIfNeeded (translate (tree.arg, tree), tr ee.type); | |
3327 | ||
3328 | if (tree.has Tag(NOT) & & tree.arg .type.cons tValue() ! = null) { | |
3329 | tree.typ e = cfolde r.fold1(bo ol_not, tr ee.arg.typ e); | |
3330 | } | |
3331 | ||
3332 | // If transl ated left hand side is an Appl y, we are | |
3333 | // seeing an access me thod invoc ation. In this case, return | |
3334 | // that acce ss method invocation as result . | |
3335 | if (isUpdate Operator & & tree.arg .hasTag(AP PLY)) { | |
3336 | result = tree.arg; | |
3337 | } else { | |
3338 | result = tree; | |
3339 | } | |
3340 | } | |
3341 | ||
3342 | public void visi tBinary(JC Binary tre e) { | |
3343 | Li st<Type> f ormals = t ree.operat or.type.ge tParameter Types(); | |
3344 | JC Tree lhs = tree.lhs = translat e(tree.lhs , formals. head); | |
3345 | sw itch (tree .getTag()) { | |
3346 | ca se OR: | |
3347 | if (lhs. type.isTru e()) { | |
3348 | resu lt = lhs; | |
3349 | retu rn; | |
3350 | } | |
3351 | if (lhs. type.isFal se()) { | |
3352 | resu lt = trans late(tree. rhs, forma ls.tail.he ad); | |
3353 | retu rn; | |
3354 | } | |
3355 | break; | |
3356 | ca se AND: | |
3357 | if (lhs. type.isFal se()) { | |
3358 | resu lt = lhs; | |
3359 | retu rn; | |
3360 | } | |
3361 | if (lhs. type.isTru e()) { | |
3362 | resu lt = trans late(tree. rhs, forma ls.tail.he ad); | |
3363 | retu rn; | |
3364 | } | |
3365 | break; | |
3366 | } | |
3367 | tr ee.rhs = t ranslate(t ree.rhs, f ormals.tai l.head); | |
3368 | re sult = tre e; | |
3369 | } | |
3370 | ||
3371 | public void visi tIdent(JCI dent tree) { | |
3372 | re sult = acc ess(tree.s ym, tree, enclOp, fa lse); | |
3373 | } | |
3374 | ||
3375 | /** Tr anslate aw ay the for each loop. */ | |
3376 | public void visi tForeachLo op(JCEnhan cedForLoop tree) { | |
3377 | if (types.el emtype(tre e.expr.typ e) == null ) | |
3378 | visitIte rableForea chLoop(tre e); | |
3379 | el se | |
3380 | visitArr ayForeachL oop(tree); | |
3381 | } | |
3382 | // where | |
3383 | /* * | |
3384 | * A stateme nt of the form | |
3385 | * | |
3386 | * <pre> | |
3387 | * for ( T v : arr ayexpr ) s tmt; | |
3388 | * </pre> | |
3389 | * | |
3390 | * (where ar rayexpr is of an arr ay type) g ets transl ated to | |
3391 | * | |
3392 | * <pre>{@co de | |
3393 | * for ( { arrayty pe #arr = arrayexpr; | |
3394 | * int #le n = array. length; | |
3395 | * int #i = 0; }; | |
3396 | * #i < #len ; i$++ ) { | |
3397 | * T v = arr$[ #i]; | |
3398 | * s tmt; | |
3399 | * } | |
3400 | * }</pre> | |
3401 | * | |
3402 | * where #ar r, #len, a nd #i are freshly na med synthe tic local variables. | |
3403 | * / | |
3404 | pr ivate void visitArra yForeachLo op(JCEnhan cedForLoop tree) { | |
3405 | make_at( tree.expr. pos()); | |
3406 | VarSymbo l arraycac he = new V arSymbol(S YNTHETIC, | |
3407 | n ames.fromS tring("arr " + target .synthetic NameChar() ), | |
3408 | t ree.expr.t ype, | |
3409 | c urrentMeth odSym); | |
3410 | JCStatem ent arrayc achedef = make.VarDe f(arraycac he, tree.e xpr); | |
3411 | VarSymbo l lencache = new Var Symbol(SYN THETIC, | |
3412 | nam es.fromStr ing("len" + target.s yntheticNa meChar()), | |
3413 | sym s.intType, | |
3414 | cur rentMethod Sym); | |
3415 | JCStatem ent lencac hedef = ma ke. | |
3416 | VarD ef(lencach e, make.Se lect(make. Ident(arra ycache), s yms.length Var)); | |
3417 | VarSymbo l index = new VarSym bol(SYNTHE TIC, | |
3418 | names. fromString ("i" + tar get.synthe ticNameCha r()), | |
3419 | syms.i ntType, | |
3420 | curren tMethodSym ); | |
3421 | ||
3422 | JCVariab leDecl ind exdef = ma ke.VarDef( index, mak e.Literal( INT, 0)); | |
3423 | indexdef .init.type = indexde f.type = s yms.intTyp e.constTyp e(0); | |
3424 | ||
3425 | List<JCS tatement> loopinit = List.of(a rraycached ef, lencac hedef, ind exdef); | |
3426 | JCBinary cond = ma keBinary(L T, make.Id ent(index) , make.Ide nt(lencach e)); | |
3427 | ||
3428 | JCExpres sionStatem ent step = make.Exec (makeUnary (PREINC, m ake.Ident( index))); | |
3429 | ||
3430 | Type ele mtype = ty pes.elemty pe(tree.ex pr.type); | |
3431 | JCExpres sion loopv arinit = m ake.Indexe d(make.Ide nt(arrayca che), | |
3432 | make.Ide nt(index)) .setType(e lemtype); | |
3433 | JCVariab leDecl loo pvardef = (JCVariabl eDecl)make .VarDef(tr ee.var.mod s, | |
3434 | tree.var.n ame, | |
3435 | tree.var.v artype, | |
3436 | loopvarini t).setType (tree.var. type); | |
3437 | loopvard ef.sym = t ree.var.sy m; | |
3438 | JCBlock body = mak e. | |
3439 | Bloc k(0, List. of(loopvar def, tree. body)); | |
3440 | ||
3441 | result = translate (make. | |
3442 | ForLoop(l oopinit, | |
3443 | c ond, | |
3444 | L ist.of(ste p), | |
3445 | b ody)); | |
3446 | patchTar gets(body, tree, res ult); | |
3447 | } | |
3448 | /* * Patch up break and continue targets. * / | |
3449 | pr ivate void patchTarg ets(JCTree body, fin al JCTree src, final JCTree de st) { | |
3450 | class Pa tcher exte nds TreeSc anner { | |
3451 | publ ic void vi sitBreak(J CBreak tre e) { | |
3452 | if (tree.t arget == s rc) | |
3453 | tree.t arget = de st; | |
3454 | } | |
3455 | publ ic void vi sitContinu e(JCContin ue tree) { | |
3456 | if (tree.t arget == s rc) | |
3457 | tree.t arget = de st; | |
3458 | } | |
3459 | publ ic void vi sitClassDe f(JCClassD ecl tree) {} | |
3460 | } | |
3461 | new Patc her().scan (body); | |
3462 | } | |
3463 | /* * | |
3464 | * A stateme nt of the form | |
3465 | * | |
3466 | * <pre> | |
3467 | * for ( T v : col l ) stmt ; | |
3468 | * </pre> | |
3469 | * | |
3470 | * (where co ll impleme nts {@code Iterable< ? extends T>}) gets translated to | |
3471 | * | |
3472 | * <pre>{@co de | |
3473 | * for ( Iterator< ? extends T> #i = co ll.iterato r(); #i.ha sNext(); ) { | |
3474 | * T v = (T) # i.next(); | |
3475 | * s tmt; | |
3476 | * } | |
3477 | * }</pre> | |
3478 | * | |
3479 | * where #i is a fresh ly named s ynthetic l ocal varia ble. | |
3480 | * / | |
3481 | pr ivate void visitIter ableForeac hLoop(JCEn hancedForL oop tree) { | |
3482 | make_at( tree.expr. pos()); | |
3483 | Type ite ratorTarge t = syms.o bjectType; | |
3484 | Type ite rableType = types.as Super(type s.cvarUppe rBound(tre e.expr.typ e), | |
3485 | syms .iterableT ype.tsym); | |
3486 | if (iter ableType.g etTypeArgu ments().no nEmpty()) | |
3487 | iter atorTarget = types.e rasure(ite rableType. getTypeArg uments().h ead); | |
3488 | Type eTy pe = tree. expr.type; | |
3489 | while (e Type.hasTa g(TYPEVAR) ) { | |
3490 | eTyp e = eType. getUpperBo und(); | |
3491 | } | |
3492 | tree.exp r.type = t ypes.erasu re(eType); | |
3493 | if (eTyp e.isCompou nd()) | |
3494 | tree .expr = ma ke.TypeCas t(types.er asure(iter ableType), tree.expr ); | |
3495 | Symbol i terator = lookupMeth od(tree.ex pr.pos(), | |
3496 | names.i terator, | |
3497 | eType, | |
3498 | List.<T ype>nil()) ; | |
3499 | VarSymbo l itvar = new VarSym bol(SYNTHE TIC, names .fromStrin g("i" + ta rget.synth eticNameCh ar()), | |
3500 | types. erasure(ty pes.asSupe r(iterator .type.getR eturnType( ), syms.it eratorType .tsym)), | |
3501 | curren tMethodSym ); | |
3502 | ||
3503 | JCState ment init = make. | |
3504 | VarD ef(itvar, make.App(m ake.Select (tree.expr , iterator ) | |
3505 | .setType( types.eras ure(iterat or.type))) ); | |
3506 | ||
3507 | Symbol h asNext = l ookupMetho d(tree.exp r.pos(), | |
3508 | names.ha sNext, | |
3509 | itvar.ty pe, | |
3510 | List.<Ty pe>nil()); | |
3511 | JCMethod Invocation cond = ma ke.App(mak e.Select(m ake.Ident( itvar), ha sNext)); | |
3512 | Symbol n ext = look upMethod(t ree.expr.p os(), | |
3513 | n ames.next, | |
3514 | i tvar.type, | |
3515 | L ist.<Type> nil()); | |
3516 | JCExpres sion varde finit = ma ke.App(mak e.Select(m ake.Ident( itvar), ne xt)); | |
3517 | if (tree .var.type. isPrimitiv e()) | |
3518 | vard efinit = m ake.TypeCa st(types.c varUpperBo und(iterat orTarget), vardefini t); | |
3519 | else | |
3520 | vard efinit = m ake.TypeCa st(tree.va r.type, va rdefinit); | |
3521 | JCVariab leDecl ind exDef = (J CVariableD ecl)make.V arDef(tree .var.mods, | |
3522 | tree.var.n ame, | |
3523 | tree.var.v artype, | |
3524 | vardefinit ).setType( tree.var.t ype); | |
3525 | indexDef .sym = tre e.var.sym; | |
3526 | JCBlock body = mak e.Block(0, List.of(i ndexDef, t ree.body)) ; | |
3527 | body.end pos = Tree Info.endPo s(tree.bod y); | |
3528 | result = translate (make. | |
3529 | ForL oop(List.o f(init), | |
3530 | cond, | |
3531 | List.< JCExpressi onStatemen t>nil(), | |
3532 | body)) ; | |
3533 | patchTar gets(body, tree, res ult); | |
3534 | } | |
3535 | ||
3536 | public void visi tVarDef(JC VariableDe cl tree) { | |
3537 | Me thodSymbol oldMethod Sym = curr entMethodS ym; | |
3538 | tr ee.mods = translate( tree.mods) ; | |
3539 | tr ee.vartype = transla te(tree.va rtype); | |
3540 | if (currentM ethodSym = = null) { | |
3541 | // A cla ss or inst ance field initializ er. | |
3542 | currentM ethodSym = | |
3543 | new MethodSymb ol((tree.m ods.flags& STATIC) | BLOCK, | |
3544 | names.e mpty, null , | |
3545 | current Class); | |
3546 | } | |
3547 | if (tree.ini t != null) tree.init = transla te(tree.in it, tree.t ype); | |
3548 | re sult = tre e; | |
3549 | cu rrentMetho dSym = old MethodSym; | |
3550 | } | |
3551 | ||
3552 | public void visi tBlock(JCB lock tree) { | |
3553 | Me thodSymbol oldMethod Sym = curr entMethodS ym; | |
3554 | if (currentM ethodSym = = null) { | |
3555 | // Block is a stat ic or inst ance initi alizer. | |
3556 | currentM ethodSym = | |
3557 | new MethodSymb ol(tree.fl ags | BLOC K, | |
3558 | names.e mpty, null , | |
3559 | current Class); | |
3560 | } | |
3561 | su per.visitB lock(tree) ; | |
3562 | cu rrentMetho dSym = old MethodSym; | |
3563 | } | |
3564 | ||
3565 | public void visi tDoLoop(JC DoWhileLoo p tree) { | |
3566 | tr ee.body = translate( tree.body) ; | |
3567 | tr ee.cond = translate( tree.cond, syms.bool eanType); | |
3568 | re sult = tre e; | |
3569 | } | |
3570 | ||
3571 | public void visi tWhileLoop (JCWhileLo op tree) { | |
3572 | tr ee.cond = translate( tree.cond, syms.bool eanType); | |
3573 | tr ee.body = translate( tree.body) ; | |
3574 | re sult = tre e; | |
3575 | } | |
3576 | ||
3577 | public void visi tForLoop(J CForLoop t ree) { | |
3578 | tr ee.init = translate( tree.init) ; | |
3579 | if (tree.con d != null) | |
3580 | tree.con d = transl ate(tree.c ond, syms. booleanTyp e); | |
3581 | tr ee.step = translate( tree.step) ; | |
3582 | tr ee.body = translate( tree.body) ; | |
3583 | re sult = tre e; | |
3584 | } | |
3585 | ||
3586 | public void visi tReturn(JC Return tre e) { | |
3587 | if (tree.exp r != null) | |
3588 | tree.exp r = transl ate(tree.e xpr, | |
3589 | types. erasure(cu rrentMetho dDef | |
3590 | .r estype.typ e)); | |
3591 | re sult = tre e; | |
3592 | } | |
3593 | ||
3594 | public void visi tSwitch(JC Switch tre e) { | |
3595 | Ty pe selsupe r = types. supertype( tree.selec tor.type); | |
3596 | bo olean enum Switch = s elsuper != null && | |
3597 | (tree.se lector.typ e.tsym.fla gs() & ENU M) != 0; | |
3598 | bo olean stri ngSwitch = selsuper != null && | |
3599 | types.is SameType(t ree.select or.type, s yms.string Type); | |
3600 | Ty pe target = enumSwit ch ? tree. selector.t ype : | |
3601 | (stringS witch? sym s.stringTy pe : syms. intType); | |
3602 | tr ee.selecto r = transl ate(tree.s elector, t arget); | |
3603 | tr ee.cases = translate Cases(tree .cases); | |
3604 | if (enumSwit ch) { | |
3605 | result = visitEnum Switch(tre e); | |
3606 | } else if (s tringSwitc h) { | |
3607 | result = visitStri ngSwitch(t ree); | |
3608 | } else { | |
3609 | result = tree; | |
3610 | } | |
3611 | } | |
3612 | ||
3613 | public JCTree vi sitEnumSwi tch(JCSwit ch tree) { | |
3614 | Ty peSymbol e numSym = t ree.select or.type.ts ym; | |
3615 | En umMapping map = mapF orEnum(tre e.pos(), e numSym); | |
3616 | ma ke_at(tree .pos()); | |
3617 | Sy mbol ordin alMethod = lookupMet hod(tree.p os(), | |
3618 | names. ordinal, | |
3619 | tree.s elector.ty pe, | |
3620 | List.< Type>nil() ); | |
3621 | JC ArrayAcces s selector = make.In dexed(map. mapVar, | |
3622 | make.App(m ake.Select (tree.sele ctor, | |
3623 | ordinalMe thod))); | |
3624 | Li stBuffer<J CCase> cas es = new L istBuffer< JCCase>(); | |
3625 | fo r (JCCase c : tree.c ases) { | |
3626 | if (c.pa t != null) { | |
3627 | VarS ymbol labe l = (VarSy mbol)TreeI nfo.symbol (c.pat); | |
3628 | JCLi teral pat = map.forC onstant(la bel); | |
3629 | case s.append(m ake.Case(p at, c.stat s)); | |
3630 | } else { | |
3631 | case s.append(c ); | |
3632 | } | |
3633 | } | |
3634 | JC Switch enu mSwitch = make.Switc h(selector , cases.to List()); | |
3635 | pa tchTargets (enumSwitc h, tree, e numSwitch) ; | |
3636 | re turn enumS witch; | |
3637 | } | |
3638 | ||
3639 | public JCTree vi sitStringS witch(JCSw itch tree) { | |
3640 | Li st<JCCase> caseList = tree.get Cases(); | |
3641 | in t alternat ives = cas eList.size (); | |
3642 | ||
3643 | if (alternat ives == 0) { // Stra nge but le gal possib ility | |
3644 | return m ake.at(tre e.pos()).E xec(attr.m akeNullChe ck(tree.ge tExpressio n())); | |
3645 | } else { | |
3646 | /* | |
3647 | * The g eneral app roach used is to tra nslate a s ingle | |
3648 | * strin g switch s tatement i nto a seri es of two chained | |
3649 | * switc h statemen ts: the fi rst a synt hesized st atement | |
3650 | * switc hing on th e argument string's hash value and | |
3651 | * compu ting a str ing's posi tion in th e list of original | |
3652 | * case labels, if any, foll owed by a second swi tch on the | |
3653 | * compu ted intege r value. The second switch ha s the same | |
3654 | * code structure as the ori ginal stri ng switch statement | |
3655 | * excep t that the string ca se labels are replac ed with | |
3656 | * posit ional inte ger consta nts starti ng at 0. | |
3657 | * | |
3658 | * The f irst switc h statemen t can be t hought of as an | |
3659 | * inlin ed map fro m strings to their p osition in the case | |
3660 | * label list. An alternate implement ation woul d use an | |
3661 | * actua l Map for this purpo se, as don e for enum switches. | |
3662 | * | |
3663 | * With some addit ional effo rt, it wou ld be poss ible to | |
3664 | * use a single sw itch state ment on th e hash cod e of the | |
3665 | * argum ent, but c are would need to be taken to preserve | |
3666 | * the p roper cont rol flow i n the pres ence of ha sh | |
3667 | * colli sions and other comp lications, such as | |
3668 | * fallt hroughs. Switch sta tements wi th one or two | |
3669 | * alter natives co uld also b e speciall y translat ed into | |
3670 | * if-th en stateme nts to omi t the comp utation of the hash | |
3671 | * code. | |
3672 | * | |
3673 | * The g enerated c ode assume s that the hashing a lgorithm | |
3674 | * of St ring is th e same in the compil ation envi ronment as | |
3675 | * in th e environm ent the co de will ru n in. The string | |
3676 | * hashi ng algorit hm in the SE JDK has been unch anged | |
3677 | * since at least JDK 1.2. Since the algorithm has been | |
3678 | * speci fied since that rele ase as wel l, it is v ery | |
3679 | * unlik ely to be changed in the futur e. | |
3680 | * | |
3681 | * Diffe rent hashi ng algorit hms, such as the len gth of the | |
3682 | * strin gs or a pe rfect hash ing algori thm over t he | |
3683 | * parti cular set of case la bels, coul d potentia lly be | |
3684 | * used instead of String.ha shCode. | |
3685 | */ | |
3686 | ||
3687 | ListBuff er<JCState ment> stmt List = new ListBuffe r<JCStatem ent>(); | |
3688 | ||
3689 | // Map f rom String case labe ls to thei r original position in | |
3690 | // the l ist of cas e labels. | |
3691 | Map<Stri ng, Intege r> caseLab elToPositi on = | |
3692 | new LinkedHash Map<String , Integer> (alternati ves + 1, 1 .0f); | |
3693 | ||
3694 | // Map o f hash cod es to the string cas e labels h aving that hashCode. | |
3695 | Map<Inte ger, Set<S tring>> ha shToString = | |
3696 | new LinkedHash Map<Intege r, Set<Str ing>>(alte rnatives + 1, 1.0f); | |
3697 | ||
3698 | int case Position = 0; | |
3699 | for(JCCa se oneCase : caseLis t) { | |
3700 | JCEx pression e xpression = oneCase. getExpress ion(); | |
3701 | ||
3702 | if ( expression != null) { // expre ssion for a "default " case is null | |
3703 | String lab elExpr = ( String) ex pression.t ype.constV alue(); | |
3704 | Integer ma pping = ca seLabelToP osition.pu t(labelExp r, casePos ition); | |
3705 | Assert.che ckNull(map ping); | |
3706 | int hashCo de = label Expr.hashC ode(); | |
3707 | ||
3708 | Set<String > stringSe t = hashTo String.get (hashCode) ; | |
3709 | if (string Set == nul l) { | |
3710 | string Set = new LinkedHash Set<String >(1, 1.0f) ; | |
3711 | string Set.add(la belExpr); | |
3712 | hashTo String.put (hashCode, stringSet ); | |
3713 | } else { | |
3714 | boolea n added = stringSet. add(labelE xpr); | |
3715 | Assert .check(add ed); | |
3716 | } | |
3717 | } | |
3718 | case Position++ ; | |
3719 | } | |
3720 | ||
3721 | // Synth esize a sw itch state ment that has the ef fect of | |
3722 | // mappi ng from a string to the intege r position of that | |
3723 | // strin g in the l ist of cas e labels. This is d one by | |
3724 | // switc hing on th e hashCode of the st ring follo wed by an | |
3725 | // if-th en-else ch ain compar ing the in put for eq uality | |
3726 | // with all the ca se labels having tha t hash val ue. | |
3727 | ||
3728 | /* | |
3729 | * s$ = top of sta ck; | |
3730 | * tmp$ = -1; | |
3731 | * switc h($s.hashC ode()) { | |
3732 | * c ase caseLa bel.hashCo de: | |
3733 | * if (s$. equals("ca seLabel_1" ) | |
3734 | * tmp$ = caseLabe lToPositio n("caseLab el_1"); | |
3735 | * else if (s$.equal s("caseLab el_2")) | |
3736 | * tmp$ = caseLabe lToPositio n("caseLab el_2"); | |
3737 | * ... | |
3738 | * break; | |
3739 | * ... | |
3740 | * } | |
3741 | */ | |
3742 | ||
3743 | VarSymbo l dollar_s = new Var Symbol(FIN AL|SYNTHET IC, | |
3744 | nam es.fromStr ing("s" + tree.pos + target.sy ntheticNam eChar()), | |
3745 | sym s.stringTy pe, | |
3746 | cur rentMethod Sym); | |
3747 | stmtList .append(ma ke.at(tree .pos()).Va rDef(dolla r_s, tree. getExpress ion()).set Type(dolla r_s.type)) ; | |
3748 | ||
3749 | VarSymbo l dollar_t mp = new V arSymbol(S YNTHETIC, | |
3750 | n ames.fromS tring("tmp " + tree.p os + targe t.syntheti cNameChar( )), | |
3751 | s yms.intTyp e, | |
3752 | c urrentMeth odSym); | |
3753 | JCVariab leDecl dol lar_tmp_de f = | |
3754 | (JCV ariableDec l)make.Var Def(dollar _tmp, make .Literal(I NT, -1)).s etType(dol lar_tmp.ty pe); | |
3755 | dollar_t mp_def.ini t.type = d ollar_tmp. type = sym s.intType; | |
3756 | stmtList .append(do llar_tmp_d ef); | |
3757 | ListBuff er<JCCase> caseBuffe r = new Li stBuffer<> (); | |
3758 | // hashC ode will t rigger nul lcheck on original s witch expr ession | |
3759 | JCMethod Invocation hashCodeC all = make Call(make. Ident(doll ar_s), | |
3760 | names .hashCode, | |
3761 | List. <JCExpress ion>nil()) .setType(s yms.intTyp e); | |
3762 | JCSwitch switch1 = make.Swit ch(hashCod eCall, | |
3763 | caseBuffer .toList()) ; | |
3764 | for(Map. Entry<Inte ger, Set<S tring>> en try : hash ToString.e ntrySet()) { | |
3765 | int hashCode = entry.get Key(); | |
3766 | Set< String> st ringsWithH ashCode = entry.getV alue(); | |
3767 | Asse rt.check(s tringsWith HashCode.s ize() >= 1 ); | |
3768 | ||
3769 | JCSt atement el separt = n ull; | |
3770 | for( String cas eLabel : s tringsWith HashCode ) { | |
3771 | JCMethodIn vocation s tringEqual sCall = ma keCall(mak e.Ident(do llar_s), | |
3772 | nam es.equals, | |
3773 | Lis t.<JCExpre ssion>of(m ake.Litera l(caseLabe l))); | |
3774 | elsepart = make.If(s tringEqual sCall, | |
3775 | m ake.Exec(m ake.Assign (make.Iden t(dollar_t mp), | |
3776 | make.Lite ral(caseLa belToPosit ion.get(ca seLabel))) . | |
3777 | s etType(dol lar_tmp.ty pe)), | |
3778 | e lsepart); | |
3779 | } | |
3780 | ||
3781 | List Buffer<JCS tatement> lb = new L istBuffer< >(); | |
3782 | JCBr eak breakS tmt = make .Break(nul l); | |
3783 | brea kStmt.targ et = switc h1; | |
3784 | lb.a ppend(else part).appe nd(breakSt mt); | |
3785 | ||
3786 | case Buffer.app end(make.C ase(make.L iteral(has hCode), lb .toList()) ); | |
3787 | } | |
3788 | ||
3789 | switch1. cases = ca seBuffer.t oList(); | |
3790 | stmtList .append(sw itch1); | |
3791 | ||
3792 | // Make isomorphic switch tr ee replaci ng string labels | |
3793 | // with correspond ing intege r ones fro m the labe l to | |
3794 | // posit ion map. | |
3795 | ||
3796 | ListBuff er<JCCase> lb = new ListBuffer <>(); | |
3797 | JCSwitch switch2 = make.Swit ch(make.Id ent(dollar _tmp), lb. toList()); | |
3798 | for(JCCa se oneCase : caseLis t ) { | |
3799 | // R ewire up o ld unlabel ed break s tatements to the | |
3800 | // r eplacement switch be ing create d. | |
3801 | patc hTargets(o neCase, tr ee, switch 2); | |
3802 | ||
3803 | bool ean isDefa ult = (one Case.getEx pression() == null); | |
3804 | JCEx pression c aseExpr; | |
3805 | if ( isDefault) | |
3806 | caseExpr = null; | |
3807 | else { | |
3808 | caseExpr = make.Lite ral(caseLa belToPosit ion.get((S tring)Tree Info.skipP arens(oneC ase. | |
3809 | getE xpression( )). | |
3810 | ty pe.constVa lue())); | |
3811 | } | |
3812 | ||
3813 | lb.a ppend(make .Case(case Expr, | |
3814 | oneC ase.getSta tements()) ); | |
3815 | } | |
3816 | ||
3817 | switch2. cases = lb .toList(); | |
3818 | stmtList .append(sw itch2); | |
3819 | ||
3820 | return m ake.Block( 0L, stmtLi st.toList( )); | |
3821 | } | |
3822 | } | |
3823 | ||
3824 | public void visi tNewArray( JCNewArray tree) { | |
3825 | tr ee.elemtyp e = transl ate(tree.e lemtype); | |
3826 | fo r (List<JC Expression > t = tree .dims; t.t ail != nul l; t = t.t ail) | |
3827 | if (t.he ad != null ) t.head = translate (t.head, s yms.intTyp e); | |
3828 | tr ee.elems = translate (tree.elem s, types.e lemtype(tr ee.type)); | |
3829 | re sult = tre e; | |
3830 | } | |
3831 | ||
3832 | public void visi tSelect(JC FieldAcces s tree) { | |
3833 | // need to s pecial cas e-access o f the form C.super.x | |
3834 | // these wil l always n eed an acc ess method , unless C | |
3835 | // is a defa ult interf ace subcla ssed by th e current class. | |
3836 | bo olean qual ifiedSuper Access = | |
3837 | tree.sel ected.hasT ag(SELECT) && | |
3838 | TreeInfo .name(tree .selected) == names. _super && | |
3839 | !types.i sDirectSup erInterfac e(((JCFiel dAccess)tr ee.selecte d).selecte d.type.tsy m, current Class); | |
3840 | tr ee.selecte d = transl ate(tree.s elected); | |
3841 | if (tree.nam e == names ._class) { | |
3842 | result = classOf(t ree.select ed); | |
3843 | } | |
3844 | el se if (tre e.name == names._sup er && | |
3845 | type s.isDirect SuperInter face(tree. selected.t ype.tsym, currentCla ss)) { | |
3846 | //defaul t super ca ll!! Not a classic q ualified s uper call | |
3847 | TypeSymb ol supSym = tree.sel ected.type .tsym; | |
3848 | Assert.c heckNonNul l(types.as Super(curr entClass.t ype, supSy m)); | |
3849 | result = tree; | |
3850 | } | |
3851 | el se if (tre e.name == names._thi s || tree. name == na mes._super ) { | |
3852 | result = makeThis( tree.pos() , tree.sel ected.type .tsym); | |
3853 | } | |
3854 | el se | |
3855 | result = access(tr ee.sym, tr ee, enclOp , qualifie dSuperAcce ss); | |
3856 | } | |
3857 | ||
3858 | public void visi tLetExpr(L etExpr tre e) { | |
3859 | tr ee.defs = translateV arDefs(tre e.defs); | |
3860 | tr ee.expr = translate( tree.expr, tree.type ); | |
3861 | re sult = tre e; | |
3862 | } | |
3863 | ||
3864 | // The re ought t o be nothi ng to rewr ite here; | |
3865 | // we don't gene rate code. | |
3866 | public void visi tAnnotatio n(JCAnnota tion tree) { | |
3867 | re sult = tre e; | |
3868 | } | |
3869 | ||
3870 | @Overr ide | |
3871 | public void visi tTry(JCTry tree) { | |
3872 | if (tree.res ources.non Empty()) { | |
3873 | result = makeTwrTr y(tree); | |
3874 | return; | |
3875 | } | |
3876 | ||
3877 | bo olean hasB ody = tree .body.getS tatements( ).nonEmpty (); | |
3878 | bo olean hasC atchers = tree.catch ers.nonEmp ty(); | |
3879 | bo olean hasF inally = t ree.finali zer != nul l && | |
3880 | tree .finalizer .getStatem ents().non Empty(); | |
3881 | ||
3882 | if (!hasCatc hers && !h asFinally) { | |
3883 | result = translate (tree.body ); | |
3884 | return; | |
3885 | } | |
3886 | ||
3887 | if (!hasBody ) { | |
3888 | if (hasF inally) { | |
3889 | resu lt = trans late(tree. finalizer) ; | |
3890 | } else { | |
3891 | resu lt = trans late(tree. body); | |
3892 | } | |
3893 | return; | |
3894 | } | |
3895 | ||
3896 | // no optimi zations po ssible | |
3897 | su per.visitT ry(tree); | |
3898 | } | |
3899 | ||
3900 | /********* ********** ********** ********** ********** ********** ********** ***** | |
3901 | * main me thod | |
3902 | ********* ********** ********** ********** ********** ********** ********** ****/ | |
3903 | ||
3904 | /** Tr anslate a toplevel c lass and r eturn a li st consist ing of | |
3905 | * th e translat ed class a nd transla ted versio ns of all inner clas ses. | |
3906 | * @p aram env The attri bution env ironment c urrent at the class definition . | |
3907 | * We need t his for re solving so me additio nal symbol s. | |
3908 | * @p aram cdef The tree representi ng the cla ss definit ion. | |
3909 | */ | |
3910 | public List<JCTr ee> transl ateTopLeve lClass(Env <AttrConte xt> env, J CTree cdef , TreeMake r make) { | |
3911 | Li stBuffer<J CTree> tra nslated = null; | |
3912 | tr y { | |
3913 | attrEnv = env; | |
3914 | this.mak e = make; | |
3915 | endPosTa ble = env. toplevel.e ndPosition s; | |
3916 | currentC lass = nul l; | |
3917 | currentM ethodDef = null; | |
3918 | outermos tClassDef = (cdef.ha sTag(CLASS DEF)) ? (J CClassDecl )cdef : nu ll; | |
3919 | outermos tMemberDef = null; | |
3920 | this.tra nslated = new ListBu ffer<JCTre e>(); | |
3921 | classdef s = new Ha shMap<Clas sSymbol,JC ClassDecl> (); | |
3922 | actualSy mbols = ne w HashMap< Symbol,Sym bol>(); | |
3923 | freevarC ache = new HashMap<C lassSymbol ,List<VarS ymbol>>(); | |
3924 | proxies = new Scop e(syms.noS ymbol); | |
3925 | twrVars = new Scop e(syms.noS ymbol); | |
3926 | outerThi sStack = L ist.nil(); | |
3927 | accessNu ms = new H ashMap<Sym bol,Intege r>(); | |
3928 | accessSy ms = new H ashMap<Sym bol,Method Symbol[]>( ); | |
3929 | accessCo nstrs = ne w HashMap< Symbol,Met hodSymbol> (); | |
3930 | accessCo nstrTags = List.nil( ); | |
3931 | accessed = new Lis tBuffer<Sy mbol>(); | |
3932 | translat e(cdef, (J CExpressio n)null); | |
3933 | for (Lis t<Symbol> l = access ed.toList( ); l.nonEm pty(); l = l.tail) | |
3934 | make Accessible (l.head); | |
3935 | for (Enu mMapping m ap : enumS witchMap.v alues()) | |
3936 | map. translate( ); | |
3937 | checkCon flicts(thi s.translat ed.toList( )); | |
3938 | checkAcc essConstru ctorTags() ; | |
3939 | translat ed = this. translated ; | |
3940 | } finally { | |
3941 | // note that recur sive invoc ations of this metho d fail har d | |
3942 | attrEnv = null; | |
3943 | this.mak e = null; | |
3944 | endPosTa ble = null ; | |
3945 | currentC lass = nul l; | |
3946 | currentM ethodDef = null; | |
3947 | outermos tClassDef = null; | |
3948 | outermos tMemberDef = null; | |
3949 | this.tra nslated = null; | |
3950 | classdef s = null; | |
3951 | actualSy mbols = nu ll; | |
3952 | freevarC ache = nul l; | |
3953 | proxies = null; | |
3954 | outerThi sStack = n ull; | |
3955 | accessNu ms = null; | |
3956 | accessSy ms = null; | |
3957 | accessCo nstrs = nu ll; | |
3958 | accessCo nstrTags = null; | |
3959 | accessed = null; | |
3960 | enumSwit chMap.clea r(); | |
3961 | assertio nsDisabled ClassCache = null; | |
3962 | } | |
3963 | re turn trans lated.toLi st(); | |
3964 | } | |
3965 | } |
Araxis Merge (but not the data content of this report) is Copyright © 1993-2016 Araxis Ltd (www.araxis.com). All rights reserved.