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 | LambdaToMethod.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 | LambdaToMethod.java | Wed Sep 12 16:49:34 2018 UTC |
Description | Between Files 1 and 2 |
|
---|---|---|
Text Blocks | Lines | |
Unchanged | 4 | 4652 |
Changed | 3 | 6 |
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) 201 0, 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 | package co m.sun.tool s.javac.co mp; | |
26 | ||
27 | import com .sun.tools .javac.tre e.*; | |
28 | import com .sun.tools .javac.tre e.JCTree.* ; | |
29 | import com .sun.tools .javac.tre e.JCTree.J CMemberRef erence.Ref erenceKind ; | |
30 | import com .sun.tools .javac.tre e.TreeMake r; | |
31 | import com .sun.tools .javac.tre e.TreeTran slator; | |
32 | import com .sun.tools .javac.cod e.Attribut e; | |
33 | import com .sun.tools .javac.cod e.Kinds; | |
34 | import com .sun.tools .javac.cod e.Scope; | |
35 | import com .sun.tools .javac.cod e.Symbol; | |
36 | import com .sun.tools .javac.cod e.Symbol.C lassSymbol ; | |
37 | import com .sun.tools .javac.cod e.Symbol.D ynamicMeth odSymbol; | |
38 | import com .sun.tools .javac.cod e.Symbol.M ethodSymbo l; | |
39 | import com .sun.tools .javac.cod e.Symbol.T ypeSymbol; | |
40 | import com .sun.tools .javac.cod e.Symbol.V arSymbol; | |
41 | import com .sun.tools .javac.cod e.Symtab; | |
42 | import com .sun.tools .javac.cod e.Type; | |
43 | import com .sun.tools .javac.cod e.Type.Met hodType; | |
44 | import com .sun.tools .javac.cod e.Type.Typ eVar; | |
45 | import com .sun.tools .javac.cod e.Types; | |
46 | import com .sun.tools .javac.com p.LambdaTo Method.Lam bdaAnalyze rPreproces sor.*; | |
47 | import com .sun.tools .javac.com p.Lower.Ba sicFreeVar Collector; | |
48 | import com .sun.tools .javac.jvm .*; | |
49 | import com .sun.tools .javac.uti l.*; | |
50 | import com .sun.tools .javac.uti l.JCDiagno stic.Diagn osticPosit ion; | |
51 | import com .sun.sourc e.tree.Mem berReferen ceTree.Ref erenceMode ; | |
52 | ||
53 | import jav a.util.Enu mMap; | |
54 | import jav a.util.Has hMap; | |
55 | import jav a.util.Has hSet; | |
56 | import jav a.util.Lin kedHashMap ; | |
57 | import jav a.util.Map ; | |
58 | import jav a.util.Set ; | |
59 | ||
60 | import sta tic com.su n.tools.ja vac.comp.L ambdaToMet hod.Lambda SymbolKind .*; | |
61 | import sta tic com.su n.tools.ja vac.code.F lags.*; | |
62 | import sta tic com.su n.tools.ja vac.code.K inds.*; | |
63 | import sta tic com.su n.tools.ja vac.code.T ypeTag.*; | |
64 | import sta tic com.su n.tools.ja vac.tree.J CTree.Tag. *; | |
65 | import jav ax.lang.mo del.type.T ypeKind; | |
66 | ||
67 | /** | |
68 | * This pa ss desugar s lambda e xpressions into stat ic methods | |
69 | * | |
70 | * <p><b> This is NO T part of any suppor ted API. | |
71 | * If you write cod e that dep ends on th is, you do so at you r own risk . | |
72 | * This c ode and it s internal interface s are subj ect to cha nge or | |
73 | * deleti on without notice.</ b> | |
74 | */ | |
75 | public cla ss LambdaT oMethod ex tends Tree Translator { | |
76 | ||
77 | privat e Attr att r; | |
78 | privat e JCDiagno stic.Facto ry diags; | |
79 | privat e Log log; | |
80 | privat e Lower lo wer; | |
81 | privat e Names na mes; | |
82 | privat e Symtab s yms; | |
83 | privat e Resolve rs; | |
84 | privat e TreeMake r make; | |
85 | privat e Types ty pes; | |
86 | privat e TransTyp es transTy pes; | |
87 | privat e Env<Attr Context> a ttrEnv; | |
88 | ||
89 | /** th e analyzer scanner * / | |
90 | privat e LambdaAn alyzerPrep rocessor a nalyzer; | |
91 | ||
92 | /** ma p from lam bda trees to transla tion conte xts */ | |
93 | privat e Map<JCTr ee, Transl ationConte xt<?>> con textMap; | |
94 | ||
95 | /** cu rrent tran slation co ntext (vis itor argum ent) */ | |
96 | privat e Translat ionContext <?> contex t; | |
97 | ||
98 | /** in fo about t he current class bei ng process ed */ | |
99 | privat e KlassInf o kInfo; | |
100 | ||
101 | /** du mp statist ics about lambda cod e generati on */ | |
102 | privat e boolean dumpLambda ToMethodSt ats; | |
103 | ||
104 | /** fo rce serial izable rep resentatio n, for str ess testin g **/ | |
105 | privat e final bo olean forc eSerializa ble; | |
106 | ||
107 | /** Fl ag for alt ernate met afactories indicatin g the lamb da object is intende d to be se rializable */ | |
108 | public static fi nal int FL AG_SERIALI ZABLE = 1 << 0; | |
109 | ||
110 | /** Fl ag for alt ernate met afactories indicatin g the lamb da object has multip le targets */ | |
111 | public static fi nal int FL AG_MARKERS = 1 << 1; | |
112 | ||
113 | /** Fl ag for alt ernate met afactories indicatin g the lamb da object requires m ultiple br idges */ | |
114 | public static fi nal int FL AG_BRIDGES = 1 << 2; | |
115 | ||
116 | // <ed itor-fold defaultsta te="collap sed" desc= "Instantia ting"> | |
117 | protec ted static final Con text.Key<L ambdaToMet hod> unlam bdaKey = | |
118 | new Cont ext.Key<La mbdaToMeth od>(); | |
119 | ||
120 | public static La mbdaToMeth od instanc e(Context context) { | |
121 | La mbdaToMeth od instanc e = contex t.get(unla mbdaKey); | |
122 | if (instance == null) { | |
123 | instance = new Lam bdaToMetho d(context) ; | |
124 | } | |
125 | re turn insta nce; | |
126 | } | |
127 | privat e LambdaTo Method(Con text conte xt) { | |
128 | co ntext.put( unlambdaKe y, this); | |
129 | di ags = JCDi agnostic.F actory.ins tance(cont ext); | |
130 | lo g = Log.in stance(con text); | |
131 | lo wer = Lowe r.instance (context); | |
132 | na mes = Name s.instance (context); | |
133 | sy ms = Symta b.instance (context); | |
134 | rs = Resolve .instance( context); | |
135 | ma ke = TreeM aker.insta nce(contex t); | |
136 | ty pes = Type s.instance (context); | |
137 | tr ansTypes = TransType s.instance (context); | |
138 | an alyzer = n ew LambdaA nalyzerPre processor( ); | |
139 | Op tions opti ons = Opti ons.instan ce(context ); | |
140 | du mpLambdaTo MethodStat s = option s.isSet("d umpLambdaT oMethodSta ts"); | |
141 | at tr = Attr. instance(c ontext); | |
142 | fo rceSeriali zable = op tions.isSe t("forceSe rializable "); | |
143 | } | |
144 | // </e ditor-fold > | |
145 | ||
146 | privat e class Kl assInfo { | |
147 | ||
148 | /* * | |
149 | * list of m ethods to append | |
150 | * / | |
151 | pr ivate List Buffer<JCT ree> appen dedMethodL ist; | |
152 | ||
153 | /* * | |
154 | * list of d eserializa tion cases | |
155 | * / | |
156 | pr ivate fina l Map<Stri ng, ListBu ffer<JCSta tement>> d eserialize Cases; | |
157 | ||
158 | /** | |
159 | * deseriali ze method symbol | |
160 | * / | |
161 | pr ivate fina l MethodSy mbol deser MethodSym; | |
162 | ||
163 | /* * | |
164 | * deseriali ze method parameter symbol | |
165 | * / | |
166 | pr ivate fina l VarSymbo l deserPar amSym; | |
167 | ||
168 | pr ivate fina l JCClassD ecl clazz; | |
169 | ||
170 | pr ivate Klas sInfo(JCCl assDecl cl azz) { | |
171 | this.cla zz = clazz ; | |
172 | appended MethodList = new Lis tBuffer<>( ); | |
173 | deserial izeCases = new HashM ap<String, ListBuffe r<JCStatem ent>>(); | |
174 | MethodTy pe type = new Method Type(List. of(syms.se rializedLa mbdaType), syms.obje ctType, | |
175 | List.<Type >nil(), sy ms.methodC lass); | |
176 | deserMet hodSym = m akePrivate SyntheticM ethod(STAT IC, names. deserializ eLambda, t ype, clazz .sym); | |
177 | deserPar amSym = ne w VarSymbo l(FINAL, n ames.fromS tring("lam bda"), | |
178 | syms.seria lizedLambd aType, des erMethodSy m); | |
179 | } | |
180 | ||
181 | pr ivate void addMethod (JCTree de cl) { | |
182 | appended MethodList = appende dMethodLis t.prepend( decl); | |
183 | } | |
184 | } | |
185 | ||
186 | // <ed itor-fold defaultsta te="collap sed" desc= "translate methods"> | |
187 | @Overr ide | |
188 | public <T extend s JCTree> T translat e(T tree) { | |
189 | Tr anslationC ontext<?> newContext = context Map.get(tr ee); | |
190 | re turn trans late(tree, newContex t != null ? newConte xt : conte xt); | |
191 | } | |
192 | ||
193 | <T ext ends JCTre e> T trans late(T tre e, Transla tionContex t<?> newCo ntext) { | |
194 | Tr anslationC ontext<?> prevContex t = contex t; | |
195 | tr y { | |
196 | context = newConte xt; | |
197 | return s uper.trans late(tree) ; | |
198 | } | |
199 | fi nally { | |
200 | context = prevCont ext; | |
201 | } | |
202 | } | |
203 | ||
204 | <T ext ends JCTre e> List<T> translate (List<T> t rees, Tran slationCon text<?> ne wContext) { | |
205 | Li stBuffer<T > buf = ne w ListBuff er<>(); | |
206 | fo r (T tree : trees) { | |
207 | buf.appe nd(transla te(tree, n ewContext) ); | |
208 | } | |
209 | re turn buf.t oList(); | |
210 | } | |
211 | ||
212 | public JCTree tr anslateTop LevelClass (Env<AttrC ontext> en v, JCTree cdef, Tree Maker make ) { | |
213 | th is.make = make; | |
214 | th is.attrEnv = env; | |
215 | th is.context = null; | |
216 | th is.context Map = new HashMap<JC Tree, Tran slationCon text<?>>() ; | |
217 | re turn trans late(cdef) ; | |
218 | } | |
219 | // </e ditor-fold > | |
220 | ||
221 | // <ed itor-fold defaultsta te="collap sed" desc= "visitor m ethods"> | |
222 | /** | |
223 | * Vis it a class . | |
224 | * Mai ntain the translated MethodList across ne sted class es. | |
225 | * App end the tr anslatedMe thodList t o the clas s after it is transl ated. | |
226 | * @pa ram tree | |
227 | */ | |
228 | @Overr ide | |
229 | public void visi tClassDef( JCClassDec l tree) { | |
230 | if (tree.sym .owner.kin d == PCK) { | |
231 | //analyz e class | |
232 | tree = a nalyzer.an alyzeAndPr eprocessCl ass(tree); | |
233 | } | |
234 | Kl assInfo pr evKlassInf o = kInfo; | |
235 | tr y { | |
236 | kInfo = new KlassI nfo(tree); | |
237 | super.vi sitClassDe f(tree); | |
238 | if (!kIn fo.deseria lizeCases. isEmpty()) { | |
239 | int prevPos = make.pos; | |
240 | try { | |
241 | make.at(tr ee); | |
242 | kInfo.addM ethod(make Deserializ eMethod(tr ee.sym)); | |
243 | } fi nally { | |
244 | make.at(pr evPos); | |
245 | } | |
246 | } | |
247 | //add al l translat ed instanc e methods here | |
248 | List<JCT ree> newMe thods = kI nfo.append edMethodLi st.toList( ); | |
249 | tree.def s = tree.d efs.append List(newMe thods); | |
250 | for (JCT ree lambda : newMeth ods) { | |
251 | tree .sym.membe rs().enter (((JCMetho dDecl)lamb da).sym); | |
252 | } | |
253 | result = tree; | |
254 | } finally { | |
255 | kInfo = prevKlassI nfo; | |
256 | } | |
257 | } | |
258 | ||
259 | /** | |
260 | * Tra nslate a l ambda into a method to be inse rted into the class. | |
261 | * The n replace the lambda site with an invoke dynamic ca ll of to l ambda | |
262 | * met a-factory, which wil l use the lambda met hod. | |
263 | * @pa ram tree | |
264 | */ | |
265 | @Overr ide | |
266 | public void visi tLambda(JC Lambda tre e) { | |
267 | La mbdaTransl ationConte xt localCo ntext = (L ambdaTrans lationCont ext)contex t; | |
268 | Me thodSymbol sym = loc alContext. translated Sym; | |
269 | Me thodType l ambdaType = (MethodT ype) sym.t ype; | |
270 | ||
271 | { | |
272 | Symbol o wner = loc alContext. owner; | |
273 | ListBuff er<Attribu te.TypeCom pound> own erTypeAnno s = new Li stBuffer<A ttribute.T ypeCompoun d>(); | |
274 | ListBuff er<Attribu te.TypeCom pound> lam bdaTypeAnn os = new L istBuffer< Attribute. TypeCompou nd>(); | |
275 | ||
276 | for (Att ribute.Typ eCompound tc : owner .getRawTyp eAttribute s()) { | |
277 | if ( tc.positio n.onLambda == tree) { | |
278 | lambdaType Annos.appe nd(tc); | |
279 | } el se { | |
280 | ownerTypeA nnos.appen d(tc); | |
281 | } | |
282 | } | |
283 | if (lamb daTypeAnno s.nonEmpty ()) { | |
284 | owne r.setTypeA ttributes( ownerTypeA nnos.toLis t()); | |
285 | sym. setTypeAtt ributes(la mbdaTypeAn nos.toList ()); | |
286 | } | |
287 | } | |
288 | ||
289 | // create the method de claration hoisting t he lambda body | |
290 | JC MethodDecl lambdaDec l = make.M ethodDef(m ake.Modifi ers(sym.fl ags_field) , | |
291 | sym. name, | |
292 | make .QualIdent (lambdaTyp e.getRetur nType().ts ym), | |
293 | List .<JCTypePa rameter>ni l(), | |
294 | loca lContext.s yntheticPa rams, | |
295 | lamb daType.get ThrownType s() == nul l ? | |
296 | List.<JCEx pression>n il() : | |
297 | make.Types (lambdaTyp e.getThrow nTypes()), | |
298 | null , | |
299 | null ); | |
300 | la mbdaDecl.s ym = sym; | |
301 | la mbdaDecl.t ype = lamb daType; | |
302 | ||
303 | // translate lambda bod y | |
304 | // As the lam bda body i s translat ed, all re ferences t o lambda l ocals, | |
305 | // captured v ariables, enclosing members ar e adjusted according ly | |
306 | // to refer t o the stat ic method parameters (rather t han i.e. a cessing to | |
307 | // captured m embers dir ectly). | |
308 | la mbdaDecl.b ody = tran slate(make LambdaBody (tree, lam bdaDecl)); | |
309 | ||
310 | // Add the me thod to th e list of methods to be added to this cl ass. | |
311 | kI nfo.addMet hod(lambda Decl); | |
312 | ||
313 | // now that w e have gen erated a m ethod for the lambda expressio n, | |
314 | // we can tra nslate the lambda in to a metho d referenc e pointing to the ne wly | |
315 | // created me thod. | |
316 | // | |
317 | // Note that we need to adjust th e method h andle so t hat it wil l match th e | |
318 | // signature of the SAM descripto r - this m eans that the method reference | |
319 | // should be added the following synthetic arguments: | |
320 | // | |
321 | // * the "th is" argume nt if it i s an insta nce method | |
322 | // * enclosi ng locals captured b y the lamb da express ion | |
323 | ||
324 | Li stBuffer<J CExpressio n> synthet icInits = new ListBu ffer<>(); | |
325 | ||
326 | if (localCon text.metho dReference Receiver ! = null) { | |
327 | syntheti cInits.app end(localC ontext.met hodReferen ceReceiver ); | |
328 | } else if (! sym.isStat ic()) { | |
329 | syntheti cInits.app end(makeTh is( | |
330 | sym.owner. enclClass( ).asType() , | |
331 | localConte xt.owner.e nclClass() )); | |
332 | } | |
333 | ||
334 | // add captur ed locals | |
335 | fo r (Symbol fv : local Context.ge tSymbolMap (CAPTURED_ VAR).keySe t()) { | |
336 | if (fv ! = localCon text.self) { | |
337 | JCTr ee capture d_local = make.Ident (fv).setTy pe(fv.type ); | |
338 | synt heticInits .append((J CExpressio n) capture d_local); | |
339 | } | |
340 | } | |
341 | // add captu red outer this insta nces (used only when `this' ca pture itse lf is ille gal) | |
342 | fo r (Symbol fv : local Context.ge tSymbolMap (CAPTURED_ OUTER_THIS ).keySet() ) { | |
343 | JCTree c aptured_lo cal = make .QualThis( fv.type); | |
344 | syntheti cInits.app end((JCExp ression) c aptured_lo cal); | |
345 | } | |
346 | ||
347 | // then, dete rmine the arguments to the ind y call | |
348 | Li st<JCExpre ssion> ind y_args = t ranslate(s yntheticIn its.toList (), localC ontext.pre v); | |
349 | ||
350 | // build a sa m instance using an indy call to the met a-factory | |
351 | in t refKind = referenc eKind(sym) ; | |
352 | ||
353 | // convert to an invoke dynamic ca ll | |
354 | re sult = mak eMetafacto ryIndyCall (context, refKind, s ym, indy_a rgs); | |
355 | } | |
356 | ||
357 | privat e JCIdent makeThis(T ype type, Symbol own er) { | |
358 | Va rSymbol _t his = new VarSymbol( PARAMETER | FINAL | SYNTHETIC, | |
359 | name s._this, | |
360 | type , | |
361 | owne r); | |
362 | re turn make. Ident(_thi s); | |
363 | } | |
364 | ||
365 | /** | |
366 | * Tra nslate a m ethod refe rence into an invoke dynamic ca ll to the | |
367 | * met a-factory. | |
368 | * @pa ram tree | |
369 | */ | |
370 | @Overr ide | |
371 | public void visi tReference (JCMemberR eference t ree) { | |
372 | Re ferenceTra nslationCo ntext loca lContext = (Referenc eTranslati onContext) context; | |
373 | ||
374 | // first dete rmine the method sym bol to be used to ge nerate the sam insta nce | |
375 | // this is ei ther the m ethod refe rence symb ol, or the bridged r eference s ymbol | |
376 | Sy mbol refSy m = localC ontext.isS ignaturePo lymorphic( ) | |
377 | ? lo calContext .sigPolySy m | |
378 | : tr ee.sym; | |
379 | ||
380 | // the qualif ying expre ssion is t reated as a special captured a rg | |
381 | JC Expression init; | |
382 | sw itch(tree. kind) { | |
383 | ||
384 | case IMP LICIT_INNE R: /** Inner :: n ew */ | |
385 | case SUP ER: /** super :: i nstMethod */ | |
386 | init = makeThi s( | |
387 | localConte xt.owner.e nclClass() .asType(), | |
388 | localConte xt.owner.e nclClass() ); | |
389 | brea k; | |
390 | ||
391 | case BOU ND: /** Expr :: in stMethod * / | |
392 | init = tree.ge tQualifier Expression (); | |
393 | init = attr.ma keNullChec k(init); | |
394 | brea k; | |
395 | ||
396 | case UNB OUND: /** Type :: in stMethod * / | |
397 | case STA TIC: /** Type :: st aticMethod */ | |
398 | case TOP LEVEL: /** Top level :: new */ | |
399 | case ARR AY_CTOR: /** ArrayType :: new */ | |
400 | init = null; | |
401 | brea k; | |
402 | ||
403 | default: | |
404 | thro w new Inte rnalError( "Should no t have an invalid ki nd"); | |
405 | } | |
406 | ||
407 | Li st<JCExpre ssion> ind y_args = i nit==null? List.<JCE xpression> nil() : tr anslate(Li st.of(init ), localCo ntext.prev ); | |
408 | ||
409 | ||
410 | // build a sa m instance using an indy call to the met a-factory | |
411 | re sult = mak eMetafacto ryIndyCall (localCont ext, local Context.re ferenceKin d(), refSy m, indy_ar gs); | |
412 | } | |
413 | ||
414 | /** | |
415 | * Tra nslate ide ntifiers w ithin a la mbda to th e mapped i dentifier | |
416 | * @pa ram tree | |
417 | */ | |
418 | @Overr ide | |
419 | public void visi tIdent(JCI dent tree) { | |
420 | if (context == null || !analyzer .lambdaIde ntSymbolFi lter(tree. sym)) { | |
421 | super.vi sitIdent(t ree); | |
422 | } else { | |
423 | int prev Pos = make .pos; | |
424 | try { | |
425 | make .at(tree); | |
426 | ||
427 | Lamb daTranslat ionContext lambdaCon text = (La mbdaTransl ationConte xt) contex t; | |
428 | JCTr ee ltree = lambdaCon text.trans late(tree) ; | |
429 | if ( ltree != n ull) { | |
430 | result = l tree; | |
431 | } el se { | |
432 | //access t o untransl ated symbo ls (i.e. c ompile-tim e constant s, | |
433 | //members defined in side the l ambda body , etc.) ) | |
434 | super.visi tIdent(tre e); | |
435 | } | |
436 | } finall y { | |
437 | make .at(prevPo s); | |
438 | } | |
439 | } | |
440 | } | |
441 | ||
442 | /** | |
443 | * Tra nslate qua lified `th is' refere nces withi n a lambda to the ma pped ident ifier | |
444 | * @pa ram tree | |
445 | */ | |
446 | @Overr ide | |
447 | public void visi tSelect(JC FieldAcces s tree) { | |
448 | if (context == null || !analyzer .lambdaFie ldAccessFi lter(tree) ) { | |
449 | super.vi sitSelect( tree); | |
450 | } else { | |
451 | int prev Pos = make .pos; | |
452 | try { | |
453 | make .at(tree); | |
454 | ||
455 | Lamb daTranslat ionContext lambdaCon text = (La mbdaTransl ationConte xt) contex t; | |
456 | JCTr ee ltree = lambdaCon text.trans late(tree) ; | |
457 | if ( ltree != n ull) { | |
458 | result = l tree; | |
459 | } el se { | |
460 | super.visi tSelect(tr ee); | |
461 | } | |
462 | } finall y { | |
463 | make .at(prevPo s); | |
464 | } | |
465 | } | |
466 | } | |
467 | ||
468 | @Overr ide | |
469 | public void visi tVarDef(JC VariableDe cl tree) { | |
470 | La mbdaTransl ationConte xt lambdaC ontext = ( LambdaTran slationCon text)conte xt; | |
471 | if (context != null && lambdaCon text.getSy mbolMap(LO CAL_VAR).c ontainsKey (tree.sym) ) { | |
472 | tree.ini t = transl ate(tree.i nit); | |
473 | tree.sym = (VarSym bol) lambd aContext.g etSymbolMa p(LOCAL_VA R).get(tre e.sym); | |
474 | result = tree; | |
475 | } else if (c ontext != null && la mbdaContex t.getSymbo lMap(TYPE_ VAR).conta insKey(tre e.sym)) { | |
476 | JCExpres sion init = translat e(tree.ini t); | |
477 | VarSymbo l xsym = ( VarSymbol) lambdaCont ext.getSym bolMap(TYP E_VAR).get (tree.sym) ; | |
478 | int prev Pos = make .pos; | |
479 | try { | |
480 | resu lt = make. at(tree).V arDef(xsym , init); | |
481 | } finall y { | |
482 | make .at(prevPo s); | |
483 | } | |
484 | // Repla ce the ent ered symbo l for this variable | |
485 | Scope sc = tree.sy m.owner.me mbers(); | |
486 | if (sc ! = null) { | |
487 | sc.r emove(tree .sym); | |
488 | sc.e nter(xsym) ; | |
489 | } | |
490 | } else { | |
491 | super.vi sitVarDef( tree); | |
492 | } | |
493 | } | |
494 | ||
495 | // </e ditor-fold > | |
496 | ||
497 | // <ed itor-fold defaultsta te="collap sed" desc= "Translati on helper methods"> | |
498 | ||
499 | privat e JCBlock makeLambda Body(JCLam bda tree, JCMethodDe cl lambdaM ethodDecl) { | |
500 | re turn tree. getBodyKin d() == JCL ambda.Body Kind.EXPRE SSION ? | |
501 | make LambdaExpr essionBody ((JCExpres sion)tree. body, lamb daMethodDe cl) : | |
502 | make LambdaStat ementBody( (JCBlock)t ree.body, lambdaMeth odDecl, tr ee.canComp leteNormal ly); | |
503 | } | |
504 | ||
505 | privat e JCBlock makeLambda Expression Body(JCExp ression ex pr, JCMeth odDecl lam bdaMethodD ecl) { | |
506 | Ty pe restype = lambdaM ethodDecl. type.getRe turnType() ; | |
507 | bo olean isLa mbda_void = expr.typ e.hasTag(V OID); | |
508 | bo olean isTa rget_void = restype. hasTag(VOI D); | |
509 | bo olean isTa rget_Void = types.is SameType(r estype, ty pes.boxedC lass(syms. voidType). type); | |
510 | in t prevPos = make.pos ; | |
511 | tr y { | |
512 | if (isTa rget_void) { | |
513 | //ta rget is vo id: | |
514 | // B ODY; | |
515 | JCSt atement st at = make. at(expr).E xec(expr); | |
516 | retu rn make.Bl ock(0, Lis t.<JCState ment>of(st at)); | |
517 | } else i f (isLambd a_void && isTarget_V oid) { | |
518 | //vo id to Void conversio n: | |
519 | // B ODY; retur n null; | |
520 | List Buffer<JCS tatement> stats = ne w ListBuff er<>(); | |
521 | stat s.append(m ake.at(exp r).Exec(ex pr)); | |
522 | stat s.append(m ake.Return (make.Lite ral(BOT, n ull).setTy pe(syms.bo tType))); | |
523 | retu rn make.Bl ock(0, sta ts.toList( )); | |
524 | } else { | |
525 | //no n-void to non-void c onversion: | |
526 | // r eturn (TYP E)BODY; | |
527 | JCEx pression r etExpr = t ransTypes. coerce(att rEnv, expr , restype) ; | |
528 | retu rn make.at (retExpr). Block(0, L ist.<JCSta tement>of( make.Retur n(retExpr) )); | |
529 | } | |
530 | } finally { | |
531 | make.at( prevPos); | |
532 | } | |
533 | } | |
534 | ||
535 | privat e JCBlock makeLambda StatementB ody(JCBloc k block, f inal JCMet hodDecl la mbdaMethod Decl, bool ean comple teNormally ) { | |
536 | fi nal Type r estype = l ambdaMetho dDecl.type .getReturn Type(); | |
537 | fi nal boolea n isTarget _void = re stype.hasT ag(VOID); | |
538 | bo olean isTa rget_Void = types.is SameType(r estype, ty pes.boxedC lass(syms. voidType). type); | |
539 | ||
540 | cl ass Lambda BodyTransl ator exten ds TreeTra nslator { | |
541 | ||
542 | @Overrid e | |
543 | public v oid visitC lassDef(JC ClassDecl tree) { | |
544 | //do NOT recur se on any inner clas ses | |
545 | resu lt = tree; | |
546 | } | |
547 | ||
548 | @Overrid e | |
549 | public v oid visitL ambda(JCLa mbda tree) { | |
550 | //do NOT recur se on any nested lam bdas | |
551 | resu lt = tree; | |
552 | } | |
553 | ||
554 | @Overrid e | |
555 | public v oid visitR eturn(JCRe turn tree) { | |
556 | bool ean isLamb da_void = tree.expr == null; | |
557 | if ( isTarget_v oid && !is Lambda_voi d) { | |
558 | //Void to void conve rsion: | |
559 | // { TYPE $loc = RET -EXPR; ret urn; } | |
560 | VarSymbol loc = make SyntheticV ar(0, name s.fromStri ng("$loc") , tree.exp r.type, la mbdaMethod Decl.sym); | |
561 | JCVariable Decl varDe f = make.V arDef(loc, tree.expr ); | |
562 | result = m ake.Block( 0, List.<J CStatement >of(varDef , make.Ret urn(null)) ); | |
563 | } el se if (!is Target_voi d || !isLa mbda_void) { | |
564 | //non-void to non-vo id convers ion: | |
565 | // return (TYPE)RET- EXPR; | |
566 | tree.expr = transTyp es.coerce( attrEnv, t ree.expr, restype); | |
567 | result = t ree; | |
568 | } el se { | |
569 | result = t ree; | |
570 | } | |
571 | ||
572 | } | |
573 | } | |
574 | ||
575 | JC Block tran s_block = new Lambda BodyTransl ator().tra nslate(blo ck); | |
576 | if (complete Normally & & isTarget _Void) { | |
577 | //there' s no retur n statemen t and the lambda (po ssibly inf erred) | |
578 | //return type is j ava.lang.V oid; emit a syntheti c return s tatement | |
579 | trans_bl ock.stats = trans_bl ock.stats. append(mak e.Return(m ake.Litera l(BOT, nul l).setType (syms.botT ype))); | |
580 | } | |
581 | re turn trans _block; | |
582 | } | |
583 | ||
584 | privat e JCMethod Decl makeD eserialize Method(Sym bol kSym) { | |
585 | Li stBuffer<J CCase> cas es = new L istBuffer< >(); | |
586 | Li stBuffer<J CBreak> br eaks = new ListBuffe r<>(); | |
587 | fo r (Map.Ent ry<String, ListBuffe r<JCStatem ent>> entr y : kInfo. deserializ eCases.ent rySet()) { | |
588 | JCBreak br = make. Break(null ); | |
589 | breaks.a dd(br); | |
590 | List<JCS tatement> stmts = en try.getVal ue().appen d(br).toLi st(); | |
591 | cases.ad d(make.Cas e(make.Lit eral(entry .getKey()) , stmts)); | |
592 | } | |
593 | JC Switch sw = make.Swi tch(deserG etter("get ImplMethod Name", sym s.stringTy pe), cases .toList()) ; | |
594 | fo r (JCBreak br : brea ks) { | |
595 | br.targe t = sw; | |
596 | } | |
597 | JC Block body = make.Bl ock(0L, Li st.<JCStat ement>of( | |
598 | sw, | |
599 | make .Throw(mak eNewClass( | |
600 | syms.illeg alArgument ExceptionT ype, | |
601 | List.<JCEx pression>o f(make.Lit eral("Inva lid lambda deseriali zation"))) ))); | |
602 | JC MethodDecl deser = m ake.Method Def(make.M odifiers(k Info.deser MethodSym. flags()), | |
603 | names. deserializ eLambda, | |
604 | make.Q ualIdent(k Info.deser MethodSym. getReturnT ype().tsym ), | |
605 | List.< JCTypePara meter>nil( ), | |
606 | List.o f(make.Var Def(kInfo. deserParam Sym, null) ), | |
607 | List.< JCExpressi on>nil(), | |
608 | body, | |
609 | null); | |
610 | de ser.sym = kInfo.dese rMethodSym ; | |
611 | de ser.type = kInfo.des erMethodSy m.type; | |
612 | // System.err .printf("D ESER: '%s' \n", deser ); | |
613 | re turn deser ; | |
614 | } | |
615 | ||
616 | /** Ma ke an attr ibuted cla ss instanc e creation expressio n. | |
617 | * @p aram ctype The cl ass type. | |
618 | * @p aram args The co nstructor arguments. | |
619 | * @p aram cons The co nstructor symbol | |
620 | */ | |
621 | JCNewC lass makeN ewClass(Ty pe ctype, List<JCExp ression> a rgs, Symbo l cons) { | |
622 | JC NewClass t ree = make .NewClass( null, | |
623 | null, ma ke.QualIde nt(ctype.t sym), args , null); | |
624 | tr ee.constru ctor = con s; | |
625 | tr ee.type = ctype; | |
626 | re turn tree; | |
627 | } | |
628 | ||
629 | /** Ma ke an attr ibuted cla ss instanc e creation expressio n. | |
630 | * @p aram ctype The cl ass type. | |
631 | * @p aram args The co nstructor arguments. | |
632 | */ | |
633 | JCNewC lass makeN ewClass(Ty pe ctype, List<JCExp ression> a rgs) { | |
634 | re turn makeN ewClass(ct ype, args, | |
635 | rs.r esolveCons tructor(nu ll, attrEn v, ctype, TreeInfo.t ypes(args) , List.<Ty pe>nil())) ; | |
636 | } | |
637 | ||
638 | privat e void add Deserializ ationCase( int implMe thodKind, Symbol ref Sym, Type targetType , MethodSy mbol samSy m, | |
639 | Diagnost icPosition pos, List <Object> s taticArgs, MethodTyp e indyType ) { | |
640 | St ring funct ionalInter faceClass = classSig (targetTyp e); | |
641 | St ring funct ionalInter faceMethod Name = sam Sym.getSim pleName(). toString() ; | |
642 | St ring funct ionalInter faceMethod Signature = typeSig( types.eras ure(samSym .type)); | |
643 | St ring implC lass = cla ssSig(type s.erasure( refSym.own er.type)); | |
644 | St ring implM ethodName = refSym.g etQualifie dName().to String(); | |
645 | St ring implM ethodSigna ture = typ eSig(types .erasure(r efSym.type )); | |
646 | ||
647 | JC Expression kindTest = eqTest(s yms.intTyp e, deserGe tter("getI mplMethodK ind", syms .intType), make.Lite ral(implMe thodKind)) ; | |
648 | Li stBuffer<J CExpressio n> serArgs = new Lis tBuffer<>( ); | |
649 | in t i = 0; | |
650 | fo r (Type t : indyType .getParame terTypes() ) { | |
651 | List<JCE xpression> indexAsAr g = new Li stBuffer<J CExpressio n>().appen d(make.Lit eral(i)).t oList(); | |
652 | List<Typ e> argType s = new Li stBuffer<T ype>().app end(syms.i ntType).to List(); | |
653 | serArgs. add(make.T ypeCast(ty pes.erasur e(t), dese rGetter("g etCaptured Arg", syms .objectTyp e, argType s, indexAs Arg))); | |
654 | ++i; | |
655 | } | |
656 | JC Statement stmt = mak e.If( | |
657 | dese rTest(dese rTest(dese rTest(dese rTest(dese rTest( | |
658 | kindTest, | |
659 | "getFuncti onalInterf aceClass", functiona lInterface Class), | |
660 | "getFuncti onalInterf aceMethodN ame", func tionalInte rfaceMetho dName), | |
661 | "getFuncti onalInterf aceMethodS ignature", functiona lInterface MethodSign ature), | |
662 | "getImplCl ass", impl Class), | |
663 | "getImplMe thodSignat ure", impl MethodSign ature), | |
664 | make .Return(ma keIndyCall ( | |
665 | pos, | |
666 | syms.lambd aMetafacto ry, | |
667 | names.altM etafactory , | |
668 | staticArgs , indyType , serArgs. toList(), samSym.nam e)), | |
669 | null ); | |
670 | Li stBuffer<J CStatement > stmts = kInfo.dese rializeCas es.get(imp lMethodNam e); | |
671 | if (stmts == null) { | |
672 | stmts = new ListBu ffer<>(); | |
673 | kInfo.de serializeC ases.put(i mplMethodN ame, stmts ); | |
674 | } | |
675 | /* *** | |
676 | Sy stem.err.p rintf("+++ ++++++++++ ++++\n"); | |
677 | Sy stem.err.p rintf("*fu nctionalIn terfaceCla ss: '%s'\n ", functio nalInterfa ceClass); | |
678 | Sy stem.err.p rintf("*fu nctionalIn terfaceMet hodName: ' %s'\n", fu nctionalIn terfaceMet hodName); | |
679 | Sy stem.err.p rintf("*fu nctionalIn terfaceMet hodSignatu re: '%s'\n ", functio nalInterfa ceMethodSi gnature); | |
680 | Sy stem.err.p rintf("*im plMethodKi nd: %d\n", implMetho dKind); | |
681 | Sy stem.err.p rintf("*im plClass: ' %s'\n", im plClass); | |
682 | Sy stem.err.p rintf("*im plMethodNa me: '%s'\n ", implMet hodName); | |
683 | Sy stem.err.p rintf("*im plMethodSi gnature: ' %s'\n", im plMethodSi gnature); | |
684 | ** **/ | |
685 | st mts.append (stmt); | |
686 | } | |
687 | ||
688 | privat e JCExpres sion eqTes t(Type arg Type, JCEx pression a rg1, JCExp ression ar g2) { | |
689 | JC Binary tes tExpr = ma ke.Binary( JCTree.Tag .EQ, arg1, arg2); | |
690 | te stExpr.ope rator = rs .resolveBi naryOperat or(null, J CTree.Tag. EQ, attrEn v, argType , argType) ; | |
691 | te stExpr.set Type(syms. booleanTyp e); | |
692 | re turn testE xpr; | |
693 | } | |
694 | ||
695 | privat e JCExpres sion deser Test(JCExp ression pr ev, String func, Str ing lit) { | |
696 | Me thodType e qmt = new MethodType (List.of(s yms.object Type), sym s.booleanT ype, List. <Type>nil( ), syms.me thodClass) ; | |
697 | Sy mbol eqsym = rs.reso lveQualifi edMethod(n ull, attrE nv, syms.o bjectType, names.equ als, List. of(syms.ob jectType), List.<Typ e>nil()); | |
698 | JC MethodInvo cation eqt est = make .Apply( | |
699 | List .<JCExpres sion>nil() , | |
700 | make .Select(de serGetter( func, syms .stringTyp e), eqsym) .setType(e qmt), | |
701 | List .<JCExpres sion>of(ma ke.Literal (lit))); | |
702 | eq test.setTy pe(syms.bo oleanType) ; | |
703 | JC Binary com pound = ma ke.Binary( JCTree.Tag .AND, prev , eqtest); | |
704 | co mpound.ope rator = rs .resolveBi naryOperat or(null, J CTree.Tag. AND, attrE nv, syms.b ooleanType , syms.boo leanType); | |
705 | co mpound.set Type(syms. booleanTyp e); | |
706 | re turn compo und; | |
707 | } | |
708 | ||
709 | privat e JCExpres sion deser Getter(Str ing func, Type type) { | |
710 | re turn deser Getter(fun c, type, L ist.<Type> nil(), Lis t.<JCExpre ssion>nil( )); | |
711 | } | |
712 | ||
713 | privat e JCExpres sion deser Getter(Str ing func, Type type, List<Type > argTypes , List<JCE xpression> args) { | |
714 | Me thodType g etmt = new MethodTyp e(argTypes , type, Li st.<Type>n il(), syms .methodCla ss); | |
715 | Sy mbol getsy m = rs.res olveQualif iedMethod( null, attr Env, syms. serialized LambdaType , names.fr omString(f unc), argT ypes, List .<Type>nil ()); | |
716 | re turn make. Apply( | |
717 | List.<JCEx pression>n il(), | |
718 | make.Selec t(make.Ide nt(kInfo.d eserParamS ym).setTyp e(syms.ser ializedLam bdaType), getsym).se tType(getm t), | |
719 | args).setT ype(type); | |
720 | } | |
721 | ||
722 | /** | |
723 | * Cre ate new sy nthetic me thod with given flag s, name, t ype, owner | |
724 | */ | |
725 | privat e MethodSy mbol makeP rivateSynt heticMetho d(long fla gs, Name n ame, Type type, Symb ol owner) { | |
726 | re turn new M ethodSymbo l(flags | SYNTHETIC | PRIVATE, name, typ e, owner); | |
727 | } | |
728 | ||
729 | /** | |
730 | * Cre ate new sy nthetic va riable wit h given fl ags, name, type, own er | |
731 | */ | |
732 | privat e VarSymbo l makeSynt heticVar(l ong flags, String na me, Type t ype, Symbo l owner) { | |
733 | re turn makeS yntheticVa r(flags, n ames.fromS tring(name ), type, o wner); | |
734 | } | |
735 | ||
736 | /** | |
737 | * Cre ate new sy nthetic va riable wit h given fl ags, name, type, own er | |
738 | */ | |
739 | privat e VarSymbo l makeSynt heticVar(l ong flags, Name name , Type typ e, Symbol owner) { | |
740 | re turn new V arSymbol(f lags | SYN THETIC, na me, type, owner); | |
741 | } | |
742 | ||
743 | /** | |
744 | * Set varargsEl ement fiel d on a giv en tree (m ust be eit her a new class tree | |
745 | * or a method c all tree) | |
746 | */ | |
747 | privat e void set VarargsIfN eeded(JCTr ee tree, T ype vararg sElement) { | |
748 | if (varargsE lement != null) { | |
749 | switch ( tree.getTa g()) { | |
750 | case APPLY: (( JCMethodIn vocation)t ree).varar gsElement = varargsE lement; br eak; | |
751 | case NEWCLASS: ((JCNewCl ass)tree). varargsEle ment = var argsElemen t; break; | |
752 | defa ult: throw new Asser tionError( ); | |
753 | } | |
754 | } | |
755 | } | |
756 | ||
757 | /** | |
758 | * Con vert metho d/construc tor argume nts by ins erting app ropriate c ast | |
759 | * as required b y type-era sure - thi s is neede d when bri dging a la mbda/metho d | |
760 | * ref erence, as the bridg ed signatu re might r equire dow ncast to b e compatib le | |
761 | * wit h the gene rated sign ature. | |
762 | */ | |
763 | privat e List<JCE xpression> convertAr gs(Symbol meth, List <JCExpress ion> args, Type vara rgsElement ) { | |
764 | Ass ert.check( meth.kind == Kinds.M TH); | |
765 | Lis t<Type> fo rmals = ty pes.erasur e(meth.typ e).getPara meterTypes (); | |
766 | if (varargsEl ement != n ull) { | |
767 | Assert.ch eck((meth. flags() & VARARGS) ! = 0); | |
768 | } | |
769 | ret urn transT ypes.trans lateArgs(a rgs, forma ls, vararg sElement, attrEnv); | |
770 | } | |
771 | ||
772 | // </e ditor-fold > | |
773 | ||
774 | /** | |
775 | * Con verts a me thod refer ence which cannot be used dire ctly into a lambda | |
776 | */ | |
777 | privat e class Me mberRefere nceToLambd a { | |
778 | ||
779 | pr ivate fina l JCMember Reference tree; | |
780 | pr ivate fina l Referenc eTranslati onContext localConte xt; | |
781 | pr ivate fina l Symbol o wner; | |
782 | pr ivate fina l ListBuff er<JCExpre ssion> arg s = new Li stBuffer<> (); | |
783 | pr ivate fina l ListBuff er<JCVaria bleDecl> p arams = ne w ListBuff er<>(); | |
784 | ||
785 | pr ivate JCEx pression r eceiverExp ression = null; | |
786 | ||
787 | Me mberRefere nceToLambd a(JCMember Reference tree, Refe renceTrans lationCont ext localC ontext, Sy mbol owner ) { | |
788 | this.tre e = tree; | |
789 | this.loc alContext = localCon text; | |
790 | this.own er = owner ; | |
791 | } | |
792 | ||
793 | JC Lambda lam bda() { | |
794 | int prev Pos = make .pos; | |
795 | try { | |
796 | make .at(tree); | |
797 | ||
798 | //bo dy generat ion - this can be ei ther a met hod call o r a | |
799 | //ne w instance creation expression , dependin g on the m ember refe rence kind | |
800 | VarS ymbol rcvr = addPara metersRetu rnReceiver (); | |
801 | JCEx pression e xpr = (tre e.getMode( ) == Refer enceMode.I NVOKE) | |
802 | ? expr essionInvo ke(rcvr) | |
803 | : expr essionNew( ); | |
804 | ||
805 | JCLa mbda slam = make.Lam bda(params .toList(), expr); | |
806 | slam .targets = tree.targ ets; | |
807 | slam .type = tr ee.type; | |
808 | slam .pos = tre e.pos; | |
809 | retu rn slam; | |
810 | } finall y { | |
811 | make .at(prevPo s); | |
812 | } | |
813 | } | |
814 | ||
815 | /* * | |
816 | * Generate the parame ter list f or the con verted mem ber refere nce. | |
817 | * | |
818 | * @return T he receive r variable symbol, i f any | |
819 | * / | |
820 | Va rSymbol ad dParameter sReturnRec eiver() { | |
821 | Type sam Desc = loc alContext. bridgedRef Sig(); | |
822 | List<Typ e> samPTyp es = samDe sc.getPara meterTypes (); | |
823 | List<Typ e> descPTy pes = tree .getDescri ptorType(t ypes).getP arameterTy pes(); | |
824 | ||
825 | // Deter mine the r eceiver, i f any | |
826 | VarSymbo l rcvr; | |
827 | switch ( tree.kind) { | |
828 | case BOUND: | |
829 | // The rec eiver is e xplicit in the metho d referenc e | |
830 | rcvr = add Parameter( "rec$", tr ee.getQual ifierExpre ssion().ty pe, false) ; | |
831 | receiverEx pression = attr.make NullCheck( tree.getQu alifierExp ression()) ; | |
832 | break; | |
833 | case UNBOUND: | |
834 | // The rec eiver is t he first p arameter, extract it and | |
835 | // adjust the SAM an d unerased type list s accordin gly | |
836 | rcvr = add Parameter( "rec$", sa mDesc.getP arameterTy pes().head , false); | |
837 | samPTypes = samPType s.tail; | |
838 | descPTypes = descPTy pes.tail; | |
839 | break; | |
840 | defa ult: | |
841 | rcvr = nul l; | |
842 | break; | |
843 | } | |
844 | List<Typ e> implPTy pes = tree .sym.type. getParamet erTypes(); | |
845 | int impl Size = imp lPTypes.si ze(); | |
846 | int samS ize = samP Types.size (); | |
847 | // Last parameter to copy fr om referen ced method , exclude final var args | |
848 | int last = localCo ntext.need sVarArgsCo nversion() ? implSiz e - 1 : im plSize; | |
849 | ||
850 | // Fails afe -- ass ure match- up | |
851 | boolean checkForIn tersection = tree.va rargsEleme nt != null || implSi ze == desc PTypes.siz e(); | |
852 | ||
853 | // Use p arameter t ypes of th e implemen tation met hod unless the unera sed | |
854 | // SAM p arameter t ype is an intersecti on type, i n that cas e use the | |
855 | // erase d SAM para meter type so that t he superty pe relatio nship | |
856 | // the i mplementat ion method parameter s is not o bscured. | |
857 | // Note: in this l oop, the l ists implP Types, sam PTypes, an d descPTyp es | |
858 | // are u sed as poi nters to t he current parameter type info rmation | |
859 | // and a re thus no t usable a fterwards. | |
860 | for (int i = 0; im plPTypes.n onEmpty() && i < las t; ++i) { | |
861 | // B y default use the im plementati on method parmeter t ype | |
862 | Type parmType = implPTyp es.head; | |
863 | // I f the uner ased param eter type is a type variable w hose | |
864 | // b ound is an intersect ion (eg. < T extends A & B>) th en | |
865 | // u se the SAM parameter type | |
866 | if ( checkForIn tersection && descPT ypes.head. getKind() == TypeKin d.TYPEVAR) { | |
867 | TypeVar tv = (TypeVa r) descPTy pes.head; | |
868 | if (tv.bou nd.getKind () == Type Kind.INTER SECTION) { | |
869 | parmTy pe = samPT ypes.head; | |
870 | } | |
871 | } | |
872 | addP arameter(" x$" + i, p armType, t rue); | |
873 | ||
874 | // A dvance to the next p arameter | |
875 | impl PTypes = i mplPTypes. tail; | |
876 | samP Types = sa mPTypes.ta il; | |
877 | desc PTypes = d escPTypes. tail; | |
878 | } | |
879 | // Flatt en out the var args | |
880 | for (int i = last; i < samSi ze; ++i) { | |
881 | addP arameter(" xva$" + i, tree.vara rgsElement , true); | |
882 | } | |
883 | ||
884 | return r cvr; | |
885 | } | |
886 | ||
887 | JC Expression getReceiv erExpressi on() { | |
888 | return r eceiverExp ression; | |
889 | } | |
890 | ||
891 | pr ivate JCEx pression m akeReceive r(VarSymbo l rcvr) { | |
892 | if (rcvr == null) return nul l; | |
893 | JCExpres sion rcvrE xpr = make .Ident(rcv r); | |
894 | Type rcv rType = tr ee.ownerAc cessible ? tree.sym. enclClass( ).type : t ree.expr.t ype; | |
895 | if (rcvr Type == sy ms.arrayCl ass.type) { | |
896 | // M ap the rec eiver type to the ac tually typ e, not jus t "array" | |
897 | rcvr Type = tre e.getQuali fierExpres sion().typ e; | |
898 | } | |
899 | if (!rcv r.type.tsy m.isSubCla ss(rcvrTyp e.tsym, ty pes)) { | |
900 | rcvr Expr = mak e.TypeCast (make.Type (rcvrType) , rcvrExpr ).setType( rcvrType); | |
901 | } | |
902 | return r cvrExpr; | |
903 | } | |
904 | ||
905 | /* * | |
906 | * determine the recei ver of the method ca ll - the r eceiver ca n | |
907 | * be a type qualifier , the synt hetic rece iver param eter or 's uper'. | |
908 | * / | |
909 | pr ivate JCEx pression e xpressionI nvoke(VarS ymbol rcvr ) { | |
910 | JCExpres sion quali fier = | |
911 | (rcvr != n ull) ? | |
912 | makeRe ceiver(rcv r) : | |
913 | tree.g etQualifie rExpressio n(); | |
914 | ||
915 | //create the quali fier expre ssion | |
916 | JCFieldA ccess sele ct = make. Select(qua lifier, tr ee.sym.nam e); | |
917 | select.s ym = tree. sym; | |
918 | select.t ype = tree .sym.erasu re(types); | |
919 | ||
920 | //create the metho d call exp ression | |
921 | JCExpres sion apply = make.Ap ply(List.< JCExpressi on>nil(), select, | |
922 | convertArg s(tree.sym , args.toL ist(), tre e.varargsE lement)). | |
923 | setType(tr ee.sym.era sure(types ).getRetur nType()); | |
924 | ||
925 | apply = transTypes .coerce(ap ply, local Context.ge neratedRef Sig().getR eturnType( )); | |
926 | setVarar gsIfNeeded (apply, tr ee.varargs Element); | |
927 | return a pply; | |
928 | } | |
929 | ||
930 | /* * | |
931 | * Lambda bo dy to use for a 'new '. | |
932 | * / | |
933 | pr ivate JCEx pression e xpressionN ew() { | |
934 | if (tree .kind == R eferenceKi nd.ARRAY_C TOR) { | |
935 | //cr eate the a rray creat ion expres sion | |
936 | JCNe wArray new Arr = make .NewArray( | |
937 | make.T ype(types. elemtype(t ree.getQua lifierExpr ession().t ype)), | |
938 | List.o f(make.Ide nt(params. first())), | |
939 | null); | |
940 | newA rr.type = tree.getQu alifierExp ression(). type; | |
941 | retu rn newArr; | |
942 | } else { | |
943 | //cr eate the i nstance cr eation exp ression | |
944 | //no te that me thod refer ence synta x does not allow an explicit | |
945 | //en closing cl ass (so th e enclosin g class is null) | |
946 | JCNe wClass new Class = ma ke.NewClas s(null, | |
947 | List.< JCExpressi on>nil(), | |
948 | make.T ype(tree.g etQualifie rExpressio n().type), | |
949 | conver tArgs(tree .sym, args .toList(), tree.vara rgsElement ), | |
950 | null); | |
951 | newC lass.const ructor = t ree.sym; | |
952 | newC lass.const ructorType = tree.sy m.erasure( types); | |
953 | newC lass.type = tree.get QualifierE xpression( ).type; | |
954 | setV arargsIfNe eded(newCl ass, tree. varargsEle ment); | |
955 | retu rn newClas s; | |
956 | } | |
957 | } | |
958 | ||
959 | pr ivate VarS ymbol addP arameter(S tring name , Type p, boolean ge nArg) { | |
960 | VarSymbo l vsym = n ew VarSymb ol(PARAMET ER | SYNTH ETIC, name s.fromStri ng(name), p, owner); | |
961 | vsym.pos = tree.po s; | |
962 | params.a ppend(make .VarDef(vs ym, null)) ; | |
963 | if (genA rg) { | |
964 | args .append(ma ke.Ident(v sym)); | |
965 | } | |
966 | return v sym; | |
967 | } | |
968 | } | |
969 | ||
970 | privat e MethodTy pe typeToM ethodType( Type mt) { | |
971 | Ty pe type = types.eras ure(mt); | |
972 | re turn new M ethodType( type.getPa rameterTyp es(), | |
973 | type.g etReturnTy pe(), | |
974 | type.g etThrownTy pes(), | |
975 | syms.m ethodClass ); | |
976 | } | |
977 | ||
978 | /** | |
979 | * Gen erate an i ndy method call to t he meta fa ctory | |
980 | */ | |
981 | privat e JCExpres sion makeM etafactory IndyCall(T ranslation Context<?> context, | |
982 | int refK ind, Symbo l refSym, List<JCExp ression> i ndy_args) { | |
983 | JC Functional Expression tree = co ntext.tree ; | |
984 | // determine the static bsm args | |
985 | Me thodSymbol samSym = (MethodSym bol) types .findDescr iptorSymbo l(tree.typ e.tsym); | |
986 | Li st<Object> staticArg s = List.< Object>of( | |
987 | type ToMethodTy pe(samSym. type), | |
988 | new Pool.Metho dHandle(re fKind, ref Sym, types ), | |
989 | type ToMethodTy pe(tree.ge tDescripto rType(type s))); | |
990 | ||
991 | // computed i ndy arg ty pes | |
992 | Li stBuffer<T ype> indy_ args_types = new Lis tBuffer<>( ); | |
993 | fo r (JCExpre ssion arg : indy_arg s) { | |
994 | indy_arg s_types.ap pend(arg.t ype); | |
995 | } | |
996 | ||
997 | // finally, c ompute the type of t he indy ca ll | |
998 | Me thodType i ndyType = new Method Type(indy_ args_types .toList(), | |
999 | tree .type, | |
1000 | List .<Type>nil (), | |
1001 | syms .methodCla ss); | |
1002 | ||
1003 | Na me metafac toryName = context.n eedsAltMet afactory() ? | |
1004 | name s.altMetaf actory : n ames.metaf actory; | |
1005 | ||
1006 | if (context. needsAltMe tafactory( )) { | |
1007 | ListBuff er<Object> markers = new ListB uffer<>(); | |
1008 | for (Typ e t : tree .targets.t ail) { | |
1009 | if ( t.tsym != syms.seria lizableTyp e.tsym) { | |
1010 | markers.ap pend(t.tsy m); | |
1011 | } | |
1012 | } | |
1013 | int flag s = contex t.isSerial izable() ? FLAG_SERI ALIZABLE : 0; | |
1014 | boolean hasMarkers = markers .nonEmpty( ); | |
1015 | boolean hasBridges = context .bridges.n onEmpty(); | |
1016 | if (hasM arkers) { | |
1017 | flag s |= FLAG_ MARKERS; | |
1018 | } | |
1019 | if (hasB ridges) { | |
1020 | flag s |= FLAG_ BRIDGES; | |
1021 | } | |
1022 | staticAr gs = stati cArgs.appe nd(flags); | |
1023 | if (hasM arkers) { | |
1024 | stat icArgs = s taticArgs. append(mar kers.lengt h()); | |
1025 | stat icArgs = s taticArgs. appendList (markers.t oList()); | |
1026 | } | |
1027 | if (hasB ridges) { | |
1028 | stat icArgs = s taticArgs. append(con text.bridg es.length( ) - 1); | |
1029 | for (Symbol s : context. bridges) { | |
1030 | Type s_era sure = s.e rasure(typ es); | |
1031 | if (!types .isSameTyp e(s_erasur e, samSym. erasure(ty pes))) { | |
1032 | static Args = sta ticArgs.ap pend(s.era sure(types )); | |
1033 | } | |
1034 | } | |
1035 | } | |
1036 | if (cont ext.isSeri alizable() ) { | |
1037 | int prevPos = make.pos; | |
1038 | try { | |
1039 | make.at(kI nfo.clazz) ; | |
1040 | addDeseria lizationCa se(refKind , refSym, tree.type, samSym, | |
1041 | tr ee, static Args, indy Type); | |
1042 | } fi nally { | |
1043 | make.at(pr evPos); | |
1044 | } | |
1045 | } | |
1046 | } | |
1047 | ||
1048 | re turn makeI ndyCall(tr ee, syms.l ambdaMetaf actory, me tafactoryN ame, stati cArgs, ind yType, ind y_args, sa mSym.name) ; | |
1049 | } | |
1050 | ||
1051 | /** | |
1052 | * Gen erate an i ndy method call with given nam e, type an d static b ootstrap | |
1053 | * arg uments typ es | |
1054 | */ | |
1055 | privat e JCExpres sion makeI ndyCall(Di agnosticPo sition pos , Type sit e, Name bs mName, | |
1056 | List<Obj ect> stati cArgs, Met hodType in dyType, Li st<JCExpre ssion> ind yArgs, | |
1057 | Name met hName) { | |
1058 | in t prevPos = make.pos ; | |
1059 | tr y { | |
1060 | make.at( pos); | |
1061 | List<Typ e> bsm_sta ticArgs = List.of(sy ms.methodH andleLooku pType, | |
1062 | syms.strin gType, | |
1063 | syms.metho dTypeType) .appendLis t(bsmStati cArgToType s(staticAr gs)); | |
1064 | ||
1065 | Symbol b sm = rs.re solveInter nalMethod( pos, attrE nv, site, | |
1066 | bsmName, b sm_staticA rgs, List. <Type>nil( )); | |
1067 | ||
1068 | DynamicM ethodSymbo l dynSym = | |
1069 | new Dynami cMethodSym bol(methNa me, | |
1070 | syms.n oSymbol, | |
1071 | bsm.is Static() ? | |
1072 | Cl assFile.RE F_invokeSt atic : | |
1073 | Cl assFile.RE F_invokeVi rtual, | |
1074 | (Metho dSymbol)bs m, | |
1075 | indyTy pe, | |
1076 | static Args.toArr ay()); | |
1077 | ||
1078 | JCFieldA ccess qual ifier = ma ke.Select( make.QualI dent(site. tsym), bsm Name); | |
1079 | qualifie r.sym = dy nSym; | |
1080 | qualifie r.type = i ndyType.ge tReturnTyp e(); | |
1081 | ||
1082 | JCMethod Invocation proxyCall = make.Ap ply(List.< JCExpressi on>nil(), qualifier, indyArgs) ; | |
1083 | proxyCal l.type = i ndyType.ge tReturnTyp e(); | |
1084 | return p roxyCall; | |
1085 | } finally { | |
1086 | make.at( prevPos); | |
1087 | } | |
1088 | } | |
1089 | //wher e | |
1090 | privat e List<Typ e> bsmStat icArgToTyp es(List<Ob ject> args ) { | |
1091 | Li stBuffer<T ype> argty pes = new ListBuffer <>(); | |
1092 | fo r (Object arg : args ) { | |
1093 | argtypes .append(bs mStaticArg ToType(arg )); | |
1094 | } | |
1095 | re turn argty pes.toList (); | |
1096 | } | |
1097 | ||
1098 | privat e Type bsm StaticArgT oType(Obje ct arg) { | |
1099 | As sert.check NonNull(ar g); | |
1100 | if (arg inst anceof Cla ssSymbol) { | |
1101 | return s yms.classT ype; | |
1102 | } else if (a rg instanc eof Intege r) { | |
1103 | return s yms.intTyp e; | |
1104 | } else if (a rg instanc eof Long) { | |
1105 | return s yms.longTy pe; | |
1106 | } else if (a rg instanc eof Float) { | |
1107 | return s yms.floatT ype; | |
1108 | } else if (a rg instanc eof Double ) { | |
1109 | return s yms.double Type; | |
1110 | } else if (a rg instanc eof String ) { | |
1111 | return s yms.string Type; | |
1112 | } else if (a rg instanc eof Pool.M ethodHandl e) { | |
1113 | return s yms.method HandleType ; | |
1114 | } else if (a rg instanc eof Method Type) { | |
1115 | return s yms.method TypeType; | |
1116 | } else { | |
1117 | Assert.e rror("bad static arg " + arg.g etClass()) ; | |
1118 | return n ull; | |
1119 | } | |
1120 | } | |
1121 | ||
1122 | /** | |
1123 | * Get the opcod e associat ed with th is method reference | |
1124 | */ | |
1125 | privat e int refe renceKind( Symbol ref Sym) { | |
1126 | if (refSym.i sConstruct or()) { | |
1127 | return C lassFile.R EF_newInvo keSpecial; | |
1128 | } else { | |
1129 | if (refS ym.isStati c()) { | |
1130 | retu rn ClassFi le.REF_inv okeStatic; | |
1131 | } else i f ((refSym .flags() & PRIVATE) != 0) { | |
1132 | retu rn ClassFi le.REF_inv okeSpecial ; | |
1133 | } else i f (refSym. enclClass( ).isInterf ace()) { | |
1134 | retu rn ClassFi le.REF_inv okeInterfa ce; | |
1135 | } else { | |
1136 | retu rn ClassFi le.REF_inv okeVirtual ; | |
1137 | } | |
1138 | } | |
1139 | } | |
1140 | ||
1141 | // <ed itor-fold defaultsta te="collap sed" desc= "Lambda/re ference an alyzer"> | |
1142 | /** | |
1143 | * Thi s visitor collects i nformation about tra nslation o f a lambda expressio n. | |
1144 | * Mor e specific ally, it k eeps track of the en closing co ntexts and captured locals | |
1145 | * acc essed by t he lambda being tran slated (as well as o ther usefu l info). | |
1146 | * It also trans lates away problems for Lambda ToMethod. | |
1147 | */ | |
1148 | class LambdaAnal yzerPrepro cessor ext ends TreeT ranslator { | |
1149 | ||
1150 | /* * the fram e stack - used to re construct translatio n info abo ut enclosi ng scopes */ | |
1151 | pr ivate List <Frame> fr ameStack; | |
1152 | ||
1153 | /* * | |
1154 | * keep the count of l ambda expr ession (us ed to gene rate unamb iguous | |
1155 | * names) | |
1156 | * / | |
1157 | pr ivate int lambdaCoun t = 0; | |
1158 | ||
1159 | /* * | |
1160 | * List of t ypes under going cons truction v ia explici t construc tor chaini ng. | |
1161 | * / | |
1162 | pr ivate List <ClassSymb ol> typesU nderConstr uction; | |
1163 | ||
1164 | /* * | |
1165 | * keep the count of l ambda expr ession def ined in gi ven contex t (used to | |
1166 | * generate unambiguou s names fo r serializ able lambd as) | |
1167 | * / | |
1168 | pr ivate clas s Syntheti cMethodNam eCounter { | |
1169 | private Map<String , Integer> map = new HashMap<> (); | |
1170 | int getI ndex(Strin gBuilder b uf) { | |
1171 | Stri ng temp = buf.toStri ng(); | |
1172 | Inte ger count = map.get( temp); | |
1173 | if ( count == n ull) { | |
1174 | count = 0; | |
1175 | } | |
1176 | ++co unt; | |
1177 | map. put(temp, count); | |
1178 | retu rn count; | |
1179 | } | |
1180 | } | |
1181 | pr ivate Synt heticMetho dNameCount er synthet icMethodNa meCounts = | |
1182 | new SyntheticM ethodNameC ounter(); | |
1183 | ||
1184 | pr ivate Map< Symbol, JC ClassDecl> localClas sDefs; | |
1185 | ||
1186 | /* * | |
1187 | * maps for fake clini t symbols to be used as owners of lambda occurring in | |
1188 | * a static var init c ontext | |
1189 | * / | |
1190 | pr ivate Map< ClassSymbo l, Symbol> clinits = | |
1191 | new HashMap<Cl assSymbol, Symbol>() ; | |
1192 | ||
1193 | pr ivate JCCl assDecl an alyzeAndPr eprocessCl ass(JCClas sDecl tree ) { | |
1194 | frameSta ck = List. nil(); | |
1195 | typesUnd erConstruc tion = Lis t.nil(); | |
1196 | localCla ssDefs = n ew HashMap <Symbol, J CClassDecl >(); | |
1197 | return t ranslate(t ree); | |
1198 | } | |
1199 | ||
1200 | @O verride | |
1201 | pu blic void visitApply (JCMethodI nvocation tree) { | |
1202 | List<Cla ssSymbol> previousNa scentTypes = typesUn derConstru ction; | |
1203 | try { | |
1204 | Name methName = TreeInfo .name(tree .meth); | |
1205 | if ( methName = = names._t his || met hName == n ames._supe r) { | |
1206 | typesUnder Constructi on = types UnderConst ruction.pr epend(curr entClass() ); | |
1207 | } | |
1208 | supe r.visitApp ly(tree); | |
1209 | } finall y { | |
1210 | type sUnderCons truction = previousN ascentType s; | |
1211 | } | |
1212 | } | |
1213 | // where | |
1214 | private ClassSymbo l currentC lass() { | |
1215 | for (Frame fra me : frame Stack) { | |
1216 | if (frame. tree.hasTa g(JCTree.T ag.CLASSDE F)) { | |
1217 | JCClas sDecl cdef = (JCClas sDecl) fra me.tree; | |
1218 | return cdef.sym; | |
1219 | } | |
1220 | } | |
1221 | retu rn null; | |
1222 | } | |
1223 | ||
1224 | @O verride | |
1225 | pu blic void visitBlock (JCBlock t ree) { | |
1226 | List<Fra me> prevSt ack = fram eStack; | |
1227 | try { | |
1228 | if ( frameStack .nonEmpty( ) && frame Stack.head .tree.hasT ag(CLASSDE F)) { | |
1229 | frameStack = frameSt ack.prepen d(new Fram e(tree)); | |
1230 | } | |
1231 | supe r.visitBlo ck(tree); | |
1232 | } | |
1233 | finally { | |
1234 | fram eStack = p revStack; | |
1235 | } | |
1236 | } | |
1237 | ||
1238 | @O verride | |
1239 | pu blic void visitClass Def(JCClas sDecl tree ) { | |
1240 | List<Fra me> prevSt ack = fram eStack; | |
1241 | int prev LambdaCoun t = lambda Count; | |
1242 | Syntheti cMethodNam eCounter p revSynthet icMethodNa meCounts = | |
1243 | syntheticM ethodNameC ounts; | |
1244 | Map<Clas sSymbol, S ymbol> pre vClinits = clinits; | |
1245 | Diagnost icSource p revSource = log.curr entSource( ); | |
1246 | try { | |
1247 | log. useSource( tree.sym.s ourcefile) ; | |
1248 | lamb daCount = 0; | |
1249 | synt heticMetho dNameCount s = new Sy ntheticMet hodNameCou nter(); | |
1250 | prev Clinits = new HashMa p<ClassSym bol, Symbo l>(); | |
1251 | if ( tree.sym.o wner.kind == MTH) { | |
1252 | localClass Defs.put(t ree.sym, t ree); | |
1253 | } | |
1254 | if ( directlyEn closingLam bda() != n ull) { | |
1255 | tree.sym.o wner = own er(); | |
1256 | if (tree.s ym.hasOute rInstance( )) { | |
1257 | //if a class is defined wi thin a lam bda, the l ambda must capture | |
1258 | //its enclosing instance ( if any) | |
1259 | Transl ationConte xt<?> loca lContext = context() ; | |
1260 | while (localCont ext != nul l) { | |
1261 | if (localCon text.tree. getTag() = = LAMBDA) { | |
1262 | ((Lambda Translatio nContext)l ocalContex t) | |
1263 | .addSymbol (tree.sym. type.getEn closingTyp e().tsym, CAPTURED_T HIS); | |
1264 | } | |
1265 | lo calContext = localCo ntext.prev ; | |
1266 | } | |
1267 | } | |
1268 | } | |
1269 | fram eStack = f rameStack. prepend(ne w Frame(tr ee)); | |
1270 | supe r.visitCla ssDef(tree ); | |
1271 | } | |
1272 | finally { | |
1273 | log. useSource( prevSource .getFile() ); | |
1274 | fram eStack = p revStack; | |
1275 | lamb daCount = prevLambda Count; | |
1276 | synt heticMetho dNameCount s = prevSy ntheticMet hodNameCou nts; | |
1277 | clin its = prev Clinits; | |
1278 | } | |
1279 | } | |
1280 | ||
1281 | @O verride | |
1282 | pu blic void visitIdent (JCIdent t ree) { | |
1283 | if (cont ext() != n ull && lam bdaIdentSy mbolFilter (tree.sym) ) { | |
1284 | if ( tree.sym.k ind == VAR && | |
1285 | tree.s ym.owner.k ind == MTH && | |
1286 | tree.t ype.constV alue() == null) { | |
1287 | Translatio nContext<? > localCon text = con text(); | |
1288 | while (loc alContext != null) { | |
1289 | if (lo calContext .tree.getT ag() == LA MBDA) { | |
1290 | JC Tree block = capture dDecl(loca lContext.d epth, tree .sym); | |
1291 | if (block == null) bre ak; | |
1292 | (( LambdaTran slationCon text)local Context) | |
1293 | .add Symbol(tre e.sym, CAP TURED_VAR) ; | |
1294 | } | |
1295 | localC ontext = l ocalContex t.prev; | |
1296 | } | |
1297 | } el se if (tre e.sym.owne r.kind == TYP) { | |
1298 | Translatio nContext<? > localCon text = con text(); | |
1299 | while (loc alContext != null) { | |
1300 | if (lo calContext .tree.hasT ag(LAMBDA) ) { | |
1301 | JC Tree block = capture dDecl(loca lContext.d epth, tree .sym); | |
1302 | if (block == null) bre ak; | |
1303 | sw itch (bloc k.getTag() ) { | |
1304 | case CLA SSDEF: | |
1305 | JCCl assDecl cd ecl = (JCC lassDecl)b lock; | |
1306 | ((La mbdaTransl ationConte xt)localCo ntext) | |
1307 | .addSy mbol(cdecl .sym, CAPT URED_THIS) ; | |
1308 | brea k; | |
1309 | default: | |
1310 | Asse rt.error(" bad block kind"); | |
1311 | } | |
1312 | } | |
1313 | localC ontext = l ocalContex t.prev; | |
1314 | } | |
1315 | } | |
1316 | } | |
1317 | super.vi sitIdent(t ree); | |
1318 | } | |
1319 | ||
1320 | @O verride | |
1321 | pu blic void visitLambd a(JCLambda tree) { | |
1322 | analyzeL ambda(tree , "lambda. stat"); | |
1323 | } | |
1324 | ||
1325 | pr ivate void analyzeLa mbda(JCLam bda tree, JCExpressi on methodR eferenceRe ceiver) { | |
1326 | // Trans lation of the receiv er express ion must o ccur first | |
1327 | JCExpres sion rcvr = translat e(methodRe ferenceRec eiver); | |
1328 | LambdaTr anslationC ontext con text = ana lyzeLambda (tree, "mr ef.stat.1" ); | |
1329 | if (rcvr != null) { | |
1330 | cont ext.method ReferenceR eceiver = rcvr; | |
1331 | } | |
1332 | } | |
1333 | ||
1334 | pr ivate Lamb daTranslat ionContext analyzeLa mbda(JCLam bda tree, String sta tKey) { | |
1335 | List<Fra me> prevSt ack = fram eStack; | |
1336 | try { | |
1337 | Lamb daTranslat ionContext context = new Lambd aTranslati onContext( tree); | |
1338 | if ( dumpLambda ToMethodSt ats) { | |
1339 | log.note(t ree, statK ey, contex t.needsAlt Metafactor y(), conte xt.transla tedSym); | |
1340 | } | |
1341 | fram eStack = f rameStack. prepend(ne w Frame(tr ee)); | |
1342 | for (JCVariabl eDecl para m : tree.p arams) { | |
1343 | context.ad dSymbol(pa ram.sym, P ARAM); | |
1344 | frameStack .head.addL ocal(param .sym); | |
1345 | } | |
1346 | cont extMap.put (tree, con text); | |
1347 | supe r.visitLam bda(tree); | |
1348 | cont ext.comple te(); | |
1349 | retu rn context ; | |
1350 | } | |
1351 | finally { | |
1352 | fram eStack = p revStack; | |
1353 | } | |
1354 | } | |
1355 | ||
1356 | @O verride | |
1357 | pu blic void visitMetho dDef(JCMet hodDecl tr ee) { | |
1358 | List<Fra me> prevSt ack = fram eStack; | |
1359 | try { | |
1360 | fram eStack = f rameStack. prepend(ne w Frame(tr ee)); | |
1361 | supe r.visitMet hodDef(tre e); | |
1362 | } | |
1363 | finally { | |
1364 | fram eStack = p revStack; | |
1365 | } | |
1366 | } | |
1367 | ||
1368 | @O verride | |
1369 | pu blic void visitNewCl ass(JCNewC lass tree) { | |
1370 | TypeSymb ol def = t ree.type.t sym; | |
1371 | boolean inReferenc edClass = currentlyI nClass(def ); | |
1372 | boolean isLocal = def.isLoca l(); | |
1373 | if ((inR eferencedC lass && is Local || l ambdaNewCl assFilter( context(), tree))) { | |
1374 | Tran slationCon text<?> lo calContext = context (); | |
1375 | whil e (localCo ntext != n ull) { | |
1376 | if (localC ontext.tre e.getTag() == LAMBDA ) { | |
1377 | ((Lamb daTranslat ionContext )localCont ext) | |
1378 | .addSymb ol(tree.ty pe.getEncl osingType( ).tsym, CA PTURED_THI S); | |
1379 | } | |
1380 | localConte xt = local Context.pr ev; | |
1381 | } | |
1382 | } | |
1383 | if (cont ext() != n ull && !in Referenced Class && i sLocal) { | |
1384 | Lamb daTranslat ionContext lambdaCon text = (La mbdaTransl ationConte xt)context (); | |
1385 | capt ureLocalCl assDefs(de f, lambdaC ontext); | |
1386 | } | |
1387 | super.vi sitNewClas s(tree); | |
1388 | } | |
1389 | // where | |
1390 | void cap tureLocalC lassDefs(S ymbol csym , final La mbdaTransl ationConte xt lambdaC ontext) { | |
1391 | JCCl assDecl lo calCDef = localClass Defs.get(c sym); | |
1392 | if ( localCDef != null && lambdaCon text.freeV arProcesse dLocalClas ses.add(cs ym)) { | |
1393 | BasicFreeV arCollecto r fvc = lo wer.new Ba sicFreeVar Collector( ) { | |
1394 | @Overr ide | |
1395 | void a ddFreeVars (ClassSymb ol c) { | |
1396 | ca ptureLocal ClassDefs( c, lambdaC ontext); | |
1397 | } | |
1398 | @Overr ide | |
1399 | void v isitSymbol (Symbol sy m) { | |
1400 | if (sym.kind == VAR && | |
1401 | sym. owner.kind == MTH && | |
1402 | ((Va rSymbol)sy m).getCons tValue() = = null) { | |
1403 | Translat ionContext <?> localC ontext = c ontext(); | |
1404 | while (l ocalContex t != null) { | |
1405 | if ( localConte xt.tree.ge tTag() == LAMBDA) { | |
1406 | JCTree blo ck = captu redDecl(lo calContext .depth, sy m); | |
1407 | if (block == null) b reak; | |
1408 | ((LambdaTr anslationC ontext)loc alContext) .addSymbol (sym, CAPT URED_VAR); | |
1409 | } | |
1410 | loca lContext = localCont ext.prev; | |
1411 | } | |
1412 | } | |
1413 | } | |
1414 | }; | |
1415 | fvc.scan(l ocalCDef); | |
1416 | } | |
1417 | } | |
1418 | // where | |
1419 | bo olean curr entlyInCla ss(Symbol csym) { | |
1420 | for (Fra me frame : frameStac k) { | |
1421 | if ( frame.tree .hasTag(JC Tree.Tag.C LASSDEF)) { | |
1422 | JCClassDec l cdef = ( JCClassDec l) frame.t ree; | |
1423 | if (cdef.s ym == csym ) { | |
1424 | return true; | |
1425 | } | |
1426 | } | |
1427 | } | |
1428 | return f alse; | |
1429 | } | |
1430 | ||
1431 | /* * | |
1432 | * Method re ferences t o local cl ass constr uctors, ma y, if the local | |
1433 | * class ref erences lo cal variab les, have implicit c onstructor | |
1434 | * parameter s added in Lower; As a result, the invok edynamic b ootstrap | |
1435 | * informati on added i n the Lamb daToMethod pass will have the wrong | |
1436 | * signature . Hooks be tween Lowe r and Lamb daToMethod have been added to | |
1437 | * handle no rmal "new" in this c ase. This visitor co nverts pot entially | |
1438 | * affected method ref erences in to a lambd a containi ng a norma l | |
1439 | * expressio n. | |
1440 | * | |
1441 | * @param tr ee | |
1442 | * / | |
1443 | @O verride | |
1444 | pu blic void visitRefer ence(JCMem berReferen ce tree) { | |
1445 | Referenc eTranslati onContext rcontext = new Refer enceTransl ationConte xt(tree); | |
1446 | contextM ap.put(tre e, rcontex t); | |
1447 | if (rcon text.needs Conversion ToLambda() ) { | |
1448 | // Convert to a lambda, and proce ss as such | |
1449 | Memb erReferenc eToLambda conv = new MemberRef erenceToLa mbda(tree, rcontext, owner()); | |
1450 | anal yzeLambda( conv.lambd a(), conv. getReceive rExpressio n()); | |
1451 | } else { | |
1452 | supe r.visitRef erence(tre e); | |
1453 | if ( dumpLambda ToMethodSt ats) { | |
1454 | log.note(t ree, "mref .stat", rc ontext.nee dsAltMetaf actory(), null); | |
1455 | } | |
1456 | } | |
1457 | } | |
1458 | ||
1459 | @O verride | |
1460 | pu blic void visitSelec t(JCFieldA ccess tree ) { | |
1461 | if (cont ext() != n ull && tre e.sym.kind == VAR && | |
1462 | (tree. sym.name = = names._t his || | |
1463 | tree. sym.name = = names._s uper)) { | |
1464 | // A select of this or s uper means , if we ar e in a lam bda, | |
1465 | // w e much hav e an insta nce contex t | |
1466 | Tran slationCon text<?> lo calContext = context (); | |
1467 | whil e (localCo ntext != n ull) { | |
1468 | if (localC ontext.tre e.hasTag(L AMBDA)) { | |
1469 | JCClas sDecl claz z = (JCCla ssDecl)cap turedDecl( localConte xt.depth, tree.sym); | |
1470 | if (cl azz == nul l) break; | |
1471 | ((Lamb daTranslat ionContext )localCont ext).addSy mbol(clazz .sym, CAPT URED_THIS) ; | |
1472 | } | |
1473 | localConte xt = local Context.pr ev; | |
1474 | } | |
1475 | } | |
1476 | super.vi sitSelect( tree); | |
1477 | } | |
1478 | ||
1479 | @O verride | |
1480 | pu blic void visitVarDe f(JCVariab leDecl tre e) { | |
1481 | Translat ionContext <?> contex t = contex t(); | |
1482 | LambdaTr anslationC ontext ltc = (contex t != null && context instanceo f LambdaTr anslationC ontext)? | |
1483 | (LambdaTra nslationCo ntext)cont ext : | |
1484 | null; | |
1485 | if (ltc != null) { | |
1486 | if ( frameStack .head.tree .hasTag(LA MBDA)) { | |
1487 | ltc.addSym bol(tree.s ym, LOCAL_ VAR); | |
1488 | } | |
1489 | // C heck for t ype variab les (inclu ding as ty pe argumen ts). | |
1490 | // I f they occ ur within class nest ed in a la mbda, mark for erasu re | |
1491 | Type type = tr ee.sym.asT ype(); | |
1492 | if ( inClassWit hinLambda( ) && !type s.isSameTy pe(types.e rasure(typ e), type)) { | |
1493 | ltc.addSym bol(tree.s ym, TYPE_V AR); | |
1494 | } | |
1495 | } | |
1496 | ||
1497 | List<Fra me> prevSt ack = fram eStack; | |
1498 | try { | |
1499 | if ( tree.sym.o wner.kind == MTH) { | |
1500 | frameStack .head.addL ocal(tree. sym); | |
1501 | } | |
1502 | fram eStack = f rameStack. prepend(ne w Frame(tr ee)); | |
1503 | supe r.visitVar Def(tree); | |
1504 | } | |
1505 | finally { | |
1506 | fram eStack = p revStack; | |
1507 | } | |
1508 | } | |
1509 | ||
1510 | /* * | |
1511 | * Return a valid owne r given th e current declaratio n stack | |
1512 | * (required to skip s ynthetic l ambda symb ols) | |
1513 | * / | |
1514 | pr ivate Symb ol owner() { | |
1515 | return o wner(false ); | |
1516 | } | |
1517 | ||
1518 | @S uppressWar nings("fal lthrough") | |
1519 | pr ivate Symb ol owner(b oolean ski pLambda) { | |
1520 | List<Fra me> frameS tack2 = fr ameStack; | |
1521 | while (f rameStack2 .nonEmpty( )) { | |
1522 | swit ch (frameS tack2.head .tree.getT ag()) { | |
1523 | case
|
|
1524 | if ((( JCVariable Decl)frame Stack2.hea d.tree).sy m.isLocal( )) { | |
1525 | fr ameStack2 = frameSta ck2.tail; | |
1526 | br eak; | |
1527 | } | |
1528 | JCClas sDecl cdec l = (JCCla ssDecl)fra meStack2.t ail.head.t ree; | |
1529 | return initSym(c decl.sym, | |
1530 | ((JCVari ableDecl)f rameStack2 .head.tree ).sym.flag s() & STAT IC); | |
1531 | case BLOCK : | |
1532 | JCClas sDecl cdec l2 = (JCCl assDecl)fr ameStack2. tail.head. tree; | |
1533 | return initSym(c decl2.sym, | |
1534 | ((JCBloc k)frameSta ck2.head.t ree).flags & STATIC) ; | |
1535 | case CLASS DEF: | |
1536 | return ((JCClass Decl)frame Stack2.hea d.tree).sy m; | |
1537 | case METHO DDEF: | |
1538 | return ((JCMetho dDecl)fram eStack2.he ad.tree).s ym; | |
1539 | case LAMBD A: | |
1540 | if (!s kipLambda) | |
1541 | re turn ((Lam bdaTransla tionContex t)contextM ap | |
1542 | .get (frameStac k2.head.tr ee)).trans latedSym; | |
1543 | default: | |
1544 | frameS tack2 = fr ameStack2. tail; | |
1545 | } | |
1546 | } | |
1547 | Assert.e rror(); | |
1548 | return n ull; | |
1549 | } | |
1550 | ||
1551 | pr ivate Symb ol initSym (ClassSymb ol csym, l ong flags) { | |
1552 | boolean isStatic = (flags & STATIC) != 0; | |
1553 | if (isSt atic) { | |
1554 | /* s tatic clin its are ge nerated in Gen, so w e need to use a fake | |
1555 | * o ne. Attr c reates a f ake clinit method wh ile attrib uting | |
1556 | * l ambda expr essions us ed as init ializers o f static f ields, so | |
1557 | * l et's use t hat one. | |
1558 | */ | |
1559 | Meth odSymbol c linit = at tr.removeC linit(csym ); | |
1560 | if ( clinit != null) { | |
1561 | clinits.pu t(csym, cl init); | |
1562 | return cli nit; | |
1563 | } | |
1564 | ||
1565 | /* i f no clini t is found at Attr, then let's try at cl inits. | |
1566 | */ | |
1567 | clin it = (Meth odSymbol)c linits.get (csym); | |
1568 | if ( clinit == null) { | |
1569 | /* no luck , let's cr eate a new one | |
1570 | */ | |
1571 | clinit = m akePrivate SyntheticM ethod(STAT IC, | |
1572 | na mes.clinit , | |
1573 | ne w MethodTy pe(List.<T ype>nil(), syms.void Type, | |
1574 | List.<Ty pe>nil(), syms.metho dClass), | |
1575 | cs ym); | |
1576 | clinits.pu t(csym, cl init); | |
1577 | } | |
1578 | retu rn clinit; | |
1579 | } else { | |
1580 | //ge t the firs t construc tor and tr eat it as the instan ce init sy m | |
1581 | for (Symbol s : csym.mem bers_field .getElemen tsByName(n ames.init) ) { | |
1582 | return s; | |
1583 | } | |
1584 | } | |
1585 | Assert.e rror("init not found "); | |
1586 | return n ull; | |
1587 | } | |
1588 | ||
1589 | pr ivate JCTr ee directl yEnclosing Lambda() { | |
1590 | if (fram eStack.isE mpty()) { | |
1591 | retu rn null; | |
1592 | } | |
1593 | List<Fra me> frameS tack2 = fr ameStack; | |
1594 | while (f rameStack2 .nonEmpty( )) { | |
1595 | swit ch (frameS tack2.head .tree.getT ag()) { | |
1596 | case CLASS DEF: | |
1597 | case METHO DDEF: | |
1598 | return null; | |
1599 | case LAMBD A: | |
1600 | return frameStac k2.head.tr ee; | |
1601 | default: | |
1602 | frameS tack2 = fr ameStack2. tail; | |
1603 | } | |
1604 | } | |
1605 | Assert.e rror(); | |
1606 | return n ull; | |
1607 | } | |
1608 | ||
1609 | pr ivate bool ean inClas sWithinLam bda() { | |
1610 | if (fram eStack.isE mpty()) { | |
1611 | retu rn false; | |
1612 | } | |
1613 | List<Fra me> frameS tack2 = fr ameStack; | |
1614 | boolean classFound = false; | |
1615 | while (f rameStack2 .nonEmpty( )) { | |
1616 | swit ch (frameS tack2.head .tree.getT ag()) { | |
1617 | case LAMBD A: | |
1618 | return classFoun d; | |
1619 | case CLASS DEF: | |
1620 | classF ound = tru e; | |
1621 | frameS tack2 = fr ameStack2. tail; | |
1622 | break; | |
1623 | default: | |
1624 | frameS tack2 = fr ameStack2. tail; | |
1625 | } | |
1626 | } | |
1627 | // No la mbda | |
1628 | return f alse; | |
1629 | } | |
1630 | ||
1631 | /* * | |
1632 | * Return th e declarat ion corres ponding to a symbol in the enc losing | |
1633 | * scope; th e depth pa rameter is used to f ilter out symbols de fined | |
1634 | * in nested scopes (w hich do no t need to undergo ca pture). | |
1635 | * / | |
1636 | pr ivate JCTr ee capture dDecl(int depth, Sym bol sym) { | |
1637 | int curr entDepth = frameStac k.size() - 1; | |
1638 | for (Fra me block : frameStac k) { | |
1639 | swit ch (block. tree.getTa g()) { | |
1640 | case CLASS DEF: | |
1641 | ClassS ymbol claz z = ((JCCl assDecl)bl ock.tree). sym; | |
1642 | if (sy m.isMember Of(clazz, types)) { | |
1643 | re turn curre ntDepth > depth ? nu ll : block .tree; | |
1644 | } | |
1645 | break; | |
1646 | case
|
|
1647 | if ((( JCVariable Decl)block .tree).sym == sym && | |
1648 | sym.owne r.kind == MTH) { //o nly locals are captu red | |
1649 | re turn curre ntDepth > depth ? nu ll : block .tree; | |
1650 | } | |
1651 | break; | |
1652 | case BLOCK : | |
1653 | case METHO DDEF: | |
1654 | case LAMBD A: | |
1655 | if (bl ock.locals != null & & block.lo cals.conta ins(sym)) { | |
1656 | re turn curre ntDepth > depth ? nu ll : block .tree; | |
1657 | } | |
1658 | break; | |
1659 | default: | |
1660 | Assert .error("ba d decl kin d " + bloc k.tree.get Tag()); | |
1661 | } | |
1662 | curr entDepth-- ; | |
1663 | } | |
1664 | return n ull; | |
1665 | } | |
1666 | ||
1667 | pr ivate Tran slationCon text<?> co ntext() { | |
1668 | for (Fra me frame : frameStac k) { | |
1669 | Tran slationCon text<?> co ntext = co ntextMap.g et(frame.t ree); | |
1670 | if ( context != null) { | |
1671 | return con text; | |
1672 | } | |
1673 | } | |
1674 | return n ull; | |
1675 | } | |
1676 | ||
1677 | /* * | |
1678 | * This is used to fi lter out t hose ident ifiers tha t needs to be adjust ed | |
1679 | * when tra nslating a way lambda expressio ns | |
1680 | * / | |
1681 | pr ivate bool ean lambda IdentSymbo lFilter(Sy mbol sym) { | |
1682 | return ( sym.kind = = VAR || s ym.kind == MTH) | |
1683 | && !sym.is Static() | |
1684 | && sym.nam e != names .init; | |
1685 | } | |
1686 | ||
1687 | /* * | |
1688 | * This is used to fi lter out t hose selec t nodes th at need to be adjust ed | |
1689 | * when tra nslating a way lambda expressio ns - at th e moment, this is th e | |
1690 | * set of n odes that select `th is' (quali fied this) | |
1691 | * / | |
1692 | pr ivate bool ean lambda FieldAcces sFilter(JC FieldAcces s fAccess) { | |
1693 | LambdaTr anslationC ontext lam bdaContext = | |
1694 | context in stanceof L ambdaTrans lationCont ext ? | |
1695 | (L ambdaTrans lationCont ext) conte xt : null; | |
1696 | return l ambdaConte xt != null | |
1697 | && !fAcces s.sym.isSt atic() | |
1698 | && fAccess .name == n ames._this | |
1699 | && (fAcces s.sym.owne r.kind == TYP) | |
1700 | && !lambda Context.tr anslatedSy mbols.get( CAPTURED_O UTER_THIS) .isEmpty() ; | |
1701 | } | |
1702 | ||
1703 | /* * | |
1704 | * This is u sed to fil ter out th ose new cl ass expres sions that need to | |
1705 | * be qualif ied with a n enclosin g tree | |
1706 | * / | |
1707 | pr ivate bool ean lambda NewClassFi lter(Trans lationCont ext<?> con text, JCNe wClass tre e) { | |
1708 | if (cont ext != nul l | |
1709 | && tree.en cl == null | |
1710 | && tree.de f == null | |
1711 | && !tree.t ype.getEnc losingType ().hasTag( NONE)) { | |
1712 | Type encl = tr ee.type.ge tEnclosing Type(); | |
1713 | Type current = context.o wner.enclC lass().typ e; | |
1714 | whil e (!curren t.hasTag(N ONE)) { | |
1715 | if (curren t.tsym.isS ubClass(en cl.tsym, t ypes)) { | |
1716 | return true; | |
1717 | } | |
1718 | current = current.ge tEnclosing Type(); | |
1719 | } | |
1720 | retu rn false; | |
1721 | } else { | |
1722 | retu rn false; | |
1723 | } | |
1724 | } | |
1725 | ||
1726 | pr ivate clas s Frame { | |
1727 | final JC Tree tree; | |
1728 | List<Sym bol> local s; | |
1729 | ||
1730 | public F rame(JCTre e tree) { | |
1731 | this .tree = tr ee; | |
1732 | } | |
1733 | ||
1734 | void add Local(Symb ol sym) { | |
1735 | if ( locals == null) { | |
1736 | locals = L ist.nil(); | |
1737 | } | |
1738 | loca ls = local s.prepend( sym); | |
1739 | } | |
1740 | } | |
1741 | ||
1742 | /* * | |
1743 | * This clas s is used to store i mportant i nformation regarding translati on of | |
1744 | * lambda ex pression/m ethod refe rences (se e subclass es). | |
1745 | * / | |
1746 | pr ivate abst ract class Translati onContext< T extends JCFunction alExpressi on> { | |
1747 | ||
1748 | /** the underlying (untransl ated) tree */ | |
1749 | final T tree; | |
1750 | ||
1751 | /** poin ts to the adjusted e nclosing s cope in wh ich this l ambda/mref expressio n occurs * / | |
1752 | final Sy mbol owner ; | |
1753 | ||
1754 | /** the depth of t his lambda expressio n in the f rame stack */ | |
1755 | final in t depth; | |
1756 | ||
1757 | /** the enclosing translatio n context (set for n ested lamb das/mref) */ | |
1758 | final Tr anslationC ontext<?> prev; | |
1759 | ||
1760 | /** list of method s to be br idged by t he meta-fa ctory */ | |
1761 | final Li st<Symbol> bridges; | |
1762 | ||
1763 | Translat ionContext (T tree) { | |
1764 | this .tree = tr ee; | |
1765 | this .owner = o wner(); | |
1766 | this .depth = f rameStack. size() - 1 ; | |
1767 | this .prev = co ntext(); | |
1768 | Clas sSymbol cs ym = | |
1769 | types. makeFuncti onalInterf aceClass(a ttrEnv, na mes.empty, tree.targ ets, ABSTR ACT | INTE RFACE); | |
1770 | this .bridges = types.fun ctionalInt erfaceBrid ges(csym); | |
1771 | } | |
1772 | ||
1773 | /** does this func tional exp ression ne ed to be c reated usi ng alterna te metafac tory? */ | |
1774 | boolean needsAltMe tafactory( ) { | |
1775 | retu rn tree.ta rgets.leng th() > 1 | | | |
1776 | isSeri alizable() || | |
1777 | bridge s.length() > 1; | |
1778 | } | |
1779 | ||
1780 | /** does this func tional exp ression re quire seri alization support? * / | |
1781 | boolean isSerializ able() { | |
1782 | if ( forceSeria lizable) { | |
1783 | return tru e; | |
1784 | } | |
1785 | for (Type targ et : tree. targets) { | |
1786 | if (types. asSuper(ta rget, syms .serializa bleType.ts ym) != nul l) { | |
1787 | return true; | |
1788 | } | |
1789 | } | |
1790 | retu rn false; | |
1791 | } | |
1792 | ||
1793 | /** | |
1794 | * @retu rn Name of the enclo sing metho d to be fo lded into synthetic | |
1795 | * metho d name | |
1796 | */ | |
1797 | String e nclosingMe thodName() { | |
1798 | retu rn synthet icMethodNa meComponen t(owner.na me); | |
1799 | } | |
1800 | ||
1801 | /** | |
1802 | * @retu rn Method name in a form that can be fol ded into a | |
1803 | * compo nent of a synthetic method nam e | |
1804 | */ | |
1805 | String s yntheticMe thodNameCo mponent(Na me name) { | |
1806 | if ( name == nu ll) { | |
1807 | return "nu ll"; | |
1808 | } | |
1809 | Stri ng methodN ame = name .toString( ); | |
1810 | if ( methodName .equals("< clinit>")) { | |
1811 | methodName = "static "; | |
1812 | } el se if (met hodName.eq uals("<ini t>")) { | |
1813 | methodName = "new"; | |
1814 | } | |
1815 | retu rn methodN ame; | |
1816 | } | |
1817 | } | |
1818 | ||
1819 | /* * | |
1820 | * This clas s retains all the us eful infor mation abo ut a lambd a expressi on; | |
1821 | * the conte nts of thi s class ar e filled b y the Lamb daAnalyzer visitor, | |
1822 | * and the u sed by the main tran slation ro utines in order to a djust refe rences | |
1823 | * to captur ed locals/ members, e tc. | |
1824 | * / | |
1825 | pr ivate clas s LambdaTr anslationC ontext ext ends Trans lationCont ext<JCLamb da> { | |
1826 | ||
1827 | /** vari able in th e enclosin g context to which t his lambda is assign ed */ | |
1828 | final Sy mbol self; | |
1829 | ||
1830 | /** vari able in th e enclosin g context to which t his lambda is assign ed */ | |
1831 | final Sy mbol assig nedTo; | |
1832 | ||
1833 | Map<Lamb daSymbolKi nd, Map<Sy mbol, Symb ol>> trans latedSymbo ls; | |
1834 | ||
1835 | /** the synthetic symbol for the metho d hoisting the trans lated lamb da */ | |
1836 | MethodSy mbol trans latedSym; | |
1837 | ||
1838 | List<JCV ariableDec l> synthet icParams; | |
1839 | ||
1840 | /** | |
1841 | * to pr event recu rsion, tra ck local c lasses pro cessed | |
1842 | */ | |
1843 | final Se t<Symbol> freeVarPro cessedLoca lClasses; | |
1844 | ||
1845 | /** | |
1846 | * For m ethod refe rences con verted to lambdas. The method | |
1847 | * refer ence recei ver expres sion. Must be treate d like a c aptured | |
1848 | * varia ble. | |
1849 | */ | |
1850 | JCExpres sion metho dReference Receiver; | |
1851 | ||
1852 | LambdaTr anslationC ontext(JCL ambda tree ) { | |
1853 | supe r(tree); | |
1854 | Fram e frame = frameStack .head; | |
1855 | swit ch (frame. tree.getTa g()) { | |
1856 | case
|
|
1857 | assign edTo = sel f = ((JCVa riableDecl ) frame.tr ee).sym; | |
1858 | break; | |
1859 | case ASSIG N: | |
1860 | self = null; | |
1861 | assign edTo = Tre eInfo.symb ol(((JCAss ign) frame .tree).get Variable() ); | |
1862 | break; | |
1863 | default: | |
1864 | assign edTo = sel f = null; | |
1865 | break; | |
1866 | } | |
1867 | ||
1868 | // T his symbol will be f illed-in i n complete | |
1869 | this .translate dSym = mak ePrivateSy ntheticMet hod(0, nul l, null, o wner.enclC lass()); | |
1870 | ||
1871 | tran slatedSymb ols = new EnumMap<>( LambdaSymb olKind.cla ss); | |
1872 | ||
1873 | tran slatedSymb ols.put(PA RAM, new L inkedHashM ap<Symbol, Symbol>() ); | |
1874 | tran slatedSymb ols.put(LO CAL_VAR, n ew LinkedH ashMap<Sym bol, Symbo l>()); | |
1875 | tran slatedSymb ols.put(CA PTURED_VAR , new Link edHashMap< Symbol, Sy mbol>()); | |
1876 | tran slatedSymb ols.put(CA PTURED_THI S, new Lin kedHashMap <Symbol, S ymbol>()); | |
1877 | tran slatedSymb ols.put(CA PTURED_OUT ER_THIS, n ew LinkedH ashMap<Sym bol, Symbo l>()); | |
1878 | tran slatedSymb ols.put(TY PE_VAR, ne w LinkedHa shMap<Symb ol, Symbol >()); | |
1879 | ||
1880 | free VarProcess edLocalCla sses = new HashSet<> (); | |
1881 | } | |
1882 | ||
1883 | /** | |
1884 | * For a serializa ble lambda , generate a disambi guating st ring | |
1885 | * which maximizes stability across de serializat ion. | |
1886 | * | |
1887 | * @retu rn String to differe ntiate syn thetic lam bda method names | |
1888 | */ | |
1889 | private String ser ializedLam bdaDisambi guation() { | |
1890 | Stri ngBuilder buf = new StringBuil der(); | |
1891 | // A ppend the enclosing method sig nature to differenti ate | |
1892 | // o verloaded enclosing methods. For lambda s enclosed in | |
1893 | // l ambdas, th e generate d lambda m ethod will not have type yet, | |
1894 | // b ut the enc losing met hod's name will have been gene rated | |
1895 | // w ith this s ame method , so it wi ll be uniq ue and nev er be | |
1896 | // o verloaded. | |
1897 | Asse rt.check( | |
1898 | owner. type != nu ll || | |
1899 | direct lyEnclosin gLambda() != null); | |
1900 | if ( owner.type != null) { | |
1901 | buf.append (typeSig(o wner.type) ); | |
1902 | buf.append (":"); | |
1903 | } | |
1904 | ||
1905 | // A dd target type info | |
1906 | buf. append(typ es.findDes criptorSym bol(tree.t ype.tsym). owner.flat Name()); | |
1907 | buf. append(" " ); | |
1908 | ||
1909 | // A dd variabl e assigned to | |
1910 | if ( assignedTo != null) { | |
1911 | buf.append (assignedT o.flatName ()); | |
1912 | buf.append ("="); | |
1913 | } | |
1914 | //ad d captured locals in fo: type, name, orde r | |
1915 | for (Symbol fv : getSymb olMap(CAPT URED_VAR). keySet()) { | |
1916 | if (fv != self) { | |
1917 | buf.ap pend(typeS ig(fv.type )); | |
1918 | buf.ap pend(" "); | |
1919 | buf.ap pend(fv.fl atName()); | |
1920 | buf.ap pend(","); | |
1921 | } | |
1922 | } | |
1923 | ||
1924 | retu rn buf.toS tring(); | |
1925 | } | |
1926 | ||
1927 | /** | |
1928 | * For a non-seria lizable la mbda, gene rate a sim ple method . | |
1929 | * | |
1930 | * @retu rn Name to use for t he synthet ic lambda method nam e | |
1931 | */ | |
1932 | private Name lambd aName() { | |
1933 | retu rn names.l ambda.appe nd(names.f romString( enclosingM ethodName( ) + "$" + lambdaCoun t++)); | |
1934 | } | |
1935 | ||
1936 | /** | |
1937 | * For a serializa ble lambda , generate a method name which maximizes | |
1938 | * name stability across des erializati on. | |
1939 | * | |
1940 | * @retu rn Name to use for t he synthet ic lambda method nam e | |
1941 | */ | |
1942 | private Name seria lizedLambd aName() { | |
1943 | Stri ngBuilder buf = new StringBuil der(); | |
1944 | buf. append(nam es.lambda) ; | |
1945 | // A ppend the name of th e method e nclosing t he lambda. | |
1946 | buf. append(enc losingMeth odName()); | |
1947 | buf. append('$' ); | |
1948 | // A ppend a ha sh of the disambigua ting strin g : enclos ing method | |
1949 | // s ignature, etc. | |
1950 | Stri ng disam = serialize dLambdaDis ambiguatio n(); | |
1951 | buf. append(Int eger.toHex String(dis am.hashCod e())); | |
1952 | buf. append('$' ); | |
1953 | // T he above a ppended na me compone nts may no t be uniqu e, append | |
1954 | // a count bas ed on the above name component s. | |
1955 | buf. append(syn theticMeth odNameCoun ts.getInde x(buf)); | |
1956 | Stri ng result = buf.toSt ring(); | |
1957 | //Sy stem.err.p rintf("ser ializedLam bdaName: % s -- %s\n" , result, disam); | |
1958 | retu rn names.f romString( result); | |
1959 | } | |
1960 | ||
1961 | /** | |
1962 | * Trans late a sym bol of a g iven kind into somet hing suita ble for th e | |
1963 | * synth etic lambd a body | |
1964 | */ | |
1965 | Symbol t ranslate(f inal Symbo l sym, Lam bdaSymbolK ind skind) { | |
1966 | Symb ol ret; | |
1967 | swit ch (skind) { | |
1968 | case CAPTU RED_THIS: | |
1969 | ret = sym; // s elf repres ented | |
1970 | break; | |
1971 | case TYPE_ VAR: | |
1972 | // Jus t erase th e type var | |
1973 | ret = new VarSym bol(sym.fl ags(), sym .name, | |
1974 | types.er asure(sym. type), sym .owner); | |
1975 | ||
1976 | /* thi s informat ion should also be k ept for LV T generati on at Gen | |
1977 | * a S ymbol with pos < sta rtPos won' t be track ed. | |
1978 | */ | |
1979 | ((VarS ymbol)ret) .pos = ((V arSymbol)s ym).pos; | |
1980 | break; | |
1981 | case CAPTU RED_VAR: | |
1982 | ret = new VarSym bol(SYNTHE TIC | FINA L | PARAME TER, sym.n ame, types .erasure(s ym.type), translated Sym) { | |
1983 | @O verride | |
1984 | pu blic Symbo l baseSymb ol() { | |
1985 | //keep m apping wit h original captured symbol | |
1986 | return s ym; | |
1987 | } | |
1988 | }; | |
1989 | break; | |
1990 | case CAPTU RED_OUTER_ THIS: | |
1991 | Name n ame = name s.fromStri ng(new Str ing(sym.fl atName().t oString() + names.do llarThis)) ; | |
1992 | ret = new VarSym bol(SYNTHE TIC | FINA L | PARAME TER, name, types.era sure(sym.t ype), tran slatedSym) { | |
1993 | @O verride | |
1994 | pu blic Symbo l baseSymb ol() { | |
1995 | //keep m apping wit h original captured symbol | |
1996 | return s ym; | |
1997 | } | |
1998 | }; | |
1999 | break; | |
2000 | case LOCAL _VAR: | |
2001 | ret = new VarSym bol(sym.fl ags() & FI NAL, sym.n ame, sym.t ype, trans latedSym); | |
2002 | ((VarS ymbol) ret ).pos = (( VarSymbol) sym).pos; | |
2003 | break; | |
2004 | case PARAM : | |
2005 | ret = new VarSym bol((sym.f lags() & F INAL) | PA RAMETER, s ym.name, t ypes.erasu re(sym.typ e), transl atedSym); | |
2006 | ((VarS ymbol) ret ).pos = (( VarSymbol) sym).pos; | |
2007 | break; | |
2008 | default: | |
2009 | Assert .error(ski nd.name()) ; | |
2010 | throw new Assert ionError() ; | |
2011 | } | |
2012 | if ( ret != sym ) { | |
2013 | ret.setDec larationAt tributes(s ym.getRawA ttributes( )); | |
2014 | ret.setTyp eAttribute s(sym.getR awTypeAttr ibutes()); | |
2015 | } | |
2016 | retu rn ret; | |
2017 | } | |
2018 | ||
2019 | void add Symbol(Sym bol sym, L ambdaSymbo lKind skin d) { | |
2020 | if ( skind == C APTURED_TH IS && sym != null && sym.kind == TYP && !typesUnde rConstruct ion.isEmpt y()) { | |
2021 | ClassSymbo l currentC lass = cur rentClass( ); | |
2022 | if (curren tClass != null && ty pesUnderCo nstruction .contains( currentCla ss)) { | |
2023 | // ref erence mus t be to en closing ou ter instan ce, mutate capture k ind. | |
2024 | Assert .check(sym != curren tClass); / / should h ave been c aught righ t in Attr | |
2025 | skind = CAPTURED _OUTER_THI S; | |
2026 | } | |
2027 | } | |
2028 | Map< Symbol, Sy mbol> tran sMap = get SymbolMap( skind); | |
2029 | if ( !transMap. containsKe y(sym)) { | |
2030 | transMap.p ut(sym, tr anslate(sy m, skind)) ; | |
2031 | } | |
2032 | } | |
2033 | ||
2034 | Map<Symb ol, Symbol > getSymbo lMap(Lambd aSymbolKin d skind) { | |
2035 | Map< Symbol, Sy mbol> m = translated Symbols.ge t(skind); | |
2036 | Asse rt.checkNo nNull(m); | |
2037 | retu rn m; | |
2038 | } | |
2039 | ||
2040 | JCTree t ranslate(J CIdent lam bdaIdent) { | |
2041 | for (LambdaSym bolKind ki nd : Lambd aSymbolKin d.values() ) { | |
2042 | Map<Symbol , Symbol> m = getSym bolMap(kin d); | |
2043 | switch(kin d) { | |
2044 | defaul t: | |
2045 | if (m.contai nsKey(lamb daIdent.sy m)) { | |
2046 | Symbol t Sym = m.ge t(lambdaId ent.sym); | |
2047 | JCTree t = make.Id ent(tSym). setType(la mbdaIdent. type); | |
2048 | tSym.set TypeAttrib utes(lambd aIdent.sym .getRawTyp eAttribute s()); | |
2049 | return t ; | |
2050 | } | |
2051 | br eak; | |
2052 | case C APTURED_OU TER_THIS: | |
2053 | if (lambdaId ent.sym.ow ner.kind = = TYP && m .containsK ey(lambdaI dent.sym.o wner)) { | |
2054 | // Trans form outer instance variable r eferences anchoring them to th e captured synthetic . | |
2055 | Symbol t Sym = m.ge t(lambdaId ent.sym.ow ner); | |
2056 | JCExpres sion t = m ake.Ident( tSym).setT ype(lambda Ident.sym. owner.type ); | |
2057 | tSym.set TypeAttrib utes(lambd aIdent.sym .owner.get RawTypeAtt ributes()) ; | |
2058 | t = make .Select(t, lambdaIde nt.name); | |
2059 | t.setTyp e(lambdaId ent.type); | |
2060 | TreeInfo .setSymbol (t, lambda Ident.sym) ; | |
2061 | return t ; | |
2062 | } | |
2063 | br eak; | |
2064 | } | |
2065 | } | |
2066 | retu rn null; | |
2067 | } | |
2068 | ||
2069 | /* Trans late away qualified this expre ssions, an choring th em to synt hetic para meters tha t | |
2070 | captu re the qua lified thi s handle. `fieldAcce ss' is gua ranteed to one such. | |
2071 | */ | |
2072 | public J CTree tran slate(JCFi eldAccess fieldAcces s) { | |
2073 | Asse rt.check(f ieldAccess .name == n ames._this ); | |
2074 | Map< Symbol, Sy mbol> m = translated Symbols.ge t(LambdaSy mbolKind.C APTURED_OU TER_THIS); | |
2075 | if ( m.contains Key(fieldA ccess.sym. owner)) { | |
2076 | Symbol tSy m = m.get( fieldAcces s.sym.owne r); | |
2077 | JCExpressi on t = mak e.Ident(tS ym).setTyp e(fieldAcc ess.sym.ow ner.type); | |
2078 | tSym.setTy peAttribut es(fieldAc cess.sym.o wner.getRa wTypeAttri butes()); | |
2079 | return t; | |
2080 | } | |
2081 | retu rn null; | |
2082 | } | |
2083 | ||
2084 | /** | |
2085 | * The t ranslatedS ym is not complete/a ccurate un til the an alysis is | |
2086 | * finis hed. Once the analy sis is fin ished, the translate dSym is | |
2087 | * "comp leted" -- updated wi th type in formation, access mo difiers, | |
2088 | * and f ull parame ter list. | |
2089 | */ | |
2090 | void com plete() { | |
2091 | if ( syntheticP arams != n ull) { | |
2092 | return; | |
2093 | } | |
2094 | bool ean inInte rface = tr anslatedSy m.owner.is Interface( ); | |
2095 | bool ean thisRe ferenced = !getSymbo lMap(CAPTU RED_THIS). isEmpty(); | |
2096 | ||
2097 | // I f instance access is n't needed , make it static. | |
2098 | // I nterface i nstance me thods must be defaul t methods. | |
2099 | // L ambda meth ods are pr ivate synt hetic. | |
2100 | // I nherit ACC _STRICT fr om the enc losing met hod, or, f or clinit, | |
2101 | // f rom the cl ass. | |
2102 | tran slatedSym. flags_fiel d = SYNTHE TIC | LAMB DA_METHOD | | |
2103 | owner. flags_fiel d & STRICT FP | | |
2104 | owner. owner.flag s_field & STRICTFP | | |
2105 | PRIVAT E | | |
2106 | (thisR eferenced? (inInterf ace? DEFAU LT : 0) : STATIC); | |
2107 | ||
2108 | //co mpute synt hetic para ms | |
2109 | List Buffer<JCV ariableDec l> params = new List Buffer<>() ; | |
2110 | List Buffer<Var Symbol> pa rameterSym bols = new ListBuffe r<>(); | |
2111 | ||
2112 | // T he signatu re of the method is augmented with the f ollowing | |
2113 | // s ynthetic p arameters: | |
2114 | // | |
2115 | // 1 ) referenc e to enclo sing conte xts captur ed by the lambda exp ression | |
2116 | // 2 ) enclosin g locals c aptured by the lambd a expressi on | |
2117 | for (Symbol th isSym : ge tSymbolMap (CAPTURED_ VAR).value s()) { | |
2118 | params.app end(make.V arDef((Var Symbol) th isSym, nul l)); | |
2119 | parameterS ymbols.app end((VarSy mbol) this Sym); | |
2120 | } | |
2121 | for (Symbol th isSym : ge tSymbolMap (CAPTURED_ OUTER_THIS ).values() ) { | |
2122 | params.app end(make.V arDef((Var Symbol) th isSym, nul l)); | |
2123 | parameterS ymbols.app end((VarSy mbol) this Sym); | |
2124 | } | |
2125 | for (Symbol th isSym : ge tSymbolMap (PARAM).va lues()) { | |
2126 | params.app end(make.V arDef((Var Symbol) th isSym, nul l)); | |
2127 | parameterS ymbols.app end((VarSy mbol) this Sym); | |
2128 | } | |
2129 | synt heticParam s = params .toList(); | |
2130 | ||
2131 | tran slatedSym. params = p arameterSy mbols.toLi st(); | |
2132 | ||
2133 | // C ompute and set the l ambda name | |
2134 | tran slatedSym. name = isS erializabl e() | |
2135 | ? seri alizedLamb daName() | |
2136 | : lamb daName(); | |
2137 | ||
2138 | //pr epend synt hetic args to transl ated lambd a method s ignature | |
2139 | tran slatedSym. type = typ es.createM ethodTypeW ithParamet ers( | |
2140 | genera tedLambdaS ig(), | |
2141 | TreeIn fo.types(s yntheticPa rams)); | |
2142 | } | |
2143 | ||
2144 | Type gen eratedLamb daSig() { | |
2145 | retu rn types.e rasure(tre e.getDescr iptorType( types)); | |
2146 | } | |
2147 | } | |
2148 | ||
2149 | /* * | |
2150 | * This clas s retains all the us eful infor mation abo ut a metho d referenc e; | |
2151 | * the conte nts of thi s class ar e filled b y the Lamb daAnalyzer visitor, | |
2152 | * and the u sed by the main tran slation ro utines in order to a djust meth od | |
2153 | * reference s (i.e. in case a br idge is ne eded) | |
2154 | * / | |
2155 | pr ivate fina l class Re ferenceTra nslationCo ntext exte nds Transl ationConte xt<JCMembe rReference > { | |
2156 | ||
2157 | final bo olean isSu per; | |
2158 | final Sy mbol sigPo lySym; | |
2159 | ||
2160 | Referenc eTranslati onContext( JCMemberRe ference tr ee) { | |
2161 | supe r(tree); | |
2162 | this .isSuper = tree.hasK ind(Refere nceKind.SU PER); | |
2163 | this .sigPolySy m = isSign aturePolym orphic() | |
2164 | ? make PrivateSyn theticMeth od(tree.sy m.flags(), | |
2165 | tree .sym.name, | |
2166 | brid gedRefSig( ), | |
2167 | tree .sym.enclC lass()) | |
2168 | : null ; | |
2169 | } | |
2170 | ||
2171 | /** | |
2172 | * Get t he opcode associated with this method re ference | |
2173 | */ | |
2174 | int refe renceKind( ) { | |
2175 | retu rn LambdaT oMethod.th is.referen ceKind(tre e.sym); | |
2176 | } | |
2177 | ||
2178 | boolean needsVarAr gsConversi on() { | |
2179 | retu rn tree.va rargsEleme nt != null ; | |
2180 | } | |
2181 | ||
2182 | /** | |
2183 | * @retu rn Is this an array operation like clone () | |
2184 | */ | |
2185 | boolean isArrayOp( ) { | |
2186 | retu rn tree.sy m.owner == syms.arra yClass; | |
2187 | } | |
2188 | ||
2189 | boolean receiverAc cessible() { | |
2190 | //ha ck needed to workaro und 292 bu g (7087658 ) | |
2191 | //wh en 292 iss ue is fixe d we shoul d remove t his and ch ange the b ackend | |
2192 | //co de to alwa ys generat e a method handle to an access ible metho d | |
2193 | retu rn tree.ow nerAccessi ble; | |
2194 | } | |
2195 | ||
2196 | /** | |
2197 | * The V M does not support a ccess acro ss nested classes (8 010319). | |
2198 | * Were that ever to change, this shou ld be remo ved. | |
2199 | */ | |
2200 | boolean isPrivateI nOtherClas s() { | |
2201 | retu rn (tree. sym.flags( ) & PRIVAT E) != 0 && | |
2202 | !types .isSameTyp e( | |
2203 | types.eras ure(tree.s ym.enclCla ss().asTyp e()), | |
2204 | types.eras ure(owner. enclClass( ).asType() )); | |
2205 | } | |
2206 | ||
2207 | /** | |
2208 | * Signa ture polym orphic met hods need special ha ndling. | |
2209 | * e.g. MethodHand le.invoke( ) MethodHa ndle.invok eExact() | |
2210 | */ | |
2211 | final bo olean isSi gnaturePol ymorphic() { | |
2212 | retu rn tree.s ym.kind == MTH && | |
2213 | types. isSignatur ePolymorph ic((Method Symbol)tre e.sym); | |
2214 | } | |
2215 | ||
2216 | /** | |
2217 | * Erasu re destroy s the impl ementation parameter subtype | |
2218 | * relat ionship fo r intersec tion types | |
2219 | */ | |
2220 | boolean interfaceP arameterIs Intersecti onType() { | |
2221 | List <Type> tl = tree.get Descriptor Type(types ).getParam eterTypes( ); | |
2222 | if ( tree.kind == Referen ceKind.UNB OUND) { | |
2223 | tl = tl.ta il; | |
2224 | } | |
2225 | for (; tl.nonE mpty(); tl = tl.tail ) { | |
2226 | Type pt = tl.head; | |
2227 | if (pt.get Kind() == TypeKind.T YPEVAR) { | |
2228 | TypeVa r tv = (Ty peVar) pt; | |
2229 | if (tv .bound.get Kind() == TypeKind.I NTERSECTIO N) { | |
2230 | re turn true; | |
2231 | } | |
2232 | } | |
2233 | } | |
2234 | retu rn false; | |
2235 | } | |
2236 | ||
2237 | /** | |
2238 | * Does this refer ence need to be conv erted to a lambda | |
2239 | * (i.e. var args need to be expanded or "super" is used) | |
2240 | */ | |
2241 | final bo olean need sConversio nToLambda( ) { | |
2242 | retu rn interfa ceParamete rIsInterse ctionType( ) || | |
2243 | isSupe r || | |
2244 | needsV arArgsConv ersion() | | | |
2245 | isArra yOp() || | |
2246 | isPriv ateInOther Class() || | |
2247 | !recei verAccessi ble() || | |
2248 | (tree. getMode() == Referen ceMode.NEW && | |
2249 | tree .kind != R eferenceKi nd.ARRAY_C TOR && | |
2250 | (tre e.sym.owne r.isLocal( ) || tree. sym.owner. isInner()) ); | |
2251 | } | |
2252 | ||
2253 | Type gen eratedRefS ig() { | |
2254 | retu rn types.e rasure(tre e.sym.type ); | |
2255 | } | |
2256 | ||
2257 | Type bri dgedRefSig () { | |
2258 | retu rn types.e rasure(typ es.findDes criptorSym bol(tree.t argets.hea d.tsym).ty pe); | |
2259 | } | |
2260 | } | |
2261 | } | |
2262 | // </e ditor-fold > | |
2263 | ||
2264 | /* | |
2265 | * The se keys pr ovide mapp ings for v arious tra nslated la mbda symbo ls | |
2266 | * and the preva iling orde r must be maintained . | |
2267 | */ | |
2268 | enum L ambdaSymbo lKind { | |
2269 | PA RAM, // ori ginal to t ranslated lambda par ameters | |
2270 | LO CAL_VAR, // ori ginal to t ranslated lambda loc als | |
2271 | CA PTURED_VAR , // var iables in enclosing scope to t ranslated synthetic parameters | |
2272 | CA PTURED_THI S, // cla ss symbols to transl ated synth etic param eters (for captured member acc ess) | |
2273 | CA PTURED_OUT ER_THIS, / / used whe n `this' c apture is illegal, b ut outer t his captur e is legit (JDK-8129 740) | |
2274 | TY PE_VAR; // ori ginal to t ranslated lambda typ e variable s | |
2275 | } | |
2276 | ||
2277 | /** | |
2278 | * *** ********** ********** ********** ********** ********** ********** * | |
2279 | * Sig nature Gen eration | |
2280 | * *** ********** ********** ********** ********** ********** ********** * | |
2281 | */ | |
2282 | ||
2283 | privat e String t ypeSig(Typ e type) { | |
2284 | L2 MSignature Generator sg = new L 2MSignatur eGenerator (); | |
2285 | sg .assembleS ig(type); | |
2286 | re turn sg.to String(); | |
2287 | } | |
2288 | ||
2289 | privat e String c lassSig(Ty pe type) { | |
2290 | L2 MSignature Generator sg = new L 2MSignatur eGenerator (); | |
2291 | sg .assembleC lassSig(ty pe); | |
2292 | re turn sg.to String(); | |
2293 | } | |
2294 | ||
2295 | /** | |
2296 | * Sig nature Gen eration | |
2297 | */ | |
2298 | privat e class L2 MSignature Generator extends Ty pes.Signat ureGenerat or { | |
2299 | ||
2300 | /* * | |
2301 | * An output buffer fo r type sig natures. | |
2302 | * / | |
2303 | St ringBuilde r sb = new StringBui lder(); | |
2304 | ||
2305 | L2 MSignature Generator( ) { | |
2306 | super(ty pes); | |
2307 | } | |
2308 | ||
2309 | @O verride | |
2310 | pr otected vo id append( char ch) { | |
2311 | sb.appen d(ch); | |
2312 | } | |
2313 | ||
2314 | @O verride | |
2315 | pr otected vo id append( byte[] ba) { | |
2316 | sb.appen d(new Stri ng(ba)); | |
2317 | } | |
2318 | ||
2319 | @O verride | |
2320 | pr otected vo id append( Name name) { | |
2321 | sb.appen d(name.toS tring()); | |
2322 | } | |
2323 | ||
2324 | @O verride | |
2325 | pu blic Strin g toString () { | |
2326 | return s b.toString (); | |
2327 | } | |
2328 | } | |
2329 | } |
Araxis Merge (but not the data content of this report) is Copyright © 1993-2016 Araxis Ltd (www.araxis.com). All rights reserved.