1 | |
|
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
|
18 | |
|
19 | |
|
20 | |
|
21 | |
|
22 | |
|
23 | |
|
24 | |
|
25 | |
package com.sun.tools.javafx.comp; |
26 | |
|
27 | |
import java.util.HashSet; |
28 | |
import java.util.Set; |
29 | |
import java.util.regex.Pattern; |
30 | |
import javax.lang.model.type.TypeKind; |
31 | |
|
32 | |
import com.sun.javafx.api.JavafxBindStatus; |
33 | |
import com.sun.javafx.api.tree.SequenceSliceTree; |
34 | |
import com.sun.tools.javac.code.*; |
35 | |
import static com.sun.tools.javac.code.Flags.*; |
36 | |
import com.sun.tools.javac.code.Type.*; |
37 | |
import com.sun.tools.javac.jvm.Target; |
38 | |
import com.sun.tools.javac.tree.JCTree; |
39 | |
import com.sun.tools.javac.tree.JCTree.*; |
40 | |
import com.sun.tools.javac.tree.TreeInfo; |
41 | |
import com.sun.tools.javac.tree.TreeMaker; |
42 | |
import com.sun.tools.javac.util.*; |
43 | |
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; |
44 | |
import com.sun.tools.javafx.code.FunctionType; |
45 | |
import com.sun.tools.javafx.code.JavafxFlags; |
46 | |
import com.sun.tools.javafx.code.JavafxSymtab; |
47 | |
import com.sun.tools.javafx.code.JavafxTypes; |
48 | |
import static com.sun.tools.javafx.code.JavafxVarSymbol.*; |
49 | |
import static com.sun.tools.javafx.comp.JavafxDefs.*; |
50 | |
import com.sun.tools.javafx.comp.JavafxInitializationBuilder.JavafxClassModel; |
51 | |
import com.sun.tools.javafx.comp.JavafxAnalyzeClass.TranslatedAttributeInfo; |
52 | |
import com.sun.tools.javafx.comp.JavafxAnalyzeClass.TranslatedOverrideAttributeInfo; |
53 | |
import com.sun.tools.javafx.comp.JavafxTypeMorpher.TypeMorphInfo; |
54 | |
import com.sun.tools.javafx.comp.JavafxTypeMorpher.VarMorphInfo; |
55 | |
import com.sun.tools.javafx.tree.*; |
56 | |
|
57 | |
|
58 | |
|
59 | |
|
60 | |
|
61 | |
|
62 | |
|
63 | |
|
64 | 6241 | public class JavafxToJava extends JavafxTranslationSupport implements JavafxVisitor { |
65 | 12 | protected static final Context.Key<JavafxToJava> jfxToJavaKey = |
66 | |
new Context.Key<JavafxToJava>(); |
67 | |
|
68 | |
|
69 | |
|
70 | |
|
71 | |
JCTree result; |
72 | |
|
73 | |
|
74 | |
|
75 | |
|
76 | |
private final JavafxToBound toBound; |
77 | |
private final JavafxInitializationBuilder initBuilder; |
78 | |
|
79 | |
private final JCExpression doNotInitializeMarker; |
80 | |
|
81 | |
|
82 | |
|
83 | |
|
84 | |
|
85 | |
|
86 | |
|
87 | |
|
88 | 399 | private ListBuffer<JCStatement> prependToDefinitions = null; |
89 | 399 | private ListBuffer<JCStatement> prependToStatements = null; |
90 | |
|
91 | 399 | private ListBuffer<JCExpression> additionalImports = null; |
92 | |
|
93 | 36 | public enum Wrapped { |
94 | 12 | InLocation, |
95 | 12 | InNothing |
96 | |
} |
97 | |
|
98 | 399 | Wrapped wrap = Wrapped.InNothing; |
99 | |
|
100 | |
|
101 | |
|
102 | 53 | enum Yield { |
103 | 12 | ToExpression, |
104 | 12 | ToReturnStatement, |
105 | 12 | ToExecStatement |
106 | |
} |
107 | |
|
108 | |
|
109 | 399 | Yield yield = Yield.ToExpression; |
110 | |
|
111 | |
private JavafxEnv<JavafxAttrContext> attrEnv; |
112 | |
private Target target; |
113 | |
|
114 | |
abstract static class Translator { |
115 | |
|
116 | |
protected DiagnosticPosition diagPos; |
117 | |
protected final JavafxToJava toJava; |
118 | |
protected final JavafxDefs defs; |
119 | |
protected final JavafxTypes types; |
120 | |
protected final JavafxSymtab syms; |
121 | |
|
122 | 6769 | Translator(DiagnosticPosition diagPos, JavafxToJava toJava) { |
123 | 6769 | this.diagPos = diagPos; |
124 | 6769 | this.toJava = toJava; |
125 | 6769 | this.defs = toJava.defs; |
126 | 6769 | this.types = toJava.types; |
127 | 6769 | this.syms = toJava.syms; |
128 | 6769 | } |
129 | |
|
130 | |
protected abstract JCTree doit(); |
131 | |
|
132 | |
protected TreeMaker m() { |
133 | 18076 | return toJava.make.at(diagPos); |
134 | |
} |
135 | |
|
136 | |
|
137 | |
|
138 | |
|
139 | |
protected JCExpression makeExpression(Type type) { |
140 | 1554 | return toJava.makeTypeTree(diagPos, type, true); |
141 | |
} |
142 | |
} |
143 | |
|
144 | |
|
145 | |
|
146 | |
|
147 | |
static final boolean generateNullChecks = true; |
148 | |
|
149 | |
private static final String sequencesRangeString = "com.sun.javafx.runtime.sequence.Sequences.range"; |
150 | |
private static final String sequencesRangeExclusiveString = "com.sun.javafx.runtime.sequence.Sequences.rangeExclusive"; |
151 | |
private static final String sequenceBuilderString = "com.sun.javafx.runtime.sequence.SequenceBuilder"; |
152 | |
private static final String boundSequenceBuilderString = "com.sun.javafx.runtime.sequence.BoundSequenceBuilder"; |
153 | |
private static final String toSequenceString = "toSequence"; |
154 | |
private static final String methodThrowsString = "java.lang.Throwable"; |
155 | |
private JFXClassDeclaration currentClass; |
156 | |
|
157 | |
|
158 | 399 | Set<ClassSymbol> hasOuters = new HashSet<ClassSymbol>(); |
159 | |
|
160 | 399 | private Set<VarSymbol> locallyBound = new HashSet<VarSymbol>(); |
161 | |
|
162 | 12 | private static final Pattern EXTENDED_FORMAT_PATTERN = Pattern.compile("%[<$0-9]*[tT][guwxGUVWXE]"); |
163 | |
|
164 | |
public static JavafxToJava instance(Context context) { |
165 | 1596 | JavafxToJava instance = context.get(jfxToJavaKey); |
166 | 1596 | if (instance == null) |
167 | 399 | instance = new JavafxToJava(context); |
168 | 1596 | return instance; |
169 | |
} |
170 | |
|
171 | |
protected JavafxToJava(Context context) { |
172 | 399 | super(context); |
173 | |
|
174 | 399 | context.put(jfxToJavaKey, this); |
175 | |
|
176 | 399 | toBound = JavafxToBound.instance(context); |
177 | 399 | initBuilder = JavafxInitializationBuilder.instance(context); |
178 | 399 | target = Target.instance(context); |
179 | |
|
180 | 399 | doNotInitializeMarker = make.Literal(TypeTags.INT, 666); |
181 | 399 | } |
182 | |
|
183 | |
|
184 | |
|
185 | |
@SuppressWarnings("unchecked") |
186 | |
public <T extends JCTree> T translate(T tree) { |
187 | |
T ret; |
188 | 37440 | Yield prevYield = yield; |
189 | 37440 | yield = Yield.ToExpression; |
190 | 37440 | if (tree == null) { |
191 | 466 | ret = null; |
192 | |
} else { |
193 | 36974 | tree.accept(this); |
194 | 36974 | ret = (T)this.result; |
195 | 36974 | this.result = null; |
196 | |
} |
197 | 37440 | yield = prevYield; |
198 | 37440 | return ret; |
199 | |
} |
200 | |
|
201 | |
public JCExpression translate(JCExpression tree, Type type) { |
202 | 5389 | if (tree == null) |
203 | 0 | return null; |
204 | 5389 | return convertTranslated(translate(tree), tree.pos(), tree.type, type); |
205 | |
} |
206 | |
|
207 | |
public JCExpression convertTranslated(JCExpression translated, DiagnosticPosition diagPos, |
208 | |
Type sourceType, Type type) { |
209 | 5515 | if (types.isSequence(sourceType) && types.isArray(type)) { |
210 | 1 | ListBuffer<JCStatement> stats = ListBuffer.lb(); |
211 | 1 | Type elemType = types.elemtype(type); |
212 | 1 | if (elemType.isPrimitive()) { |
213 | 0 | String mname = "toArray"; |
214 | 0 | if (elemType == syms.floatType) |
215 | 0 | mname = "toFloatArray"; |
216 | 0 | return callExpression(diagPos, makeTypeTree( diagPos,syms.javafx_SequencesType, false), |
217 | |
mname, translated); |
218 | |
} |
219 | 1 | JCVariableDecl tmpVar = makeTmpVar(diagPos, sourceType, translated); |
220 | 1 | stats.append(tmpVar); |
221 | 1 | JCVariableDecl arrVar = makeTmpVar(diagPos, "arr", type, |
222 | |
make.NewArray(makeTypeTree(diagPos, elemType, true), |
223 | |
List.<JCExpression>of(callExpression(diagPos, make.Ident(tmpVar.name), "size")), null)); |
224 | 1 | stats.append(arrVar); |
225 | 1 | stats.append(callStatement(diagPos, make.Ident(tmpVar.name), "toArray", |
226 | |
List.of(make.Ident(arrVar.name), make.Literal(TypeTags.INT, 0)))); |
227 | 1 | JCIdent ident2 = make.Ident(arrVar.name); |
228 | 1 | return makeBlockExpression(diagPos, stats, ident2); |
229 | |
|
230 | |
} |
231 | 5514 | if (types.isArray(sourceType) && types.isSequence(type)) { |
232 | 7 | ListBuffer<JCStatement> stats = ListBuffer.lb(); |
233 | 7 | Type elemType = types.elemtype(sourceType); |
234 | 7 | String mname = "fromArray"; |
235 | 7 | if (elemType.isPrimitive()) |
236 | 1 | return callExpression(diagPos, makeTypeTree( diagPos,syms.javafx_SequencesType, false), |
237 | |
mname, translated); |
238 | |
else { |
239 | 6 | List<JCExpression> args = |
240 | |
List.of(make.at(diagPos).Select(makeTypeTree(diagPos, elemType, true), names._class), |
241 | |
translated); |
242 | 6 | return callExpression(diagPos, makeTypeTree( diagPos,syms.javafx_SequencesType, false), |
243 | |
mname, args); |
244 | |
} |
245 | |
} |
246 | 5507 | if (types.isSequence(type) && ! types.isSequence(sourceType)) { |
247 | 35 | return callExpression(diagPos, |
248 | |
makeQualifiedTree(diagPos, "com.sun.javafx.runtime.sequence.Sequences"), |
249 | |
"singleton", |
250 | |
List.of(makeElementClassObject(diagPos, types.elementType(type)), |
251 | |
translated)); |
252 | |
} |
253 | |
|
254 | 5472 | if (sourceType == syms.javafx_IntegerType || |
255 | |
type == syms.javafx_IntegerType) { |
256 | 1112 | if (sourceType != type && type.isPrimitive()) { |
257 | 137 | translated = make.at(diagPos).TypeCast(type, translated); |
258 | |
} |
259 | |
} |
260 | |
|
261 | 5472 | return translated; |
262 | |
} |
263 | |
|
264 | |
|
265 | |
|
266 | |
public <T extends JCTree> List<T> translate(List<T> trees) { |
267 | 4441 | ListBuffer<T> translated = ListBuffer.lb(); |
268 | 4441 | if (trees == null) return null; |
269 | 7215 | for (List<T> l = trees; l.nonEmpty(); l = l.tail) { |
270 | 2774 | T tree = translate(l.head); |
271 | 2774 | if (tree != null) { |
272 | 2774 | translated.append( tree ); |
273 | |
} |
274 | |
} |
275 | 4441 | return translated.toList(); |
276 | |
} |
277 | |
|
278 | |
public List<JCExpression> translate(List<JCExpression> trees, List<Type> types) { |
279 | 100 | ListBuffer<JCExpression> translated = ListBuffer.lb(); |
280 | 100 | if (trees == null) return null; |
281 | 100 | List<Type> t = types; |
282 | 197 | for (List<JCExpression> l = trees; l.nonEmpty(); l = l.tail, t = t.tail) { |
283 | 97 | JCExpression tree = translate(l.head, t.head); |
284 | 97 | if (tree != null) { |
285 | 97 | translated.append( tree ); |
286 | |
} |
287 | |
} |
288 | 100 | return translated.toList(); |
289 | |
} |
290 | |
|
291 | |
|
292 | |
|
293 | |
|
294 | |
|
295 | |
|
296 | |
|
297 | |
private List<JCStatement> translateStatements(List<JCStatement> stmts) { |
298 | 580 | ListBuffer<JCStatement> prevPrependToStatements = prependToStatements; |
299 | 580 | prependToStatements = ListBuffer.lb(); |
300 | 580 | List<JCStatement> translatedStats = translate(stmts); |
301 | 580 | translatedStats = translatedStats.prependList(prependToStatements.toList()); |
302 | 580 | prependToStatements = prevPrependToStatements; |
303 | 580 | return translatedStats; |
304 | |
} |
305 | |
|
306 | |
|
307 | |
|
308 | |
public <T extends JCTree> T translate(T tree, Wrapped newState) { |
309 | 8986 | Wrapped prevWrap = wrap; |
310 | 8986 | wrap = newState; |
311 | 8986 | T ret = translate(tree); |
312 | 8986 | wrap = prevWrap; |
313 | 8986 | return ret; |
314 | |
} |
315 | |
|
316 | |
JCStatement translateExpressionToStatement(JCExpression expr) { |
317 | 5953 | assert yield != Yield.ToExpression; |
318 | 5953 | if (expr == null) { |
319 | 0 | return null; |
320 | |
} else { |
321 | 5953 | expr.accept(this); |
322 | 5953 | JCTree ret = this.result; |
323 | 5953 | this.result = null; |
324 | 5953 | return ret instanceof JCStatement? |
325 | |
(JCStatement)ret |
326 | |
: toCorrectReturn(expr, (JCExpression)ret ); |
327 | |
} |
328 | |
} |
329 | |
|
330 | |
JCStatement translateExpressionToStatement(JCExpression expr, Wrapped newState, Type targetType) { |
331 | 4106 | Wrapped prevWrap = wrap; |
332 | 4106 | Yield prevYield = yield; |
333 | 4106 | wrap = newState; |
334 | |
JCStatement ret; |
335 | 4106 | if (targetType == expr.type || targetType==syms.voidType |
336 | |
|| targetType == null || expr.type == syms.unreachableType) { |
337 | 4097 | yield = targetType==syms.voidType? Yield.ToExecStatement : Yield.ToReturnStatement; |
338 | 4097 | ret = translateExpressionToStatement(expr); |
339 | |
} else { |
340 | 9 | yield = Yield.ToExpression; |
341 | 9 | ret = make.at(expr).Return(translate(expr, targetType)); |
342 | |
} |
343 | 4106 | yield = prevYield; |
344 | 4106 | wrap = prevWrap; |
345 | 4106 | return ret; |
346 | |
} |
347 | |
|
348 | |
JCStatement translateExpressionToStatement(JCExpression expr, Type targetType) { |
349 | 4106 | return translateExpressionToStatement(expr, wrap, targetType); |
350 | |
} |
351 | |
|
352 | |
void setLocallyBound(VarSymbol vsym) { |
353 | 45 | locallyBound.add(vsym); |
354 | 45 | } |
355 | |
|
356 | |
JCBlock asBlock(JCStatement stmt) { |
357 | 831 | if (stmt.getTag() == JavafxTag.BLOCK) { |
358 | 339 | return (JCBlock)stmt; |
359 | |
} else { |
360 | 492 | return make.at(stmt).Block(0L, List.of(stmt)); |
361 | |
} |
362 | |
} |
363 | |
|
364 | |
JCStatement toCorrectReturn(JCExpression expr, JCExpression translated) { |
365 | 2290 | switch (yield) { |
366 | |
case ToExecStatement: |
367 | 1921 | return make.at(expr).Exec( translated ); |
368 | |
case ToReturnStatement: |
369 | 369 | return make.at(expr).Return( translated ); |
370 | |
case ToExpression: |
371 | |
default: |
372 | 0 | assert false : "this method should not be called"; |
373 | 0 | return null; |
374 | |
} |
375 | |
} |
376 | |
|
377 | |
public void toJava(JavafxEnv<JavafxAttrContext> attrEnv) { |
378 | 340 | this.attrEnv = attrEnv; |
379 | |
|
380 | 340 | attrEnv.toplevel = translate(attrEnv.toplevel); |
381 | 340 | } |
382 | |
|
383 | |
|
384 | |
|
385 | |
|
386 | |
|
387 | |
|
388 | |
|
389 | |
|
390 | |
|
391 | |
|
392 | |
|
393 | |
|
394 | |
|
395 | |
|
396 | |
public void fixupBlockExpression (JFXBlockExpression body, JFXClassDeclaration module) { |
397 | 340 | boolean changed = false; |
398 | 340 | ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>(); |
399 | |
|
400 | 340 | for (JCStatement stat : body.stats) { |
401 | 2351 | if (stat instanceof JFXVar) { |
402 | 781 | JFXVar decl = (JFXVar) stat; |
403 | 781 | if ((decl.sym.flags_field & JavafxFlags.INNER_ACCESS) != 0) { |
404 | 35 | decl.sym.flags_field |= STATIC; |
405 | 35 | changed = true; |
406 | 35 | JCExpression init = decl.init; |
407 | 35 | decl.sym.owner = module.type.tsym; |
408 | 35 | if (init != null) { |
409 | 33 | Name name = decl.name; |
410 | 33 | make.at(decl); |
411 | 33 | JavafxBindStatus bindStatus = decl.getBindStatus(); |
412 | 33 | if (bindStatus != JavafxBindStatus.UNBOUND) |
413 | 4 | init = fxmake.BindExpression(init, bindStatus); |
414 | 33 | JCIdent lhs = make.Ident(name); |
415 | 33 | lhs.sym = decl.sym; |
416 | 33 | stats.append(make.Exec(make.Assign(lhs, init))); |
417 | 33 | decl.init = doNotInitializeMarker; |
418 | |
} |
419 | 35 | module.setMembers(module.getMembers().prepend(decl)); |
420 | 35 | continue; |
421 | |
} |
422 | |
} |
423 | 2316 | stats.append(stat); |
424 | |
} |
425 | 340 | if (changed) { |
426 | 18 | body.stats = stats.toList(); |
427 | |
} |
428 | 340 | } |
429 | |
|
430 | |
|
431 | |
|
432 | |
|
433 | |
|
434 | |
|
435 | |
|
436 | |
|
437 | |
|
438 | |
|
439 | |
|
440 | |
|
441 | |
|
442 | |
|
443 | |
|
444 | |
|
445 | |
|
446 | |
|
447 | |
|
448 | |
|
449 | |
|
450 | |
|
451 | |
|
452 | |
|
453 | |
|
454 | |
|
455 | |
|
456 | |
|
457 | |
|
458 | |
|
459 | |
|
460 | |
|
461 | |
|
462 | |
|
463 | |
|
464 | |
|
465 | |
|
466 | |
|
467 | |
|
468 | |
|
469 | |
|
470 | |
|
471 | |
|
472 | |
|
473 | |
|
474 | |
|
475 | |
|
476 | |
|
477 | |
|
478 | |
|
479 | |
|
480 | |
|
481 | |
|
482 | |
|
483 | |
|
484 | |
|
485 | |
|
486 | |
|
487 | |
|
488 | |
|
489 | |
|
490 | |
|
491 | |
|
492 | |
|
493 | |
|
494 | |
|
495 | |
|
496 | |
|
497 | |
|
498 | |
|
499 | |
|
500 | |
|
501 | |
|
502 | |
@Override |
503 | |
public void visitTopLevel(JCCompilationUnit tree) { |
504 | 340 | for (JCTree def : tree.defs) { |
505 | 733 | if (def instanceof JFXClassDeclaration) { |
506 | 340 | JFXClassDeclaration cdecl = (JFXClassDeclaration) def; |
507 | 340 | JFXFunctionDefinition runMethod = cdecl.runMethod; |
508 | 340 | if (runMethod != null) { |
509 | 340 | fixupBlockExpression(runMethod.getBodyExpression(), cdecl); |
510 | |
} |
511 | 733 | } |
512 | |
} |
513 | |
|
514 | 340 | fillClassesWithOuters(tree); |
515 | |
|
516 | 340 | ListBuffer<JCTree> translatedDefinitions= ListBuffer.lb(); |
517 | 340 | ListBuffer<JCTree> imports= ListBuffer.lb(); |
518 | 340 | additionalImports = ListBuffer.lb(); |
519 | 340 | prependToStatements = prependToDefinitions = ListBuffer.lb(); |
520 | 340 | for (JCTree def : tree.defs) { |
521 | 733 | if (def.getTag() == JCTree.IMPORT) { |
522 | 393 | imports.append(def); |
523 | 393 | if (!((JCImport)def).isStatic()) { |
524 | 393 | if (((JCImport)def).getQualifiedIdentifier().getTag() == JCTree.SELECT) { |
525 | 393 | JCFieldAccess select = (JCFieldAccess)((JCImport)def).getQualifiedIdentifier(); |
526 | 393 | if (select.name != names.asterisk && |
527 | |
types.isCompoundClass(select.sym)) { |
528 | 18 | imports.append(make.Import(make.Select( |
529 | |
translate( select.selected ), |
530 | |
names.fromString(select.name.toString() + interfaceSuffix)), |
531 | |
false)); |
532 | |
} |
533 | 393 | } else if (((JCImport)def).getQualifiedIdentifier().getTag() == JCTree.IDENT) { |
534 | 0 | JCIdent ident = (JCIdent)((JCImport)def).getQualifiedIdentifier(); |
535 | 0 | if (ident.name != names.asterisk && |
536 | |
types.isCompoundClass(ident.sym)) { |
537 | 0 | imports.append(make.Import(make.Ident(names.fromString(ident.name.toString() + interfaceSuffix)), false)); |
538 | |
} |
539 | 0 | } |
540 | |
} |
541 | |
} else { |
542 | |
|
543 | 340 | translatedDefinitions.append( translate(def) ); |
544 | |
} |
545 | |
} |
546 | |
|
547 | |
|
548 | 340 | for (JCTree prepend : prependToDefinitions) { |
549 | 334 | translatedDefinitions.prepend(prepend); |
550 | |
} |
551 | |
|
552 | 340 | for (JCTree prepend : imports) { |
553 | 411 | translatedDefinitions.prepend(prepend); |
554 | |
} |
555 | |
|
556 | 340 | for (JCExpression prepend : additionalImports) { |
557 | 10 | translatedDefinitions.append(make.Import(prepend, false)); |
558 | |
} |
559 | |
|
560 | 340 | prependToStatements = prependToDefinitions = null; |
561 | |
|
562 | 340 | JCExpression pid = tree.pid; |
563 | 340 | JCCompilationUnit translated = make.at(tree.pos).TopLevel(List.<JCAnnotation>nil(), pid, translatedDefinitions.toList()); |
564 | 340 | translated.sourcefile = tree.sourcefile; |
565 | 340 | translated.docComments = tree.docComments; |
566 | 340 | translated.lineMap = tree.lineMap; |
567 | 340 | translated.flags = tree.flags; |
568 | 340 | result = translated; |
569 | 340 | } |
570 | |
|
571 | |
@Override |
572 | |
public void visitClassDeclaration(JFXClassDeclaration tree) { |
573 | 612 | JFXClassDeclaration prevClass = currentClass; |
574 | 612 | JFXClassDeclaration prevEnclClass = attrEnv.enclClass; |
575 | 612 | Wrapped prevWrap = wrap; |
576 | 612 | wrap = Wrapped.InNothing; |
577 | 612 | currentClass = tree; |
578 | |
|
579 | |
try { |
580 | 612 | DiagnosticPosition diagPos = tree.pos(); |
581 | |
|
582 | 612 | attrEnv.enclClass = tree; |
583 | |
|
584 | 612 | ListBuffer<JCStatement> translatedInitBlocks = ListBuffer.lb(); |
585 | 612 | ListBuffer<JCStatement> translatedPostInitBlocks = ListBuffer.lb(); |
586 | 612 | ListBuffer<JCTree> translatedDefs = ListBuffer.lb(); |
587 | 612 | ListBuffer<TranslatedAttributeInfo> attrInfo = ListBuffer.lb(); |
588 | 612 | ListBuffer<TranslatedOverrideAttributeInfo> overrideInfo = ListBuffer.lb(); |
589 | |
|
590 | |
|
591 | |
|
592 | 612 | ListBuffer<JCStatement> prevPrependToDefinitions = prependToDefinitions; |
593 | 612 | ListBuffer<JCStatement> prevPrependToStatements = prependToStatements; |
594 | 612 | prependToStatements = prependToDefinitions = ListBuffer.lb(); |
595 | |
{ |
596 | 612 | for (JCTree def : tree.getMembers()) { |
597 | 1859 | switch(def.getTag()) { |
598 | |
case JavafxTag.INIT_DEF: { |
599 | 30 | translatedInitBlocks.append(translate((JCBlock) ((JFXInitDefinition) def).getBody())); |
600 | 30 | break; |
601 | |
} |
602 | |
case JavafxTag.POSTINIT_DEF: { |
603 | 10 | translatedPostInitBlocks.append(translate((JCBlock) ((JFXPostInitDefinition) def).getBody())); |
604 | 10 | break; |
605 | |
} |
606 | |
case JavafxTag.VAR_DEF: { |
607 | 556 | JFXVar attrDef = (JFXVar) def; |
608 | 556 | boolean isStatic = (attrDef.getModifiers().flags & STATIC) != 0; |
609 | 556 | JCStatement init = attrDef.getInitializer()==doNotInitializeMarker? null : |
610 | |
translateDefinitionalAssignmentToSet(attrDef.pos(), |
611 | |
attrDef.getInitializer(), attrDef.getBindStatus(), attrDef.sym, |
612 | |
isStatic? null : make.Ident(defs.receiverName), FROM_DEFAULT_MILIEU); |
613 | 556 | attrInfo.append(new TranslatedAttributeInfo( |
614 | |
attrDef, |
615 | |
typeMorpher.varMorphInfo(attrDef.sym), |
616 | |
init, |
617 | |
translate(attrDef.getOnReplace()))); |
618 | |
|
619 | 556 | break; |
620 | |
} |
621 | |
case JavafxTag.OVERRIDE_ATTRIBUTE_DEF: { |
622 | 9 | JFXOverrideAttribute override = (JFXOverrideAttribute) def; |
623 | 9 | boolean isStatic = (override.sym.flags() & STATIC) != 0; |
624 | |
JCStatement init; |
625 | 9 | if (override.getInitializer() == null) { |
626 | 0 | init = null; |
627 | |
} else { |
628 | 9 | init = translateDefinitionalAssignmentToSet(override.pos(), |
629 | |
override.getInitializer(), override.getBindStatus(), override.sym, |
630 | |
isStatic? null : make.Ident(defs.receiverName), |
631 | |
FROM_DEFAULT_MILIEU); |
632 | |
} |
633 | 9 | overrideInfo.append(new TranslatedOverrideAttributeInfo( |
634 | |
override, |
635 | |
typeMorpher.varMorphInfo(override.sym), |
636 | |
init, |
637 | |
translate(override.getOnReplace()))); |
638 | 9 | break; |
639 | |
} |
640 | |
case JavafxTag.FUNCTION_DEF : { |
641 | 1008 | JFXFunctionDefinition funcDef = (JFXFunctionDefinition) def; |
642 | 1008 | translatedDefs.append(translate(funcDef)); |
643 | 1008 | break; |
644 | |
} |
645 | |
case JCTree.METHODDEF : { |
646 | 0 | assert false : "translated method should never appear in an FX class"; |
647 | |
break; |
648 | |
} |
649 | |
default: { |
650 | 246 | JCTree tdef = translate(def); |
651 | 246 | if ( tdef != null ) { |
652 | 246 | translatedDefs.append( tdef ); |
653 | |
} |
654 | |
break; |
655 | |
} |
656 | |
} |
657 | |
} |
658 | |
} |
659 | |
|
660 | 612 | for (JCTree prepend : prependToDefinitions) { |
661 | 237 | translatedDefs.prepend(prepend); |
662 | |
} |
663 | 612 | prependToDefinitions = prevPrependToDefinitions ; |
664 | 612 | prependToStatements = prevPrependToStatements; |
665 | |
|
666 | |
|
667 | 612 | boolean classOnly = tree.generateClassOnly(); |
668 | 612 | JavafxClassModel model = initBuilder.createJFXClassModel(tree, attrInfo.toList(), overrideInfo.toList()); |
669 | 612 | additionalImports.appendList(model.additionalImports); |
670 | |
|
671 | 612 | boolean classIsFinal = (tree.getModifiers().flags & Flags.FINAL) != 0; |
672 | |
|
673 | |
|
674 | 612 | if (!tree.hasBeenTranslated) { |
675 | 612 | if (! classOnly) { |
676 | 571 | JCModifiers mods = make.Modifiers(Flags.PUBLIC | Flags.INTERFACE); |
677 | 571 | mods = addAccessAnnotationModifiers(diagPos, tree.mods.flags, mods); |
678 | |
|
679 | 571 | JCClassDecl cInterface = make.ClassDef(mods, |
680 | |
model.interfaceName, List.<JCTypeParameter>nil(), null, |
681 | |
model.interfaces, model.iDefinitions); |
682 | |
|
683 | 571 | prependToDefinitions.append(cInterface); |
684 | |
} |
685 | 612 | tree.hasBeenTranslated = true; |
686 | |
} |
687 | |
|
688 | 612 | translatedDefs.appendList(model.additionalClassMembers); |
689 | |
|
690 | |
{ |
691 | |
|
692 | 612 | List<JCVariableDecl> receiverVarDeclList = List.of(makeReceiverParam(tree)); |
693 | 612 | ListBuffer<JCStatement> initStats = ListBuffer.lb(); |
694 | |
|
695 | 612 | Set<String> dupSet = new HashSet<String>(); |
696 | 612 | for (JCExpression parent : tree.getExtending()) { |
697 | 106 | if (! (parent instanceof JCIdent)) |
698 | 10 | continue; |
699 | 96 | Symbol symbol = expressionSymbol(parent); |
700 | 96 | if (types.isJFXClass(symbol)) { |
701 | 89 | ClassSymbol cSym = (ClassSymbol) symbol; |
702 | 89 | String className = cSym.fullname.toString(); |
703 | 89 | if (className.endsWith(interfaceSuffix)) { |
704 | 0 | className = className.substring(0, className.length() - interfaceSuffix.length()); |
705 | |
} |
706 | |
|
707 | 89 | if (!dupSet.contains(className)) { |
708 | 89 | dupSet.add(className); |
709 | 89 | List<JCExpression> args1 = List.nil(); |
710 | 89 | args1 = args1.append(make.TypeCast(makeTypeTree( diagPos,cSym.type, true), make.Ident(defs.receiverName))); |
711 | 89 | initStats = initStats.append(callStatement(tree.pos(), makeIdentifier(diagPos, className), initBuilder.userInitName, args1)); |
712 | |
} |
713 | |
} |
714 | 96 | } |
715 | 612 | initStats.appendList(translatedInitBlocks); |
716 | |
|
717 | 612 | JCBlock userInitBlock = make.Block(0L, initStats.toList()); |
718 | 612 | translatedDefs.append(make.MethodDef( |
719 | |
make.Modifiers(classIsFinal? Flags.PUBLIC : Flags.PUBLIC | Flags.STATIC), |
720 | |
initBuilder.userInitName, |
721 | |
makeTypeTree( null,syms.voidType), |
722 | |
List.<JCTypeParameter>nil(), |
723 | |
receiverVarDeclList, |
724 | |
List.<JCExpression>nil(), |
725 | |
userInitBlock, |
726 | |
null)); |
727 | |
} |
728 | |
{ |
729 | |
|
730 | 612 | List<JCVariableDecl> receiverVarDeclList = List.of(makeReceiverParam(tree)); |
731 | 612 | ListBuffer<JCStatement> initStats = ListBuffer.lb(); |
732 | |
|
733 | 612 | Set<String> dupSet = new HashSet<String>(); |
734 | 612 | for (JCExpression parent : tree.getExtending()) { |
735 | 106 | if (! (parent instanceof JCIdent)) |
736 | 10 | continue; |
737 | 96 | Symbol symbol = expressionSymbol(parent); |
738 | 96 | if (types.isJFXClass(symbol)) { |
739 | 89 | ClassSymbol cSym = (ClassSymbol) symbol; |
740 | 89 | String className = cSym.fullname.toString(); |
741 | 89 | if (className.endsWith(interfaceSuffix)) { |
742 | 0 | className = className.substring(0, className.length() - interfaceSuffix.length()); |
743 | |
} |
744 | |
|
745 | 89 | if (!dupSet.contains(className)) { |
746 | 89 | dupSet.add(className); |
747 | 89 | List<JCExpression> args1 = List.nil(); |
748 | 89 | args1 = args1.append(make.TypeCast(makeTypeTree( diagPos,cSym.type, true), make.Ident(defs.receiverName))); |
749 | 89 | initStats = initStats.append(callStatement(tree.pos(), makeIdentifier(diagPos, className), initBuilder.postInitName, args1)); |
750 | |
} |
751 | |
} |
752 | 96 | } |
753 | 612 | initStats.appendList(translatedPostInitBlocks); |
754 | |
|
755 | 612 | JCBlock postInitBlock = make.Block(0L, initStats.toList()); |
756 | 612 | translatedDefs.append(make.MethodDef( |
757 | |
make.Modifiers(classIsFinal? Flags.PUBLIC : Flags.PUBLIC | Flags.STATIC), |
758 | |
initBuilder.postInitName, |
759 | |
makeTypeTree( null,syms.voidType), |
760 | |
List.<JCTypeParameter>nil(), |
761 | |
receiverVarDeclList, |
762 | |
List.<JCExpression>nil(), |
763 | |
postInitBlock, |
764 | |
null)); |
765 | |
} |
766 | |
|
767 | 612 | if (tree.isModuleClass) { |
768 | |
|
769 | 340 | translatedDefs.append(makeMainMethod(diagPos, tree.getName())); |
770 | |
} |
771 | |
|
772 | |
|
773 | |
List<JCExpression> implementing; |
774 | 612 | if (classOnly) { |
775 | 41 | implementing = model.interfaces; |
776 | |
} |
777 | |
else { |
778 | 571 | implementing = List.of(make.Ident(model.interfaceName), makeIdentifier(diagPos, fxObjectString)); |
779 | |
} |
780 | |
|
781 | 612 | long flags = tree.mods.flags & (Flags.PUBLIC | Flags.PRIVATE | Flags.PROTECTED | Flags.FINAL | Flags.ABSTRACT); |
782 | 612 | if (tree.sym.owner.kind == Kinds.TYP) { |
783 | 246 | flags |= Flags.STATIC; |
784 | |
} |
785 | |
|
786 | |
|
787 | 612 | JCClassDecl res = make.at(diagPos).ClassDef( |
788 | |
make.at(diagPos).Modifiers(flags), |
789 | |
tree.getName(), |
790 | |
tree.getEmptyTypeParameters(), |
791 | |
model.superType==null? null : makeTypeTree( null,model.superType, false), |
792 | |
implementing, |
793 | |
translatedDefs.toList()); |
794 | 612 | res.sym = tree.sym; |
795 | 612 | res.type = tree.type; |
796 | 612 | result = res; |
797 | |
} |
798 | |
finally { |
799 | 612 | attrEnv.enclClass = prevEnclClass; |
800 | 612 | wrap = prevWrap; |
801 | |
|
802 | 612 | currentClass = prevClass; |
803 | 612 | } |
804 | 612 | } |
805 | |
|
806 | |
@Override |
807 | |
public void visitInitDefinition(JFXInitDefinition tree) { |
808 | 0 | assert false : "should be processed by class tree"; |
809 | 0 | } |
810 | |
|
811 | |
public void visitPostInitDefinition(JFXPostInitDefinition tree) { |
812 | 0 | assert false : "should be processed by class tree"; |
813 | 0 | } |
814 | |
|
815 | 2 | abstract static class InstanciateTranslator extends Translator { |
816 | |
|
817 | |
protected final JFXInstanciate tree; |
818 | 659 | protected ListBuffer<JCStatement> stats = ListBuffer.lb(); |
819 | |
|
820 | |
InstanciateTranslator(final JFXInstanciate tree, JavafxToJava toJava) { |
821 | 659 | super(tree.pos(), toJava); |
822 | 659 | this.tree = tree; |
823 | 659 | } |
824 | |
|
825 | |
abstract protected void processLocalVar(JFXVar var); |
826 | |
|
827 | |
protected List<JCExpression> translatedConstructorArgs() { |
828 | 595 | if (tree.constructor != null && tree.constructor.type != null) { |
829 | 100 | List<Type> ptypes = tree.constructor.type.asMethodType().getParameterTypes(); |
830 | 100 | return toJava.translate(tree.getArgs(), ptypes); |
831 | |
} else { |
832 | 495 | return toJava.translate(tree.getArgs()); |
833 | |
} |
834 | |
} |
835 | |
|
836 | |
abstract protected JCStatement translateAttributeSet(JCExpression init, JavafxBindStatus bindStatus, VarSymbol vsym, |
837 | |
JCExpression instance); |
838 | |
|
839 | |
protected JCExpression doit() { |
840 | |
Type type; |
841 | |
|
842 | 659 | for (JFXVar var : tree.getLocalvars()) { |
843 | |
|
844 | 8 | toJava.typeMorpher.varMorphInfo(var.sym).markBoundTo(); |
845 | |
|
846 | 8 | processLocalVar(var); |
847 | |
} |
848 | 659 | if (tree.getClassBody() == null) { |
849 | 633 | type = tree.type; |
850 | |
} else { |
851 | 26 | JFXClassDeclaration cdef = tree.getClassBody(); |
852 | 26 | stats.append(toJava.translate(cdef)); |
853 | 26 | type = cdef.type; |
854 | |
} |
855 | 659 | JCExpression classTypeExpr = toJava.makeTypeTree(tree, type, false); |
856 | 659 | Symbol sym = TreeInfo.symbol(tree.getIdentifier()); |
857 | |
|
858 | 659 | List<JCExpression> newClassArgs = translatedConstructorArgs(); |
859 | 659 | if (tree.getClassBody() != null || types.isJFXClass(sym)) { |
860 | 581 | assert newClassArgs.size() == 0 : "should not be args for JavaFX class constructors"; |
861 | 581 | newClassArgs = newClassArgs.append(m().Literal(TypeTags.BOOLEAN, 1)); |
862 | |
} |
863 | 659 | if (tree.getClassBody() != null && |
864 | |
tree.getClassBody().sym != null && toJava.hasOuters.contains(tree.getClassBody().sym)) { |
865 | 8 | JCIdent thisIdent = m().Ident(defs.receiverName); |
866 | 8 | thisIdent.sym = tree.getClassBody().sym.owner; |
867 | 8 | thisIdent.type = tree.getClassBody().sym.owner.type; |
868 | |
|
869 | 8 | newClassArgs = newClassArgs.prepend(thisIdent); |
870 | |
} |
871 | |
|
872 | 659 | JCNewClass newClass = |
873 | |
m().NewClass(null, null, classTypeExpr, |
874 | |
newClassArgs, |
875 | |
null); |
876 | |
|
877 | |
JCExpression instExpression; |
878 | |
{ |
879 | 659 | if (sym != null && |
880 | |
sym.kind == Kinds.TYP && (sym instanceof ClassSymbol) && |
881 | |
(types.isJFXClass((ClassSymbol) sym) || |
882 | |
tree.getClassBody() != null)) { |
883 | |
|
884 | 581 | JCVariableDecl tmpVar = toJava.makeTmpVar(diagPos, "objlit", type, newClass); |
885 | 581 | stats.append(tmpVar); |
886 | 581 | for (JFXObjectLiteralPart olpart : tree.getParts()) { |
887 | 765 | diagPos = olpart.pos(); |
888 | 765 | JavafxBindStatus bindStatus = olpart.getBindStatus(); |
889 | 765 | JCExpression init = olpart.getExpression(); |
890 | 765 | VarSymbol vsym = (VarSymbol) olpart.sym; |
891 | 765 | VarMorphInfo vmi = toJava.typeMorpher.varMorphInfo(vsym); |
892 | 765 | assert toJava.shouldMorph(vmi); |
893 | |
|
894 | |
|
895 | 765 | if (types.isSequence(olpart.type)) { |
896 | 96 | JCExpression olexpr = olpart.getExpression(); |
897 | 96 | if (!types.isSequence(olexpr.type)) { |
898 | 13 | init = ((JavafxTreeMaker) m()).ExplicitSequence(List.<JCExpression>of(olexpr)); |
899 | 13 | WildcardType tpType = new WildcardType(olexpr.type, BoundKind.EXTENDS, olexpr.type.tsym); |
900 | 13 | init.type = new ClassType(((JavafxSymtab) syms).javafx_SequenceType, List.<Type>of(tpType), ((JavafxSymtab) syms).javafx_SequenceType.tsym); |
901 | |
} |
902 | |
} |
903 | |
|
904 | 765 | JCIdent ident1 = m().Ident(tmpVar.name); |
905 | 765 | stats.append( translateAttributeSet(init, bindStatus, vsym, ident1) ); |
906 | 765 | } |
907 | 581 | diagPos = tree.pos(); |
908 | 581 | JCIdent ident3 = m().Ident(tmpVar.name); |
909 | 581 | JCStatement applyExec = toJava.callStatement(diagPos, ident3, defs.initializeName); |
910 | 581 | stats.append(applyExec); |
911 | |
|
912 | 581 | JCIdent ident2 = m().Ident(tmpVar.name); |
913 | 581 | instExpression = toJava.makeBlockExpression(diagPos, stats, ident2); |
914 | 581 | } else { |
915 | |
|
916 | 78 | instExpression = newClass; |
917 | |
} |
918 | |
} |
919 | 659 | if (toJava.wrap == Wrapped.InLocation) { |
920 | 1 | instExpression = toJava.makeConstantLocation(diagPos, tree.type, instExpression); |
921 | |
} |
922 | 659 | return instExpression; |
923 | |
} |
924 | |
} |
925 | |
|
926 | |
@Override |
927 | |
public void visitInstanciate(JFXInstanciate tree) { |
928 | |
|
929 | 590 | ListBuffer<JCStatement> prevPrependToStatements = prependToStatements; |
930 | 590 | prependToStatements = ListBuffer.lb(); |
931 | |
|
932 | 590 | result = new InstanciateTranslator(tree, this) { |
933 | |
|
934 | |
protected void processLocalVar(JFXVar var) { |
935 | 7 | stats.append(translate(var)); |
936 | 7 | } |
937 | |
|
938 | |
protected JCStatement translateAttributeSet(JCExpression init, JavafxBindStatus bindStatus, VarSymbol vsym, JCExpression instance) { |
939 | 660 | return toJava.translateDefinitionalAssignmentToSet(diagPos, init, bindStatus, |
940 | |
vsym, instance, FROM_LITERAL_MILIEU); |
941 | |
} |
942 | |
}.doit(); |
943 | |
|
944 | 590 | if (result instanceof JFXBlockExpression) { |
945 | 512 | JFXBlockExpression blockExpr = (JFXBlockExpression)result; |
946 | 512 | blockExpr.stats = blockExpr.getStatements().prependList(prependToStatements.toList()); |
947 | |
} |
948 | 590 | prependToStatements = prevPrependToStatements; |
949 | 590 | } |
950 | |
|
951 | 0 | abstract static class StringExpressionTranslator extends Translator { |
952 | |
|
953 | |
private final JFXStringExpression tree; |
954 | |
StringExpressionTranslator(JFXStringExpression tree, JavafxToJava toJava) { |
955 | 730 | super(tree.pos(), toJava); |
956 | 730 | this.tree = tree; |
957 | 730 | } |
958 | |
|
959 | |
protected JCExpression doit() { |
960 | 730 | StringBuffer sb = new StringBuffer(); |
961 | 730 | List<JCExpression> parts = tree.getParts(); |
962 | 730 | ListBuffer<JCExpression> values = new ListBuffer<JCExpression>(); |
963 | |
|
964 | 730 | JCLiteral lit = (JCLiteral) (parts.head); |
965 | 730 | sb.append((String) lit.value); |
966 | 730 | parts = parts.tail; |
967 | 730 | boolean containsExtendedFormat = false; |
968 | |
|
969 | 1883 | while (parts.nonEmpty()) { |
970 | 1153 | lit = (JCLiteral) (parts.head); |
971 | 1153 | String format = (String) lit.value; |
972 | 1153 | if ((!containsExtendedFormat) && format.length() > 0 |
973 | |
&& EXTENDED_FORMAT_PATTERN.matcher(format).find()) { |
974 | 8 | containsExtendedFormat = true; |
975 | |
} |
976 | 1153 | parts = parts.tail; |
977 | 1153 | JCExpression exp = parts.head; |
978 | 1153 | if (exp != null && |
979 | |
types.isSameType(exp.type, syms.javafx_DurationType)) { |
980 | 16 | exp = m().Apply(null, |
981 | |
m().Select(translateArg(exp), |
982 | |
Name.fromString(toJava.names, "toDate")), |
983 | |
List.<JCExpression>nil()); |
984 | 16 | sb.append(format.length() == 0 ? "%tQms" : format); |
985 | |
} else { |
986 | 1137 | exp = translateArg(exp); |
987 | 1137 | sb.append(format.length() == 0 ? "%s" : format); |
988 | |
} |
989 | 1153 | values.append(exp); |
990 | 1153 | parts = parts.tail; |
991 | |
|
992 | 1153 | lit = (JCLiteral) (parts.head); |
993 | 1153 | String part = (String)lit.value; |
994 | 1153 | sb.append(part.replace("%", "%%")); |
995 | 1153 | parts = parts.tail; |
996 | 1153 | } |
997 | 730 | JCLiteral formatLiteral = m().Literal(TypeTags.CLASS, sb.toString()); |
998 | 730 | values.prepend(formatLiteral); |
999 | |
String formatMethod; |
1000 | 730 | if (tree.translationKey != null) { |
1001 | 28 | formatMethod = "com.sun.javafx.runtime.util.StringLocalization.getLocalizedString"; |
1002 | 28 | if (tree.translationKey.length() == 0) { |
1003 | 24 | values.prepend(m().Literal(TypeTags.BOT, null)); |
1004 | |
} else { |
1005 | 4 | values.prepend(m().Literal(TypeTags.CLASS, tree.translationKey)); |
1006 | |
} |
1007 | 28 | String resourceName = |
1008 | |
toJava.attrEnv.enclClass.sym.flatname.toString().replace('.', '/').replaceAll("\\$.*", ""); |
1009 | 28 | values.prepend(m().Literal(TypeTags.CLASS, resourceName)); |
1010 | 28 | } else if (containsExtendedFormat) { |
1011 | 8 | formatMethod = "com.sun.javafx.runtime.util.FXFormatter.sprintf"; |
1012 | |
} else { |
1013 | 694 | formatMethod = "java.lang.String.format"; |
1014 | |
} |
1015 | 730 | JCExpression formatter = toJava.makeQualifiedTree(diagPos, formatMethod); |
1016 | 730 | return m().Apply(null, formatter, values.toList()); |
1017 | |
} |
1018 | |
|
1019 | |
abstract protected JCExpression translateArg(JCExpression arg); |
1020 | |
|
1021 | |
} |
1022 | |
|
1023 | |
@Override |
1024 | |
public void visitStringExpression(JFXStringExpression tree) { |
1025 | 716 | result = new StringExpressionTranslator(tree, this) { |
1026 | |
protected JCExpression translateArg(JCExpression arg) { |
1027 | 1125 | return translate(arg); |
1028 | |
} |
1029 | |
}.doit(); |
1030 | 716 | } |
1031 | |
|
1032 | |
private List<JCExpression> translateDefinitionalAssignmentToArgs(DiagnosticPosition diagPos, |
1033 | |
JCExpression init, JavafxBindStatus bindStatus, VarMorphInfo vmi) { |
1034 | 2392 | if (bindStatus.isUnidiBind()) { |
1035 | 251 | return List.of(toBound.translate(init, vmi.getRealType())); |
1036 | 2141 | } else if (bindStatus.isBidiBind()) { |
1037 | 19 | assert (shouldMorph(vmi)); |
1038 | |
|
1039 | 19 | return List.<JCExpression>of( translate(init, Wrapped.InLocation) ); |
1040 | |
} else { |
1041 | |
JCExpression initExpr; |
1042 | |
|
1043 | 2122 | if (init == null) { |
1044 | |
|
1045 | 312 | initExpr = makeDefaultValue(diagPos, vmi); |
1046 | |
} else { |
1047 | |
|
1048 | 1810 | initExpr = translate(init, vmi.getSymbol().type); |
1049 | |
} |
1050 | 2122 | return List.<JCExpression>of( initExpr ); |
1051 | |
} |
1052 | |
} |
1053 | |
|
1054 | |
private JCExpression translateDefinitionalAssignmentToValue(DiagnosticPosition diagPos, |
1055 | |
JCExpression init, JavafxBindStatus bindStatus, VarSymbol vsym) { |
1056 | 1 | VarMorphInfo vmi = typeMorpher.varMorphInfo(vsym); |
1057 | 1 | List<JCExpression> args = translateDefinitionalAssignmentToArgs(diagPos, init, bindStatus, vmi); |
1058 | 1 | if (bindStatus.isUnidiBind()) { |
1059 | 0 | return args.head; |
1060 | 1 | } else if (shouldMorph(vmi)) { |
1061 | 0 | Name makeName = defs.makeMethodName; |
1062 | 0 | if (bindStatus.isBidiBind()) { |
1063 | 0 | makeName = defs.makeBijectiveMethodName; |
1064 | |
} |
1065 | 0 | return makeLocationVariable(vmi, diagPos, args, makeName); |
1066 | |
} else { |
1067 | 1 | return args.head; |
1068 | |
} |
1069 | |
} |
1070 | |
|
1071 | |
private JCStatement translateDefinitionalAssignmentToSet(DiagnosticPosition diagPos, |
1072 | |
JCExpression init, JavafxBindStatus bindStatus, VarSymbol vsym, |
1073 | |
JCExpression instance, int milieu) { |
1074 | 2387 | return make.at(diagPos).Exec( translateDefinitionalAssignmentToSetExpression(diagPos, |
1075 | |
init, bindStatus, vsym, |
1076 | |
instance, milieu) ); |
1077 | |
} |
1078 | |
|
1079 | |
private JCExpression translateDefinitionalAssignmentToSetExpression(DiagnosticPosition diagPos, |
1080 | |
JCExpression init, JavafxBindStatus bindStatus, VarSymbol vsym, |
1081 | |
JCExpression instance, int milieu) { |
1082 | 2391 | VarMorphInfo vmi = typeMorpher.varMorphInfo(vsym); |
1083 | 2391 | List<JCExpression> args = translateDefinitionalAssignmentToArgs(diagPos, init, bindStatus, vmi); |
1084 | |
JCExpression localAttr; |
1085 | |
|
1086 | |
|
1087 | 2391 | if (vsym.owner.kind == Kinds.TYP) { |
1088 | 1202 | if ((vsym.flags() & STATIC) != 0) { |
1089 | |
|
1090 | 46 | localAttr = make.Ident(vsym); |
1091 | |
} else { |
1092 | 1156 | String attrAccess = attributeGetMethodNamePrefix + vsym; |
1093 | 1156 | localAttr = callExpression(diagPos, instance, attrAccess); |
1094 | 1156 | } |
1095 | |
} else { |
1096 | |
|
1097 | 1189 | assert( (vsym.flags() & Flags.PARAMETER) == 0): "Parameters are not initialized"; |
1098 | 1189 | localAttr = make.at(diagPos).Ident(vsym); |
1099 | |
|
1100 | 1189 | if (!shouldMorph(vmi)) { |
1101 | 709 | return make.at(diagPos).Assign(localAttr, args.head); |
1102 | |
} |
1103 | |
} |
1104 | |
|
1105 | |
Name methName; |
1106 | 1682 | if (bindStatus.isUnidiBind()) { |
1107 | 251 | methName = defs.locationBindMilieuMethodName[milieu]; |
1108 | 1431 | } else if (bindStatus.isBidiBind()) { |
1109 | 19 | methName = defs.locationBijectiveBindMilieuMethodName[milieu]; |
1110 | |
} else { |
1111 | 1412 | methName = defs.locationSetMilieuMethodName[vmi.getTypeKind()][milieu]; |
1112 | |
} |
1113 | 1682 | return callExpression(diagPos, localAttr, methName, args); |
1114 | |
} |
1115 | |
|
1116 | |
@Override |
1117 | |
public void visitVar(JFXVar tree) { |
1118 | 2274 | DiagnosticPosition diagPos = tree.pos(); |
1119 | 2274 | Type type = tree.type; |
1120 | 2274 | JCModifiers mods = tree.getModifiers(); |
1121 | 2274 | long modFlags = mods.flags & ~Flags.FINAL; |
1122 | 2274 | VarSymbol vsym = tree.sym; |
1123 | 2274 | VarMorphInfo vmi = typeMorpher.varMorphInfo(vsym); |
1124 | 2274 | assert vsym.owner.kind != Kinds.TYP : "attributes are processed in the class and should never come here"; |
1125 | |
|
1126 | |
|
1127 | 2274 | if ((vsym.flags_field & JavafxFlags.INNER_ACCESS) != 0) { |
1128 | 9 | modFlags |= Flags.FINAL; |
1129 | |
} |
1130 | |
|
1131 | |
|
1132 | 2274 | if (tree.getOnReplace() != null) |
1133 | 7 | vmi.markBoundTo(); |
1134 | |
|
1135 | 2274 | if (shouldMorph(vmi)) { |
1136 | |
|
1137 | 488 | if ((vsym.flags() & Flags.PARAMETER) != 0) { |
1138 | 8 | type = vmi.getLocationType(); |
1139 | |
} else { |
1140 | 480 | type = vmi.getVariableType(); |
1141 | |
} |
1142 | |
|
1143 | |
|
1144 | 488 | modFlags |= Flags.FINAL; |
1145 | |
} |
1146 | |
|
1147 | 2274 | mods = make.at(diagPos).Modifiers(modFlags); |
1148 | 2274 | JCExpression typeExpression = makeTypeTree(diagPos, type, true); |
1149 | |
|
1150 | |
|
1151 | |
|
1152 | |
JCExpression init; |
1153 | 2274 | if ((vsym.flags() & Flags.PARAMETER) != 0) { |
1154 | |
|
1155 | 1084 | init = null; |
1156 | 1084 | result = make.at(diagPos).VarDef(mods, tree.name, typeExpression, init); |
1157 | |
} else { |
1158 | |
|
1159 | 1190 | if ( !shouldMorph(vmi)) { |
1160 | 710 | if ( (modFlags & Flags.FINAL) != 0 ) { |
1161 | 1 | init = translateDefinitionalAssignmentToValue(tree.pos(), tree.init, |
1162 | |
tree.getBindStatus(), tree.sym); |
1163 | 1 | result = make.at(diagPos).VarDef(mods, tree.name, typeExpression, init); |
1164 | 1 | return; |
1165 | |
} |
1166 | |
|
1167 | 709 | init = makeDefaultValue(diagPos, vmi); |
1168 | |
} else { |
1169 | |
|
1170 | 480 | init = makeLocationAttributeVariable(vmi, diagPos); |
1171 | |
} |
1172 | 1189 | prependToStatements.append(make.at(diagPos).VarDef(mods, tree.name, typeExpression, init)); |
1173 | |
|
1174 | |
|
1175 | 1189 | JFXOnReplace onReplace = tree.getOnReplace(); |
1176 | 1189 | if ( onReplace != null ) { |
1177 | |
|
1178 | 7 | TranslatedAttributeInfo attrInfo = new TranslatedAttributeInfo( |
1179 | |
tree, |
1180 | |
typeMorpher.varMorphInfo(vsym), |
1181 | |
null, |
1182 | |
translate(tree.getOnReplace())); |
1183 | 7 | JCStatement changeListener = initBuilder.makeChangeListenerCall(attrInfo); |
1184 | 7 | prependToStatements.append(changeListener); |
1185 | |
} |
1186 | |
|
1187 | 1189 | result = translateDefinitionalAssignmentToSet(diagPos, tree.init, tree.getBindStatus(), tree.sym, null, 0); |
1188 | |
} |
1189 | 2273 | } |
1190 | |
|
1191 | |
@Override |
1192 | |
public void visitOverrideAttribute(JFXOverrideAttribute tree) { |
1193 | 0 | assert false : "should be processed by parent tree"; |
1194 | 0 | } |
1195 | |
|
1196 | |
@Override |
1197 | |
public void visitOnReplace(JFXOnReplace tree) { |
1198 | 126 | result = ((JavafxTreeMaker) make).OnReplace( |
1199 | |
tree.getOldValue(), tree.getFirstIndex(), tree.getLastIndex(), |
1200 | |
tree.getEndKind(), tree.getNewElements(), |
1201 | |
translate(tree.getBody())); |
1202 | 126 | } |
1203 | |
|
1204 | |
|
1205 | |
@Override |
1206 | |
public void visitFunctionValue(JFXFunctionValue tree) { |
1207 | 173 | JFXFunctionDefinition def = tree.definition; |
1208 | 173 | result = makeFunctionValue(make.Ident(defs.lambdaName), def, tree.pos(), (MethodType) def.type); |
1209 | 173 | } |
1210 | |
|
1211 | |
JCExpression makeFunctionValue (JCExpression meth, JFXFunctionDefinition def, DiagnosticPosition diagPos, MethodType mtype) { |
1212 | 182 | ListBuffer<JCTree> members = new ListBuffer<JCTree>(); |
1213 | 182 | if (def != null) |
1214 | 173 | members.append(translate(def)); |
1215 | 182 | JCExpression encl = null; |
1216 | 182 | List<JCExpression> args = List.nil(); |
1217 | 182 | int nargs = mtype.argtypes.size(); |
1218 | 182 | Type ftype = syms.javafx_FunctionTypes[nargs]; |
1219 | 182 | JCExpression t = makeQualifiedTree(null, ftype.tsym.getQualifiedName().toString()); |
1220 | 182 | ListBuffer<JCExpression> typeargs = new ListBuffer<JCExpression>(); |
1221 | 182 | Type rtype = syms.boxIfNeeded(mtype.restype); |
1222 | 182 | typeargs.append(makeTypeTree(diagPos, rtype)); |
1223 | 182 | ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>(); |
1224 | 182 | ListBuffer<JCExpression> margs = new ListBuffer<JCExpression>(); |
1225 | 182 | int i = 0; |
1226 | 217 | for (List<Type> l = mtype.argtypes; l.nonEmpty(); l = l.tail) { |
1227 | 35 | Name pname = make.paramName(i++); |
1228 | 35 | Type ptype = syms.boxIfNeeded(l.head); |
1229 | 35 | JCVariableDecl param = make.VarDef(make.Modifiers(0), pname, |
1230 | |
makeTypeTree(diagPos, ptype), null); |
1231 | 35 | params.append(param); |
1232 | 35 | JCExpression marg = make.Ident(pname); |
1233 | 35 | margs.append(marg); |
1234 | 35 | typeargs.append(makeTypeTree(diagPos, ptype)); |
1235 | |
} |
1236 | |
|
1237 | |
|
1238 | 182 | long flags = PUBLIC | BRIDGE; |
1239 | |
|
1240 | 182 | JCExpression call = make.Apply(null, meth, margs.toList()); |
1241 | |
|
1242 | |
List<JCStatement> stats; |
1243 | 182 | if (mtype.restype == syms.voidType) |
1244 | 160 | stats = List.of(make.Exec(call), make.Return(make.Literal(TypeTags.BOT, null))); |
1245 | |
else { |
1246 | 22 | if (mtype.restype.isPrimitive()) |
1247 | 12 | call = makeBox(diagPos, call, mtype.restype); |
1248 | 22 | stats = List.<JCStatement>of(make.Return(call)); |
1249 | |
} |
1250 | 182 | JCMethodDecl bridgeDef = make.at(diagPos).MethodDef( |
1251 | |
make.Modifiers(flags), |
1252 | |
defs.invokeName, |
1253 | |
makeTypeTree(diagPos, rtype), |
1254 | |
List.<JCTypeParameter>nil(), |
1255 | |
params.toList(), |
1256 | |
make.at(diagPos).Types(mtype.getThrownTypes()), |
1257 | |
make.Block(0, stats), |
1258 | |
null); |
1259 | |
|
1260 | 182 | members.append(bridgeDef); |
1261 | 182 | JCClassDecl cl = make.AnonymousClassDef(make.Modifiers(0), members.toList()); |
1262 | 182 | return make.NewClass(encl, args, make.TypeApply(t, typeargs.toList()), args, cl); |
1263 | |
} |
1264 | |
|
1265 | |
boolean isInnerFunction (MethodSymbol sym) { |
1266 | 1181 | return sym.owner != null && sym.owner.kind != Kinds.TYP |
1267 | |
&& (sym.flags() & Flags.SYNTHETIC) == 0; |
1268 | |
} |
1269 | |
|
1270 | |
|
1271 | |
|
1272 | |
|
1273 | |
@Override |
1274 | |
public void visitFunctionDefinition(JFXFunctionDefinition tree) { |
1275 | 1181 | if (isInnerFunction(tree.sym)) { |
1276 | |
|
1277 | |
|
1278 | |
|
1279 | |
|
1280 | |
|
1281 | |
|
1282 | |
|
1283 | |
|
1284 | |
|
1285 | |
|
1286 | 0 | DiagnosticPosition diagPos = tree.pos(); |
1287 | 0 | MethodType mtype = (MethodType) tree.type; |
1288 | 0 | JCExpression typeExpression = makeTypeTree( diagPos,syms.makeFunctionType(mtype), true); |
1289 | 0 | JFXFunctionDefinition def = new JFXFunctionDefinition(make.Modifiers(Flags.SYNTHETIC), tree.name, tree.operation); |
1290 | 0 | def.type = mtype; |
1291 | 0 | def.sym = new MethodSymbol(0, def.name, mtype, tree.sym.owner.owner); |
1292 | 0 | JCExpression init = |
1293 | |
makeFunctionValue(make.Ident(tree.name), def, tree.pos(), mtype); |
1294 | 0 | JCModifiers mods = make.at(diagPos).Modifiers(Flags.FINAL); |
1295 | 0 | result = make.at(diagPos).VarDef(mods, tree.name, typeExpression, init); |
1296 | 0 | return; |
1297 | |
} |
1298 | |
|
1299 | 1181 | boolean isBound = (tree.sym.flags() & JavafxFlags.BOUND) != 0; |
1300 | 1181 | Wrapped prevWrap = wrap; |
1301 | 1181 | wrap = Wrapped.InNothing; |
1302 | |
|
1303 | |
try { |
1304 | 1181 | boolean classOnly = currentClass.generateClassOnly(); |
1305 | |
|
1306 | |
|
1307 | |
|
1308 | 1181 | long flags = tree.mods.flags; |
1309 | 1181 | long originalFlags = flags; |
1310 | 1181 | flags &= ~(Flags.PROTECTED | Flags.PRIVATE); |
1311 | 1181 | flags |= Flags.PUBLIC; |
1312 | 1181 | if (((flags & (Flags.ABSTRACT | Flags.SYNTHETIC)) == 0) && !classOnly) { |
1313 | 582 | flags |= Flags.STATIC; |
1314 | |
} |
1315 | 1181 | flags &= ~Flags.SYNTHETIC; |
1316 | 1181 | JCModifiers mods = make.Modifiers(flags); |
1317 | 1181 | boolean isImplMethod = (originalFlags & (Flags.STATIC | Flags.ABSTRACT | Flags.SYNTHETIC)) == 0 && !classOnly; |
1318 | |
|
1319 | 1181 | DiagnosticPosition diagPos = tree.pos(); |
1320 | 1181 | MethodType mtype = (MethodType)tree.type; |
1321 | |
|
1322 | 1181 | if (isBound) { |
1323 | 15 | locallyBound = new HashSet<VarSymbol>(); |
1324 | 15 | for (JFXVar fxVar : tree.getParameters()) { |
1325 | 8 | setLocallyBound(fxVar.sym); |
1326 | |
} |
1327 | |
} |
1328 | |
|
1329 | |
|
1330 | 1181 | JFXBlockExpression bexpr = tree.getBodyExpression(); |
1331 | |
JCBlock body; |
1332 | 1181 | if (bexpr == null) { |
1333 | 10 | body = null; |
1334 | 1171 | } else if (isBound) { |
1335 | |
|
1336 | |
|
1337 | 14 | JCExpression expr = toBound.translate(bexpr, typeMorpher.varMorphInfo(tree.sym)); |
1338 | 14 | body = asBlock(make.at(diagPos).Return(expr)); |
1339 | 14 | } else if (syms.isRunMethod(tree.sym)) { |
1340 | |
|
1341 | 340 | body = runMethodBody(bexpr); |
1342 | 340 | isImplMethod = false; |
1343 | |
} else { |
1344 | |
|
1345 | 817 | body = asBlock(translateExpressionToStatement(bexpr, mtype.getReturnType())); |
1346 | |
} |
1347 | |
|
1348 | 1181 | ListBuffer<JCVariableDecl> params = ListBuffer.lb(); |
1349 | 1181 | if ((originalFlags & (Flags.STATIC | Flags.ABSTRACT | Flags.SYNTHETIC)) == 0) { |
1350 | 524 | if (classOnly) { |
1351 | |
|
1352 | |
|
1353 | |
|
1354 | 71 | body.stats = body.stats.prepend( |
1355 | |
make.at(diagPos).VarDef( |
1356 | |
make.at(diagPos).Modifiers(Flags.FINAL), |
1357 | |
defs.receiverName, |
1358 | |
make.Ident(initBuilder.interfaceName(currentClass)), |
1359 | |
make.at(diagPos).Ident(names._this)) |
1360 | |
); |
1361 | |
} else { |
1362 | |
|
1363 | 453 | params.prepend(makeReceiverParam(currentClass)); |
1364 | |
} |
1365 | |
} |
1366 | 1181 | for (JFXVar fxVar : tree.getParameters()) { |
1367 | 1049 | JCVariableDecl var = (JCVariableDecl)translate(fxVar); |
1368 | 1049 | params.append(var); |
1369 | 1049 | } |
1370 | |
|
1371 | 1181 | mods = addAccessAnnotationModifiers(diagPos, tree.mods.flags, mods); |
1372 | |
|
1373 | 1181 | result = make.at(diagPos).MethodDef( |
1374 | |
mods, |
1375 | |
functionName(tree.sym, isImplMethod, isBound), |
1376 | |
makeReturnTypeTree(diagPos, tree.sym, isBound), |
1377 | |
make.at(diagPos).TypeParams(mtype.getTypeArguments()), |
1378 | |
params.toList(), |
1379 | |
make.at(diagPos).Types(mtype.getThrownTypes()), |
1380 | |
body, |
1381 | |
null); |
1382 | 1181 | ((JCMethodDecl)result).sym = tree.sym; |
1383 | 1181 | result.type = tree.type; |
1384 | |
} |
1385 | |
finally { |
1386 | 1181 | wrap = prevWrap; |
1387 | 1181 | } |
1388 | 1181 | } |
1389 | |
|
1390 | |
public void visitBindExpression(JFXBindExpression tree) { |
1391 | 0 | throw new AssertionError(tree); |
1392 | |
} |
1393 | |
|
1394 | |
public void visitBlockExpression(JFXBlockExpression tree) { |
1395 | 1501 | DiagnosticPosition diagPos = tree.pos(); |
1396 | 1501 | ListBuffer<JCStatement> prevPrependToStatements = prependToStatements; |
1397 | 1501 | prependToStatements = ListBuffer.lb(); |
1398 | |
|
1399 | 1501 | JCExpression value = tree.value; |
1400 | 1501 | boolean valueFromReturn = (value == null) && (yield == Yield.ToReturnStatement); |
1401 | 1501 | ListBuffer<JCStatement> translated = ListBuffer.lb(); |
1402 | 1501 | for(JCStatement stmt : tree.getStatements()) { |
1403 | 2070 | if (valueFromReturn && stmt.getTag() == JavafxTag.RETURN) { |
1404 | 174 | value = ((JCReturn)stmt).getExpression(); |
1405 | |
} else { |
1406 | 1896 | translated.append( translate(stmt) ); |
1407 | |
} |
1408 | |
} |
1409 | 1501 | List<JCStatement> localDefs = translated.toList(); |
1410 | |
|
1411 | 1501 | if (yield == Yield.ToExpression) { |
1412 | 91 | assert (tree.type != syms.voidType) : "void block expressions should be handled below"; |
1413 | 91 | JCExpression tvalue = translate(value); |
1414 | 91 | localDefs = prependToStatements.appendList(localDefs).toList(); |
1415 | 91 | result = ((JavafxTreeMaker) make).at(tree.pos).BlockExpression(tree.flags, localDefs, tvalue); |
1416 | 91 | } else { |
1417 | 1410 | prependToStatements.appendList(localDefs); |
1418 | 1410 | if (value != null) { |
1419 | 1135 | prependToStatements.append( translateExpressionToStatement(value) ); |
1420 | |
} |
1421 | 1410 | localDefs = prependToStatements.toList(); |
1422 | 1410 | result = localDefs.size() == 1? localDefs.head : make.at(diagPos).Block(0L, localDefs); |
1423 | |
} |
1424 | 1501 | prependToStatements = prevPrependToStatements; |
1425 | 1501 | } |
1426 | |
|
1427 | |
@Override |
1428 | |
public void visitBlock(JCBlock tree) { |
1429 | 240 | List<JCStatement> localDefs = translateStatements(tree.stats); |
1430 | 240 | result = make.at(tree.pos).Block(tree.flags, localDefs); |
1431 | 240 | } |
1432 | |
|
1433 | |
@Override |
1434 | |
public void visitAssign(JCAssign tree) { |
1435 | 938 | DiagnosticPosition diagPos = tree.pos(); |
1436 | |
|
1437 | 938 | Symbol sym = expressionSymbol(tree.lhs); |
1438 | 938 | VarSymbol vsym = (sym != null && (sym instanceof VarSymbol))? (VarSymbol)sym : null; |
1439 | |
|
1440 | 938 | if (tree.rhs instanceof JFXBindExpression) { |
1441 | 4 | JFXBindExpression bind = (JFXBindExpression) tree.rhs; |
1442 | 4 | JCExpression lhs = translate(tree.lhs, Wrapped.InLocation); |
1443 | 4 | result = translateDefinitionalAssignmentToSetExpression(bind.pos(), |
1444 | |
bind.getExpression(), bind.getBindStatus(), vsym, |
1445 | |
null , FROM_DEFAULT_MILIEU); |
1446 | 4 | return; |
1447 | |
} |
1448 | |
|
1449 | 934 | JCExpression rhs = translate(tree.rhs); |
1450 | 934 | if (tree.lhs.getTag() == JavafxTag.SEQUENCE_INDEXED) { |
1451 | |
|
1452 | 60 | JFXSequenceIndexed si = (JFXSequenceIndexed)tree.lhs; |
1453 | 60 | JCExpression seq = translate(si.getSequence(), Wrapped.InLocation); |
1454 | 60 | JCExpression index = translate(si.getIndex()); |
1455 | 60 | JCFieldAccess select = make.Select(seq, defs.setMethodName); |
1456 | 60 | List<JCExpression> args = List.of(index, rhs); |
1457 | 60 | result = make.at(diagPos).Apply(null, select, args); |
1458 | 60 | } else if (tree.lhs.getTag() == JavafxTag.SEQUENCE_SLICE) { |
1459 | |
|
1460 | 12 | JFXSequenceSlice si = (JFXSequenceSlice)tree.lhs; |
1461 | 12 | JCExpression seq = translate(si.getSequence(), Wrapped.InLocation); |
1462 | 12 | JCExpression firstIndex = translate(si.getFirstIndex()); |
1463 | 12 | JCExpression lastIndex = makeSliceLastIndex(si); |
1464 | 12 | JCFieldAccess select = make.Select(seq, defs.replaceSliceMethodName); |
1465 | 12 | List<JCExpression> args = List.of(firstIndex, lastIndex, rhs); |
1466 | 12 | result = make.at(diagPos).Apply(null, select, args); |
1467 | 12 | } else if (shouldMorph(vsym)) { |
1468 | |
|
1469 | 539 | JCExpression lhs = translate(tree.lhs, Wrapped.InLocation); |
1470 | 539 | JCFieldAccess setSelect = make.Select(lhs, defs.locationSetMethodName[typeMorpher.typeMorphInfo(vsym.type).getTypeKind()]); |
1471 | 539 | List<JCExpression> setArgs = List.of(rhs); |
1472 | 539 | result = make.at(diagPos).Apply(null, setSelect, setArgs); |
1473 | 539 | } else { |
1474 | |
|
1475 | 323 | JCExpression lhs = translate(tree.lhs); |
1476 | 323 | result = make.at(diagPos).Assign(lhs, rhs); |
1477 | |
} |
1478 | 934 | } |
1479 | |
|
1480 | |
@Override |
1481 | |
public void visitAssignop(JCAssignOp tree) { |
1482 | 38 | DiagnosticPosition diagPos = tree.pos(); |
1483 | |
|
1484 | 38 | Symbol sym = expressionSymbol(tree.lhs); |
1485 | 38 | VarSymbol vsym = (sym != null && (sym instanceof VarSymbol))? (VarSymbol)sym : null; |
1486 | |
|
1487 | 38 | JCExpression rhs = translate(tree.rhs); |
1488 | 38 | JCExpression lhs = translate(tree.lhs); |
1489 | |
int binaryOp; |
1490 | 38 | switch (tree.getTag()) { |
1491 | |
case JCTree.PLUS_ASG: |
1492 | 25 | binaryOp = JCTree.PLUS; |
1493 | 25 | break; |
1494 | |
case JCTree.MINUS_ASG: |
1495 | 4 | binaryOp = JCTree.MINUS; |
1496 | 4 | break; |
1497 | |
case JCTree.MUL_ASG: |
1498 | 3 | binaryOp = JCTree.MUL; |
1499 | 3 | break; |
1500 | |
case JCTree.DIV_ASG: |
1501 | 3 | binaryOp = JCTree.DIV; |
1502 | 3 | break; |
1503 | |
case JCTree.MOD_ASG: |
1504 | 3 | binaryOp = JCTree.MOD; |
1505 | 3 | break; |
1506 | |
default: |
1507 | 0 | assert false : "unexpected assign op kind"; |
1508 | 0 | binaryOp = JCTree.PLUS; |
1509 | |
break; |
1510 | |
} |
1511 | 38 | JCExpression combined = make.at(diagPos).Binary(binaryOp, lhs, rhs); |
1512 | |
|
1513 | 38 | if (tree.lhs.getTag() == JavafxTag.SEQUENCE_INDEXED) { |
1514 | |
|
1515 | 4 | JFXSequenceIndexed si = (JFXSequenceIndexed)tree.lhs; |
1516 | 4 | JCExpression seq = translate(si.getSequence(), Wrapped.InLocation); |
1517 | 4 | JCExpression index = translate(si.getIndex()); |
1518 | 4 | JCFieldAccess select = make.Select(seq, defs.setMethodName); |
1519 | 4 | List<JCExpression> args = List.of(index, combined); |
1520 | 4 | result = make.at(diagPos).Apply(null, select, args); |
1521 | 4 | } else if (shouldMorph(vsym)) { |
1522 | |
|
1523 | 17 | JCExpression targetLHS = translate(tree.lhs, Wrapped.InLocation); |
1524 | 17 | JCFieldAccess setSelect = make.Select(targetLHS, defs.locationSetMethodName[typeMorpher.typeMorphInfo(vsym.type).getTypeKind()]); |
1525 | 17 | List<JCExpression> setArgs = List.of(combined); |
1526 | 17 | result = make.at(diagPos).Apply(null, setSelect, setArgs); |
1527 | 17 | } else { |
1528 | |
|
1529 | 17 | result = make.at(diagPos).Assignop(tree.getTag(), lhs, rhs); |
1530 | |
} |
1531 | 38 | } |
1532 | |
|
1533 | |
@Override |
1534 | |
public void visitSelect(JCFieldAccess tree) { |
1535 | 6473 | DiagnosticPosition diagPos = tree.pos(); |
1536 | 6473 | JCExpression expr = tree.getExpression(); |
1537 | 6473 | Type exprType = expr.type; |
1538 | |
|
1539 | |
|
1540 | |
|
1541 | 6473 | JCExpression translatedSelected = translate(expr, Wrapped.InNothing); |
1542 | |
|
1543 | 6473 | if (tree.type instanceof FunctionType && tree.sym.type instanceof MethodType) { |
1544 | |
|
1545 | 0 | MethodType mtype = (MethodType) tree.sym.type; |
1546 | 0 | JCVariableDecl selectedTmpDecl = makeTmpVar(diagPos, "tg", exprType, translatedSelected); |
1547 | 0 | JCExpression translated = make.at(diagPos).Select(make.Ident(selectedTmpDecl.name), tree.getIdentifier()); |
1548 | 0 | translated = makeFunctionValue(translated, null, diagPos, mtype); |
1549 | |
|
1550 | 0 | result = ((JavafxTreeMaker)make).BlockExpression( |
1551 | |
0L, |
1552 | |
List.<JCStatement>of(selectedTmpDecl), |
1553 | |
translated); |
1554 | 0 | return; |
1555 | |
} |
1556 | |
|
1557 | 6473 | if (exprType != null && exprType.isPrimitive()) { |
1558 | 25 | translatedSelected = makeBox(diagPos, translatedSelected, exprType); |
1559 | |
} |
1560 | |
|
1561 | 6473 | boolean staticReference = tree.sym.isStatic(); |
1562 | 6473 | if (staticReference) { |
1563 | 3558 | translatedSelected = makeTypeTree( diagPos,types.erasure(tree.sym.owner.type), false); |
1564 | |
} |
1565 | |
|
1566 | 6473 | boolean testForNull = generateNullChecks && !staticReference |
1567 | |
&& (tree.sym instanceof VarSymbol) |
1568 | |
&& types.isJFXClass(exprType.tsym); |
1569 | 6473 | boolean hasSideEffects = testForNull && hasSideEffects(expr); |
1570 | 6473 | JCVariableDecl tmpVar = null; |
1571 | 6473 | if (hasSideEffects) { |
1572 | 8 | tmpVar = makeTmpVar(diagPos, exprType, translatedSelected); |
1573 | 8 | translatedSelected = make.at(diagPos).Ident(tmpVar.name); |
1574 | |
} |
1575 | |
|
1576 | 6473 | JCFieldAccess translated = make.at(diagPos).Select(translatedSelected, tree.getIdentifier()); |
1577 | |
|
1578 | 6473 | JCExpression ref = convertVariableReference( |
1579 | |
diagPos, |
1580 | |
translated, |
1581 | |
tree.sym, |
1582 | |
(wrap == Wrapped.InLocation)); |
1583 | 6473 | if (testForNull) { |
1584 | |
|
1585 | 471 | TypeMorphInfo tmi = typeMorpher.typeMorphInfo(tree.type); |
1586 | 471 | JCExpression defaultExpr = makeDefaultValue(diagPos, tmi); |
1587 | 471 | if (wrap == Wrapped.InLocation) { |
1588 | 114 | defaultExpr = makeUnboundLocation(diagPos, tmi, defaultExpr); |
1589 | |
} |
1590 | |
|
1591 | |
JCExpression checkedExpr; |
1592 | 471 | if (hasSideEffects) { |
1593 | |
|
1594 | 8 | checkedExpr = make.at(diagPos).Ident(tmpVar.name); |
1595 | |
} else { |
1596 | |
|
1597 | 463 | checkedExpr = translate(expr, Wrapped.InNothing); |
1598 | |
} |
1599 | 471 | JCExpression cond = make.at(diagPos).Binary( |
1600 | |
JCTree.EQ, |
1601 | |
checkedExpr, |
1602 | |
make.Literal(TypeTags.BOT, null)); |
1603 | 471 | ref = make.at(diagPos).Conditional(cond, defaultExpr, ref); |
1604 | 471 | if (hasSideEffects) { |
1605 | |
|
1606 | 8 | List<JCStatement> stmts = List.<JCStatement>of(tmpVar); |
1607 | 8 | ref = fxmake.at(diagPos).BlockExpression(0L, stmts, ref); |
1608 | |
} |
1609 | |
} |
1610 | 6473 | result = ref; |
1611 | 6473 | } |
1612 | |
|
1613 | |
private boolean hasSideEffects(JCExpression expr) { |
1614 | 2596 | final boolean[] hasSideEffectHolder = {false}; |
1615 | 2596 | new JavafxTreeScanner() { |
1616 | |
|
1617 | |
private void markSideEffects() { |
1618 | 52 | hasSideEffectHolder[0] = true; |
1619 | 52 | } |
1620 | |
|
1621 | |
@Override |
1622 | |
public void visitBlockExpression(JFXBlockExpression tree) { |
1623 | 0 | markSideEffects(); |
1624 | 0 | } |
1625 | |
|
1626 | |
@Override |
1627 | |
public void visitUnary(JCUnary tree) { |
1628 | 3 | markSideEffects(); |
1629 | 3 | } |
1630 | |
|
1631 | |
@Override |
1632 | |
public void visitAssignop(JCAssignOp tree) { |
1633 | 0 | markSideEffects(); |
1634 | 0 | } |
1635 | |
|
1636 | |
@Override |
1637 | |
public void visitInstanciate(JFXInstanciate tree) { |
1638 | 10 | markSideEffects(); |
1639 | 10 | } |
1640 | |
|
1641 | |
@Override |
1642 | |
public void visitAssign(JCAssign tree) { |
1643 | 0 | markSideEffects(); |
1644 | 0 | } |
1645 | |
|
1646 | |
@Override |
1647 | |
public void visitApply(JCMethodInvocation tree) { |
1648 | 39 | markSideEffects(); |
1649 | 39 | } |
1650 | |
}.scan(expr); |
1651 | 2596 | return hasSideEffectHolder[0]; |
1652 | |
} |
1653 | |
|
1654 | |
@Override |
1655 | |
public void visitIdent(JCIdent tree) { |
1656 | 12647 | DiagnosticPosition diagPos = tree.pos(); |
1657 | 12647 | if (tree.name == names._this) { |
1658 | |
|
1659 | 35 | JCExpression rcvr = make.at(diagPos).Ident(defs.receiverName); |
1660 | 35 | if (wrap == Wrapped.InLocation) { |
1661 | 0 | rcvr = makeConstantLocation(diagPos, tree.type, rcvr); |
1662 | |
} |
1663 | 35 | result = rcvr; |
1664 | 35 | return; |
1665 | 12612 | } else if (tree.name == names._super) { |
1666 | 9 | if (types.isCompoundClass(tree.type.tsym)) { |
1667 | |
|
1668 | |
|
1669 | 9 | result = make.at(diagPos).Ident(tree.type.tsym.name); |
1670 | |
} |
1671 | |
else { |
1672 | 0 | JCFieldAccess superSelect = make.at(diagPos).Select(make.at(diagPos).Ident(defs.receiverName), tree.name); |
1673 | 0 | result = superSelect; |
1674 | |
} |
1675 | 9 | return; |
1676 | |
} |
1677 | |
|
1678 | |
|
1679 | |
|
1680 | |
JCExpression convert; |
1681 | 12603 | boolean isStatic = tree.sym.isStatic(); |
1682 | 12603 | int kind = tree.sym.kind; |
1683 | 12603 | if (isStatic) { |
1684 | |
|
1685 | 1044 | convert = make.at(diagPos).Select(makeTypeTree( diagPos,tree.sym.owner.type, false), tree.name); |
1686 | |
} else { |
1687 | 11559 | if ((kind == Kinds.VAR || kind == Kinds.MTH) && tree.sym.owner.kind == Kinds.TYP) { |
1688 | |
|
1689 | |
|
1690 | 1999 | JCExpression mRec = makeReceiver(diagPos, tree.sym, attrEnv.enclClass.sym); |
1691 | 1999 | convert = make.at(diagPos).Select(mRec, tree.name); |
1692 | 1999 | } else { |
1693 | 9560 | convert = make.at(diagPos).Ident(tree.name); |
1694 | |
} |
1695 | |
} |
1696 | |
|
1697 | 12603 | if (tree.type instanceof FunctionType && tree.sym.type instanceof MethodType) { |
1698 | 9 | MethodType mtype = (MethodType) tree.sym.type; |
1699 | 9 | JFXFunctionDefinition def = null; |
1700 | 9 | result = makeFunctionValue(convert, def, tree.pos(), mtype); |
1701 | 9 | return; |
1702 | |
} |
1703 | |
|
1704 | 12594 | result = convertVariableReference(diagPos, |
1705 | |
convert, |
1706 | |
tree.sym, |
1707 | |
(wrap == Wrapped.InLocation)); |
1708 | 12594 | } |
1709 | |
|
1710 | |
@Override |
1711 | |
public void visitSequenceExplicit(JFXSequenceExplicit tree) { |
1712 | |
|
1713 | |
|
1714 | |
|
1715 | |
|
1716 | |
|
1717 | |
|
1718 | |
|
1719 | |
|
1720 | |
|
1721 | |
|
1722 | |
|
1723 | |
|
1724 | |
|
1725 | |
|
1726 | |
|
1727 | 378 | ListBuffer<JCStatement> stmts = ListBuffer.lb(); |
1728 | 378 | Type elemType = elementType(tree.type); |
1729 | 378 | UseSequenceBuilder builder = useSequenceBuilder(tree.pos(), elemType); |
1730 | 378 | stmts.append(builder.makeBuilderVar()); |
1731 | 378 | for (JCExpression item : tree.getItems()) { |
1732 | 1420 | stmts.append(builder.makeAdd( item ) ); |
1733 | |
} |
1734 | 378 | result = makeBlockExpression(tree.pos(), stmts, builder.makeToSequence()); |
1735 | 378 | } |
1736 | |
|
1737 | |
@Override |
1738 | |
public void visitSequenceRange(JFXSequenceRange tree) { |
1739 | 180 | DiagnosticPosition diagPos = tree.pos(); |
1740 | 180 | JCExpression meth = makeQualifiedTree( |
1741 | |
diagPos, tree.isExclusive()? |
1742 | |
sequencesRangeExclusiveString : |
1743 | |
sequencesRangeString); |
1744 | 180 | ListBuffer<JCExpression> args = ListBuffer.lb(); |
1745 | 180 | List<JCExpression> typeArgs = List.nil(); |
1746 | 180 | args.append( translate( tree.getLower() )); |
1747 | 180 | args.append( translate( tree.getUpper() )); |
1748 | 180 | if (tree.getStepOrNull() != null) { |
1749 | 39 | args.append( translate( tree.getStepOrNull() )); |
1750 | |
} |
1751 | 180 | result = make.at(diagPos).Apply(typeArgs, meth, args.toList()); |
1752 | 180 | } |
1753 | |
|
1754 | |
@Override |
1755 | |
public void visitSequenceEmpty(JFXSequenceEmpty tree) { |
1756 | 51 | if (types.isSequence(tree.type)) { |
1757 | 23 | Type elemType = elementType(tree.type); |
1758 | 23 | result = makeEmptySequenceCreator(tree.pos(), elemType); |
1759 | 23 | } |
1760 | |
else |
1761 | 28 | result = make.at(tree.pos).Literal(TypeTags.BOT, null); |
1762 | 51 | } |
1763 | |
|
1764 | |
@Override |
1765 | |
public void visitSequenceIndexed(JFXSequenceIndexed tree) { |
1766 | 398 | DiagnosticPosition diagPos = tree.pos(); |
1767 | 398 | JCExpression seq = translate(tree.getSequence(), Wrapped.InLocation); |
1768 | 398 | JCExpression index = translate(tree.getIndex()); |
1769 | 398 | JCFieldAccess select = make.at(diagPos).Select(seq, defs.getMethodName); |
1770 | 398 | List<JCExpression> args = List.of(index); |
1771 | 398 | result = make.at(diagPos).Apply(null, select, args); |
1772 | 398 | } |
1773 | |
|
1774 | |
@Override |
1775 | |
public void visitSequenceSlice(JFXSequenceSlice tree) { |
1776 | 14 | DiagnosticPosition diagPos = tree.pos(); |
1777 | 14 | JCExpression seq = translate(tree.getSequence(), Wrapped.InLocation); |
1778 | 14 | JCExpression firstIndex = translate(tree.getFirstIndex()); |
1779 | 14 | JCExpression lastIndex = makeSliceLastIndex(tree); |
1780 | 14 | JCFieldAccess select = make.at(diagPos).Select(seq, defs.getSliceMethodName); |
1781 | 14 | List<JCExpression> args = List.of(firstIndex, lastIndex); |
1782 | 14 | result = make.at(diagPos).Apply(null, select, args); |
1783 | 14 | } |
1784 | |
|
1785 | |
@Override |
1786 | |
public void visitSequenceInsert(JFXSequenceInsert tree) { |
1787 | 186 | DiagnosticPosition diagPos = tree.pos(); |
1788 | 186 | JCExpression seqLoc = translate(tree.getSequence(), Wrapped.InLocation); |
1789 | 186 | JCExpression elem = translate( tree.getElement() ); |
1790 | 186 | if (tree.getPosition() == null) { |
1791 | 99 | result = callStatement(diagPos, seqLoc, "insert", elem); |
1792 | |
} else { |
1793 | 87 | String meth = tree.shouldInsertAfter()? "insertAfter" : "insertBefore"; |
1794 | 87 | result = callStatement(diagPos, seqLoc, meth, |
1795 | |
List.of(elem, translate(tree.getPosition()))); |
1796 | |
} |
1797 | 186 | } |
1798 | |
|
1799 | |
@Override |
1800 | |
public void visitSequenceDelete(JFXSequenceDelete tree) { |
1801 | 123 | JCExpression seq = tree.getSequence(); |
1802 | |
|
1803 | 123 | if (tree.getElement() != null) { |
1804 | 25 | JCExpression seqLoc = translate(seq, Wrapped.InLocation); |
1805 | 25 | result = callStatement(tree.pos(), seqLoc, "deleteValue", translate(tree.getElement())); |
1806 | 25 | } else { |
1807 | 98 | if (seq.getTag() == JavafxTag.SEQUENCE_INDEXED) { |
1808 | |
|
1809 | 38 | JFXSequenceIndexed si = (JFXSequenceIndexed) seq; |
1810 | 38 | JCExpression seqseq = si.getSequence(); |
1811 | 38 | JCExpression seqLoc = translate(seqseq, Wrapped.InLocation); |
1812 | 38 | JCExpression index = translate(si.getIndex()); |
1813 | 38 | result = callStatement(tree.pos(), seqLoc, "delete", index); |
1814 | 38 | } else if (seq.getTag() == JavafxTag.SEQUENCE_SLICE) { |
1815 | |
|
1816 | 35 | JFXSequenceSlice slice = (JFXSequenceSlice) seq; |
1817 | 35 | JCExpression seqseq = slice.getSequence(); |
1818 | 35 | JCExpression seqLoc = translate(seqseq, Wrapped.InLocation); |
1819 | 35 | JCExpression first = translate(slice.getFirstIndex()); |
1820 | 35 | JCExpression last = makeSliceLastIndex(slice); |
1821 | 35 | result = callStatement(tree.pos(), seqLoc, "deleteSlice", List.of(first, last)); |
1822 | 35 | } else if (types.isSequence(seq.type)) { |
1823 | 25 | JCExpression seqLoc = translate(seq, Wrapped.InLocation); |
1824 | 25 | result = callStatement(tree.pos(), seqLoc, "deleteAll"); |
1825 | 25 | } else { |
1826 | 0 | result = make.at(tree.pos()).Exec( |
1827 | |
make.Assign( |
1828 | |
translate(seq), |
1829 | |
make.Literal(TypeTags.BOT, null))); |
1830 | |
} |
1831 | |
} |
1832 | 123 | } |
1833 | |
|
1834 | |
|
1835 | |
|
1836 | |
JCExpression makeSliceLastIndex(JFXSequenceSlice tree) { |
1837 | 61 | JCExpression lastIndex = tree.getLastIndex() == null ? |
1838 | |
callExpression(tree, |
1839 | |
translate(tree.getSequence()), |
1840 | |
defs.sizeMethodName) : |
1841 | |
translate(tree.getLastIndex()); |
1842 | 61 | int decr = |
1843 | |
(tree.getEndKind() == SequenceSliceTree.END_EXCLUSIVE ? 1 : 0) + |
1844 | |
(tree.getLastIndex() == null ? 1 : 0); |
1845 | 61 | if (decr > 0) { |
1846 | 26 | lastIndex = make.at(tree).Binary(JavafxTag.MINUS, |
1847 | |
lastIndex, make.Literal(TypeTags.INT, decr)); |
1848 | |
} |
1849 | 61 | return lastIndex; |
1850 | |
} |
1851 | |
|
1852 | |
JCMethodDecl makeMainMethod(DiagnosticPosition diagPos, Name className) { |
1853 | 340 | List<JCExpression> emptyExpressionList = List.nil(); |
1854 | 340 | JCExpression classIdent = make.at(diagPos).Ident(className); |
1855 | 340 | JCExpression classConstant = make.at(diagPos).Select(classIdent, names._class); |
1856 | 340 | JCExpression commandLineArgs = makeIdentifier(diagPos, "args"); |
1857 | 340 | JCExpression startIdent = makeQualifiedTree(diagPos, JavafxDefs.startMethodString); |
1858 | 340 | ListBuffer<JCExpression>args = new ListBuffer<JCExpression>(); |
1859 | 340 | args.append(classConstant); |
1860 | 340 | args.append(commandLineArgs); |
1861 | 340 | JCMethodInvocation runCall = make.at(diagPos).Apply(emptyExpressionList, startIdent, args.toList()); |
1862 | 340 | List<JCStatement> mainStats = List.<JCStatement>of(make.at(diagPos).Exec(runCall)); |
1863 | 340 | List<JCVariableDecl> paramList = List.nil(); |
1864 | 340 | paramList = paramList.append(make.at(diagPos).VarDef(make.Modifiers(0), |
1865 | |
Name.fromString(names, "args"), |
1866 | |
make.at(diagPos).TypeArray(make.Ident(Name.fromString(names, "String"))), |
1867 | |
null)); |
1868 | 340 | JCBlock body = make.Block(0, mainStats); |
1869 | 340 | return make.at(diagPos).MethodDef(make.Modifiers(Flags.PUBLIC | Flags.STATIC), |
1870 | |
Name.fromString(names, "main"), |
1871 | |
make.at(diagPos).TypeIdent(TypeTags.VOID), |
1872 | |
List.<JCTypeParameter>nil(), |
1873 | |
paramList, |
1874 | |
makeThrows(diagPos), |
1875 | |
body, |
1876 | |
null); |
1877 | |
} |
1878 | |
|
1879 | |
|
1880 | |
|
1881 | |
|
1882 | |
TreeMaker make_at(DiagnosticPosition pos) { |
1883 | 47 | return make.at(pos); |
1884 | |
} |
1885 | |
|
1886 | |
|
1887 | |
|
1888 | |
private MethodSymbol lookupMethod(DiagnosticPosition pos, Name name, Type qual, List<Type> args) { |
1889 | 47 | return rs.resolveInternalMethod(pos, attrEnv, qual, name, args, null); |
1890 | |
} |
1891 | |
|
1892 | |
|
1893 | |
|
1894 | |
private MethodSymbol lookupConstructor(DiagnosticPosition pos, Type qual, List<Type> args) { |
1895 | 0 | return rs.resolveInternalConstructor(pos, attrEnv, qual, args, null); |
1896 | |
} |
1897 | |
|
1898 | |
|
1899 | |
JCExpression makeBox(DiagnosticPosition diagPos, JCExpression translatedExpr, Type primitiveType) { |
1900 | 47 | make_at(translatedExpr.pos()); |
1901 | 47 | if (target.boxWithConstructors()) { |
1902 | 0 | Symbol ctor = lookupConstructor(translatedExpr.pos(), |
1903 | |
types.boxedClass(primitiveType).type, |
1904 | |
List.<Type>nil() |
1905 | |
.prepend(primitiveType)); |
1906 | 0 | return make.Create(ctor, List.of(translatedExpr)); |
1907 | |
} else { |
1908 | 47 | Symbol valueOfSym = lookupMethod(translatedExpr.pos(), |
1909 | |
names.valueOf, |
1910 | |
types.boxedClass(primitiveType).type, |
1911 | |
List.<Type>nil() |
1912 | |
.prepend(primitiveType)); |
1913 | |
|
1914 | 47 | JCExpression meth = make.Select(makeTypeTree( diagPos,valueOfSym.owner.type), valueOfSym.name); |
1915 | 47 | TreeInfo.setSymbol(meth, valueOfSym); |
1916 | 47 | meth.type = valueOfSym.type; |
1917 | 47 | return make.App(meth, List.of(translatedExpr)); |
1918 | |
} |
1919 | |
} |
1920 | |
|
1921 | |
public List<JCExpression> makeThrows(DiagnosticPosition diagPos) { |
1922 | 340 | return List.of(makeQualifiedTree(diagPos, methodThrowsString)); |
1923 | |
} |
1924 | |
|
1925 | |
UseSequenceBuilder useSequenceBuilder(DiagnosticPosition diagPos, Type elemType) { |
1926 | |
|
1927 | 432 | return new UseSequenceBuilder(diagPos, elemType, sequenceBuilderString) { |
1928 | |
|
1929 | |
JCStatement makeAdd(JCExpression exprToAdd) { |
1930 | 1474 | JCExpression expr = translate(exprToAdd); |
1931 | 1474 | Type exprType = exprToAdd.type; |
1932 | 1474 | return makeAdd(expr, exprType); |
1933 | |
} |
1934 | |
}; |
1935 | |
} |
1936 | |
|
1937 | |
UseSequenceBuilder useBoundSequenceBuilder(DiagnosticPosition diagPos, Type elemType) { |
1938 | |
|
1939 | 29 | return new UseSequenceBuilder(diagPos, elemType, boundSequenceBuilderString) { |
1940 | |
|
1941 | |
JCStatement makeAdd(JCExpression exprToAdd) { |
1942 | 80 | JCExpression expr = toBound.translate(exprToAdd); |
1943 | 80 | Type exprType = exprToAdd.type; |
1944 | 80 | return makeAdd(expr, exprType); |
1945 | |
} |
1946 | |
}; |
1947 | |
} |
1948 | |
|
1949 | |
abstract class UseSequenceBuilder { |
1950 | |
final DiagnosticPosition diagPos; |
1951 | |
final Type elemType; |
1952 | |
final String seqBuilder; |
1953 | |
|
1954 | |
Name sbName; |
1955 | |
|
1956 | 461 | UseSequenceBuilder(DiagnosticPosition diagPos, Type elemType, String seqBuilder) { |
1957 | 461 | this.diagPos = diagPos; |
1958 | 461 | this.elemType = elemType; |
1959 | 461 | this.seqBuilder = seqBuilder; |
1960 | 461 | } |
1961 | |
|
1962 | |
JCStatement makeBuilderVar() { |
1963 | 461 | JCExpression builderTypeExpr = makeQualifiedTree(diagPos, seqBuilder); |
1964 | 461 | List<JCExpression> btargs = List.of(makeTypeTree(diagPos, elemType)); |
1965 | 461 | builderTypeExpr = make.at(diagPos).TypeApply(builderTypeExpr, btargs); |
1966 | |
|
1967 | |
|
1968 | 461 | sbName = getSyntheticName("sb"); |
1969 | |
|
1970 | |
|
1971 | 461 | List<JCExpression> args = List.<JCExpression>of( |
1972 | |
makeElementClassObject(diagPos, elemType)); |
1973 | |
|
1974 | 461 | JCExpression newExpr = make.at(diagPos).NewClass( |
1975 | |
null, |
1976 | |
List.<JCExpression>nil(), |
1977 | |
make.at(diagPos).TypeApply( |
1978 | |
makeQualifiedTree(diagPos, seqBuilder), |
1979 | |
List.<JCExpression>of(makeTypeTree(diagPos, elemType))), |
1980 | |
args, |
1981 | |
null |
1982 | |
); |
1983 | |
|
1984 | |
|
1985 | 461 | return make.at(diagPos).VarDef( |
1986 | |
make.at(diagPos).Modifiers(0L), |
1987 | |
sbName, builderTypeExpr, newExpr); |
1988 | |
} |
1989 | |
|
1990 | |
JCIdent makeBuilderVarAccess() { |
1991 | 2015 | return make.Ident(sbName); |
1992 | |
} |
1993 | |
|
1994 | |
abstract JCStatement makeAdd(JCExpression expr); |
1995 | |
|
1996 | |
JCStatement makeAdd(JCExpression expr, Type exprType) { |
1997 | 1554 | if (exprType != elemType) { |
1998 | 863 | Type unboxedElemType = types.unboxedType(elemType); |
1999 | 863 | if (unboxedElemType != Type.noType) { |
2000 | 734 | Type unboxedExprType = types.unboxedType(exprType); |
2001 | 734 | if (unboxedExprType != Type.noType) { |
2002 | 0 | expr = make.at(diagPos).TypeCast(unboxedExprType, expr); |
2003 | 0 | exprType = unboxedExprType; |
2004 | |
} |
2005 | 734 | if (exprType.tag == TypeTags.INT && unboxedElemType.tag == TypeTags.DOUBLE) { |
2006 | 26 | expr = make.at(diagPos).TypeCast(unboxedElemType, expr); |
2007 | |
} |
2008 | |
} |
2009 | |
} |
2010 | 1554 | JCMethodInvocation addCall = make.Apply( |
2011 | |
List.<JCExpression>nil(), |
2012 | |
make.at(diagPos).Select( |
2013 | |
makeBuilderVarAccess(), |
2014 | |
Name.fromString(names, "add")), |
2015 | |
List.<JCExpression>of(expr)); |
2016 | 1554 | return make.at(diagPos).Exec(addCall); |
2017 | |
} |
2018 | |
|
2019 | |
JCExpression makeToSequence() { |
2020 | 461 | return make.Apply( |
2021 | |
List.<JCExpression>nil(), |
2022 | |
make.at(diagPos).Select( |
2023 | |
makeBuilderVarAccess(), |
2024 | |
Name.fromString(names, toSequenceString)), |
2025 | |
List.<JCExpression>nil() |
2026 | |
); |
2027 | |
} |
2028 | |
} |
2029 | |
|
2030 | |
JCExpression castFromObject (JCExpression arg, Type castType) { |
2031 | 26 | if (castType.isPrimitive()) |
2032 | 17 | castType = types.boxedClass(castType).type; |
2033 | 26 | return make.TypeCast(makeTypeTree( arg.pos(),castType), arg); |
2034 | |
} |
2035 | |
|
2036 | |
|
2037 | |
|
2038 | |
|
2039 | |
|
2040 | |
@Override |
2041 | |
public void visitAnnotation(JCAnnotation tree) { |
2042 | 0 | JCTree annotationType = translate(tree.annotationType); |
2043 | 0 | List<JCExpression> args = translate(tree.args); |
2044 | 0 | result = make.at(tree.pos).Annotation(annotationType, args); |
2045 | 0 | } |
2046 | |
|
2047 | |
@Override |
2048 | |
public void visitAssert(JCAssert tree) { |
2049 | 0 | JCExpression cond = translate(tree.cond); |
2050 | 0 | JCExpression detail = translate(tree.detail); |
2051 | 0 | result = make.at(tree.pos).Assert(cond, detail); |
2052 | 0 | } |
2053 | |
|
2054 | |
@Override |
2055 | |
public void visitBinary(final JCBinary tree) { |
2056 | 995 | result = (new Translator( tree.pos(), this ) { |
2057 | |
|
2058 | |
|
2059 | |
|
2060 | |
|
2061 | |
private JCExpression makeNullCheck(JCExpression targ) { |
2062 | 18 | return makeEqEq(targ, makeNull()); |
2063 | |
} |
2064 | |
|
2065 | |
|
2066 | |
|
2067 | |
|
2068 | |
|
2069 | |
private JCExpression makePrimitiveNullCheck(Type argType, JCExpression arg) { |
2070 | 0 | TypeMorphInfo tmi = typeMorpher.typeMorphInfo(argType); |
2071 | 0 | JCExpression defaultValue = makeLit(diagPos, tmi.getRealType(), tmi.getDefaultValue()); |
2072 | 0 | return makeEqEq( arg, defaultValue); |
2073 | |
} |
2074 | |
|
2075 | |
|
2076 | |
|
2077 | |
|
2078 | |
private JCExpression makeObjectNullCheck(Type argType, JCExpression arg) { |
2079 | 65 | TypeMorphInfo tmi = typeMorpher.typeMorphInfo(argType); |
2080 | 65 | if (tmi.getTypeKind() == TYPE_KIND_SEQUENCE || tmi.getRealType() == syms.javafx_StringType) { |
2081 | 47 | return callRuntime(JavafxDefs.isNullMethodString, List.of(arg)); |
2082 | |
} else { |
2083 | 18 | return makeNullCheck(arg); |
2084 | |
} |
2085 | |
} |
2086 | |
|
2087 | |
|
2088 | |
|
2089 | |
|
2090 | |
private JCExpression makeEqEq(JCExpression arg1, JCExpression arg2) { |
2091 | 177 | return makeBinary(JCTree.EQ, arg1, arg2); |
2092 | |
} |
2093 | |
|
2094 | |
private JCExpression makeBinary(int tag, JCExpression arg1, JCExpression arg2) { |
2095 | 769 | return make.at(diagPos).Binary(tag, arg1, arg2); |
2096 | |
} |
2097 | |
|
2098 | |
private JCExpression makeNull() { |
2099 | 18 | return make.at(diagPos).Literal(TypeTags.BOT, null); |
2100 | |
} |
2101 | |
|
2102 | |
private JCExpression callRuntime(String methNameString, List<JCExpression> args) { |
2103 | 218 | JCExpression meth = makeQualifiedTree(diagPos, methNameString); |
2104 | 218 | List<JCExpression> typeArgs = List.nil(); |
2105 | 218 | return m().Apply(typeArgs, meth, args); |
2106 | |
} |
2107 | |
|
2108 | |
|
2109 | |
|
2110 | |
|
2111 | |
private JCExpression makeFullCheck(JCExpression lhs, JCExpression rhs) { |
2112 | 171 | return callRuntime(JavafxDefs.equalsMethodString, List.of(lhs, rhs)); |
2113 | |
} |
2114 | |
|
2115 | |
|
2116 | |
|
2117 | |
|
2118 | |
private JCExpression translateEqualsEquals() { |
2119 | 396 | final JCExpression lhs = translate( tree.lhs ); |
2120 | 396 | final JCExpression rhs = translate( tree.rhs ); |
2121 | 396 | final Type lhsType = tree.lhs.type; |
2122 | 396 | final Type rhsType = tree.rhs.type; |
2123 | |
|
2124 | |
|
2125 | 396 | if (lhsType.getKind() == TypeKind.NULL) { |
2126 | 21 | if (rhsType.getKind() == TypeKind.NULL) { |
2127 | |
|
2128 | 1 | return make.at(diagPos).Literal(TypeTags.BOOLEAN, 1); |
2129 | 20 | } else if (rhsType.isPrimitive()) { |
2130 | |
|
2131 | 0 | return makePrimitiveNullCheck(rhsType, rhs); |
2132 | |
} else { |
2133 | |
|
2134 | 20 | return makeObjectNullCheck(rhsType, rhs); |
2135 | |
} |
2136 | 375 | } else if (lhsType.isPrimitive()) { |
2137 | 163 | if (rhsType.getKind() == TypeKind.NULL) { |
2138 | |
|
2139 | 0 | return makePrimitiveNullCheck(lhsType, lhs); |
2140 | 163 | } else if (rhsType.isPrimitive()) { |
2141 | |
|
2142 | 159 | return makeEqEq(lhs, rhs); |
2143 | |
} else { |
2144 | |
|
2145 | 4 | return makeFullCheck(rhs, lhs); |
2146 | |
} |
2147 | |
} else { |
2148 | 212 | if (rhsType.getKind() == TypeKind.NULL) { |
2149 | |
|
2150 | 45 | return makeObjectNullCheck(lhsType, lhs); |
2151 | |
} else { |
2152 | |
|
2153 | 167 | return makeFullCheck(lhs, rhs); |
2154 | |
} |
2155 | |
} |
2156 | |
} |
2157 | |
|
2158 | |
|
2159 | |
|
2160 | |
|
2161 | |
public JCTree doit() { |
2162 | |
|
2163 | 995 | if (tree.getTag() == JavafxTag.EQ) { |
2164 | 303 | return translateEqualsEquals(); |
2165 | 692 | } else if (tree.getTag() == JavafxTag.NE) { |
2166 | 93 | return make.at(diagPos).Unary(JCTree.NOT, translateEqualsEquals()); |
2167 | |
} else { |
2168 | |
|
2169 | |
|
2170 | |
|
2171 | 599 | if ((types.isSameType(tree.lhs.type, syms.javafx_DurationType) || |
2172 | |
types.isSameType(tree.rhs.type, syms.javafx_DurationType)) && |
2173 | |
tree.operator == null) { |
2174 | 7 | JCExpression l = tree.lhs; |
2175 | 7 | JCExpression r = tree.rhs; |
2176 | 7 | switch (tree.getTag()) { |
2177 | |
case JavafxTag.PLUS: |
2178 | 4 | return make.at(diagPos).Apply(null, |
2179 | |
make.at(diagPos).Select(translate(l), Name.fromString(names, "add")), List.<JCExpression>of(translate(r))); |
2180 | |
|
2181 | |
case JavafxTag.MINUS: |
2182 | |
|
2183 | 1 | return make.at(diagPos).Apply(null, |
2184 | |
make.at(diagPos).Select(translate(l), Name.fromString(names, "sub")), List.<JCExpression>of(translate(r))); |
2185 | |
case JavafxTag.DIV: |
2186 | |
|
2187 | 1 | return make.at(diagPos).Apply(null, |
2188 | |
make.at(diagPos).Select(translate(l), Name.fromString(names, "div")), List.<JCExpression>of(translate(r))); |
2189 | |
case JavafxTag.MUL: |
2190 | |
|
2191 | 1 | if (!types.isSameType(l.type, syms.javafx_DurationType)) { |
2192 | 0 | r = l; |
2193 | 0 | l = tree.rhs; |
2194 | |
} |
2195 | 1 | return make.at(diagPos).Apply(null, |
2196 | |
make.at(diagPos).Select(translate(l), Name.fromString(names, "mul")), List.<JCExpression>of(translate(r))); |
2197 | |
case JavafxTag.LT: |
2198 | 0 | return make.at(diagPos).Apply(null, |
2199 | |
make.at(diagPos).Select(translate(l), Name.fromString(names, "lt")), List.<JCExpression>of(translate(r))); |
2200 | |
case JavafxTag.LE: |
2201 | 0 | return make.at(diagPos).Apply(null, |
2202 | |
make.at(diagPos).Select(translate(l), Name.fromString(names, "le")), List.<JCExpression>of(translate(r))); |
2203 | |
case JavafxTag.GT: |
2204 | 0 | return make.at(diagPos).Apply(null, |
2205 | |
make.at(diagPos).Select(translate(l), Name.fromString(names, "gt")), List.<JCExpression>of(translate(r))); |
2206 | |
case JavafxTag.GE: |
2207 | 0 | return make.at(diagPos).Apply(null, |
2208 | |
make.at(diagPos).Select(translate(l), Name.fromString(names, "ge")), List.<JCExpression>of(translate(r))); |
2209 | |
} |
2210 | |
} |
2211 | 592 | final JCExpression lhs = translate(tree.lhs); |
2212 | 592 | final JCExpression rhs = translate(tree.rhs); |
2213 | 592 | return makeBinary(tree.getTag(), lhs, rhs); |
2214 | |
} |
2215 | |
} |
2216 | |
|
2217 | |
}).doit(); |
2218 | 995 | } |
2219 | |
|
2220 | |
@Override |
2221 | |
public void visitBreak(JCBreak tree) { |
2222 | 5 | result = make.at(tree.pos).Break(tree.label); |
2223 | 5 | } |
2224 | |
|
2225 | |
@Override |
2226 | |
public void visitCase(JCCase tree) { |
2227 | 0 | assert false : "should not be in JavaFX AST"; |
2228 | 0 | } |
2229 | |
|
2230 | |
@Override |
2231 | |
public void visitCatch(JCCatch tree) { |
2232 | 35 | JCVariableDecl param = translate(tree.param); |
2233 | 35 | JCBlock body = translate(tree.body); |
2234 | 35 | result = make.at(tree.pos).Catch(param, body); |
2235 | 35 | } |
2236 | |
|
2237 | |
@Override |
2238 | |
public void visitClassDef(JCClassDecl tree) { |
2239 | 0 | assert false : "should not be in JavaFX AST"; |
2240 | 0 | } |
2241 | |
|
2242 | |
|
2243 | |
|
2244 | |
|
2245 | |
|
2246 | |
|
2247 | |
|
2248 | |
|
2249 | |
|
2250 | |
|
2251 | |
|
2252 | |
|
2253 | |
|
2254 | |
|
2255 | |
|
2256 | |
|
2257 | |
|
2258 | |
|
2259 | |
@Override |
2260 | |
public void visitForExpression(JFXForExpression tree) { |
2261 | |
|
2262 | 169 | if (yield == Yield.ToExecStatement) { |
2263 | 115 | result = wrapWithInClause(tree, translateExpressionToStatement(tree.getBodyExpression())); |
2264 | |
} else { |
2265 | |
|
2266 | 54 | assert tree.type != syms.voidType : "should be handled above"; |
2267 | 54 | DiagnosticPosition diagPos = tree.pos(); |
2268 | 54 | ListBuffer<JCStatement> stmts = ListBuffer.lb(); |
2269 | |
JCStatement stmt; |
2270 | |
JCExpression value; |
2271 | |
|
2272 | |
|
2273 | 54 | assert tree.type.getTypeArguments().size() == 1; |
2274 | 54 | Type elemType = elementType(tree.type); |
2275 | |
|
2276 | 54 | UseSequenceBuilder builder = useSequenceBuilder(diagPos, elemType); |
2277 | 54 | stmts.append(builder.makeBuilderVar()); |
2278 | |
|
2279 | |
|
2280 | 54 | stmt = builder.makeAdd( tree.getBodyExpression() ); |
2281 | |
|
2282 | |
|
2283 | 54 | value = builder.makeToSequence(); |
2284 | 54 | stmt = wrapWithInClause(tree, stmt); |
2285 | 54 | stmts.append(stmt); |
2286 | |
|
2287 | 54 | if (yield == Yield.ToExpression) { |
2288 | |
|
2289 | 51 | result = makeBlockExpression(diagPos, stmts, value); |
2290 | |
} else { |
2291 | 3 | stmts.append( make.at(tree).Return( value ) ); |
2292 | 3 | result = make.at(diagPos).Block(0L, stmts.toList()); |
2293 | |
} |
2294 | |
} |
2295 | 169 | } |
2296 | |
|
2297 | |
|
2298 | |
private JCStatement wrapWithInClause(JFXForExpression tree, JCStatement coreStmt) { |
2299 | 169 | JCStatement stmt = coreStmt; |
2300 | 344 | for (int inx = tree.getInClauses().size() - 1; inx >= 0; --inx) { |
2301 | 175 | JFXForExpressionInClause clause = (JFXForExpressionInClause)tree.getInClauses().get(inx); |
2302 | 175 | if (clause.getWhereExpression() != null) { |
2303 | 28 | stmt = make.at(clause).If( translate( clause.getWhereExpression() ), stmt, null); |
2304 | |
} |
2305 | |
|
2306 | |
|
2307 | |
|
2308 | |
|
2309 | |
|
2310 | |
|
2311 | |
|
2312 | |
|
2313 | |
|
2314 | |
|
2315 | |
|
2316 | |
|
2317 | 175 | JFXVar var = clause.getVar(); |
2318 | 175 | Name tmpVarName = getSyntheticName(var.getName().toString()); |
2319 | 175 | JCVariableDecl finalVar = make.VarDef( |
2320 | |
make.Modifiers(Flags.FINAL), |
2321 | |
var.getName(), |
2322 | |
makeTypeTree( var,var.type), |
2323 | |
make.Ident(tmpVarName)); |
2324 | |
Name tmpIndexVarName; |
2325 | 175 | if (clause.getIndexUsed()) { |
2326 | 20 | Name indexVarName = indexVarName(clause); |
2327 | 20 | tmpIndexVarName = getSyntheticName(indexVarName.toString()); |
2328 | 20 | JCVariableDecl finalIndexVar = make.VarDef( |
2329 | |
make.Modifiers(Flags.FINAL), |
2330 | |
indexVarName, |
2331 | |
makeTypeTree( var,syms.javafx_IntegerType), |
2332 | |
make.Unary(JCTree.POSTINC, make.Ident(tmpIndexVarName))); |
2333 | 20 | stmt = make.Block(0L, List.of(finalIndexVar, finalVar, stmt)); |
2334 | 20 | } |
2335 | |
else { |
2336 | 155 | tmpIndexVarName = null; |
2337 | 155 | stmt = make.Block(0L, List.of(finalVar, stmt)); |
2338 | |
} |
2339 | |
|
2340 | 175 | DiagnosticPosition diagPos = clause.seqExpr; |
2341 | 175 | if (types.isSequence(clause.seqExpr.type)) { |
2342 | |
|
2343 | |
|
2344 | |
|
2345 | 171 | JCExpression seq = callExpression(diagPos, |
2346 | |
makeQualifiedTree(diagPos, "com.sun.javafx.runtime.sequence.Sequences"), |
2347 | |
"forceNonNull", |
2348 | |
List.of(makeElementClassObject(diagPos, var.type), |
2349 | |
translate(clause.seqExpr))); |
2350 | 171 | stmt = make.at(clause).ForeachLoop( |
2351 | |
|
2352 | |
|
2353 | |
make.VarDef( |
2354 | |
make.Modifiers(0L), |
2355 | |
tmpVarName, |
2356 | |
makeTypeTree( var,var.type, true), |
2357 | |
null), |
2358 | |
seq, |
2359 | |
stmt); |
2360 | 171 | } else { |
2361 | |
|
2362 | |
|
2363 | 4 | if (! var.type.isPrimitive()) |
2364 | 3 | stmt = make.If(make.Binary(JCTree.NE, make.Ident(tmpVarName), |
2365 | |
make.Literal(TypeTags.BOT, null)), |
2366 | |
stmt, null); |
2367 | 4 | stmt = make.at(diagPos).Block(0, |
2368 | |
List.of(make.at(diagPos).VarDef( |
2369 | |
make.Modifiers(0L), |
2370 | |
tmpVarName, |
2371 | |
makeTypeTree( var,var.type, true), |
2372 | |
translate(clause.seqExpr)), |
2373 | |
stmt)); |
2374 | |
} |
2375 | 175 | if (clause.getIndexUsed()) { |
2376 | 20 | JCVariableDecl tmpIndexVar = |
2377 | |
make.VarDef( |
2378 | |
make.Modifiers(0L), |
2379 | |
tmpIndexVarName, |
2380 | |
makeTypeTree( var,syms.javafx_IntegerType), |
2381 | |
make.Literal(Integer.valueOf(0))); |
2382 | 20 | stmt = make.Block(0L, List.of(tmpIndexVar, stmt)); |
2383 | |
} |
2384 | |
} |
2385 | 169 | return stmt; |
2386 | |
} |
2387 | |
|
2388 | |
public void visitIndexof(JFXIndexof that) { |
2389 | 21 | result = make.at(that.pos()).Ident(indexVarName(that.clause)); |
2390 | 21 | } |
2391 | |
|
2392 | |
@Override |
2393 | |
public void visitConditional(JCConditional tree) { |
2394 | 448 | final DiagnosticPosition diagPos = tree.pos(); |
2395 | 448 | JCExpression cond = translate(tree.getCondition()); |
2396 | 448 | JCExpression trueSide = tree.getTrueExpression(); |
2397 | 448 | JCExpression falseSide = tree.getFalseExpression(); |
2398 | 448 | if (yield == Yield.ToExpression) { |
2399 | |
JCExpression translatedFalseSide; |
2400 | 63 | if (falseSide == null) { |
2401 | 0 | Type trueSideType = tree.getTrueExpression().type; |
2402 | 0 | switch (trueSideType.tag) { |
2403 | |
case TypeTags.BOOLEAN: |
2404 | 0 | translatedFalseSide = make.at(diagPos).Literal(TypeTags.BOOLEAN, 0); |
2405 | 0 | break; |
2406 | |
case TypeTags.INT: |
2407 | 0 | translatedFalseSide = make.at(diagPos).Literal(TypeTags.INT, 0); |
2408 | 0 | break; |
2409 | |
case TypeTags.DOUBLE: |
2410 | 0 | translatedFalseSide = make.at(diagPos).Literal(TypeTags.DOUBLE, 0.0); |
2411 | 0 | break; |
2412 | |
case TypeTags.BOT: |
2413 | 0 | translatedFalseSide = make.at(diagPos).Literal(TypeTags.BOT, null); |
2414 | 0 | break; |
2415 | |
case TypeTags.VOID: |
2416 | 0 | assert false : "should have been translated"; |
2417 | 0 | translatedFalseSide = make.at(diagPos).Literal(TypeTags.BOT, null); |
2418 | 0 | break; |
2419 | |
case TypeTags.CLASS: |
2420 | 0 | if (trueSideType == syms.stringType) { |
2421 | 0 | translatedFalseSide = make.at(diagPos).Literal(TypeTags.CLASS, ""); |
2422 | |
} else { |
2423 | 0 | translatedFalseSide = make.at(diagPos).Literal(TypeTags.BOT, null); |
2424 | |
} |
2425 | 0 | break; |
2426 | |
default: |
2427 | 0 | assert false : "what is this type doing here? " + trueSideType; |
2428 | 0 | translatedFalseSide = make.at(diagPos).Literal(TypeTags.BOT, null); |
2429 | |
break; |
2430 | |
} |
2431 | 0 | } else { |
2432 | 63 | translatedFalseSide = translate(falseSide); |
2433 | |
} |
2434 | 63 | JCExpression translatedTrueSide = convertTranslated(translate(trueSide), trueSide, trueSide.type, tree.type); |
2435 | 63 | translatedFalseSide = convertTranslated(translatedFalseSide, falseSide, falseSide.type, tree.type); |
2436 | 63 | result = make.at(diagPos).Conditional(cond, translatedTrueSide, translatedFalseSide); |
2437 | 63 | } else { |
2438 | 385 | result = make.at(diagPos).If(cond, |
2439 | |
translateExpressionToStatement(trueSide), |
2440 | |
falseSide == null ? null : translateExpressionToStatement(falseSide)); |
2441 | |
} |
2442 | 448 | } |
2443 | |
|
2444 | |
@Override |
2445 | |
public void visitContinue(JCContinue tree) { |
2446 | 3 | result = make.at(tree.pos).Continue(tree.label); |
2447 | 3 | } |
2448 | |
|
2449 | |
@Override |
2450 | |
public void visitDoLoop(JCDoWhileLoop tree) { |
2451 | 0 | assert false : "should not be in JavaFX AST"; |
2452 | 0 | } |
2453 | |
|
2454 | |
@Override |
2455 | |
public void visitErroneous(JCErroneous tree) { |
2456 | 0 | List<? extends JCTree> errs = translate(tree.errs); |
2457 | 0 | result = make.at(tree.pos).Erroneous(errs); |
2458 | 0 | } |
2459 | |
|
2460 | |
@Override |
2461 | |
public void visitReturn(JCReturn tree) { |
2462 | 10 | JCExpression exp = tree.getExpression(); |
2463 | 10 | if (exp == null) { |
2464 | 1 | result = make.at(tree).Return(null); |
2465 | |
} else { |
2466 | 9 | result = translateExpressionToStatement(exp, tree.type); |
2467 | |
} |
2468 | 10 | } |
2469 | |
|
2470 | |
@Override |
2471 | |
public void visitExec(JCExpressionStatement tree) { |
2472 | 3066 | result = translateExpressionToStatement(tree.getExpression(), syms.voidType); |
2473 | 3066 | } |
2474 | |
|
2475 | |
@Override |
2476 | |
public void visitParens(JCParens tree) { |
2477 | 0 | if (yield == Yield.ToExpression) { |
2478 | 0 | JCExpression expr = translate(tree.expr); |
2479 | 0 | result = make.at(tree.pos).Parens(expr); |
2480 | 0 | } else { |
2481 | 0 | result = translateExpressionToStatement(tree.expr); |
2482 | |
} |
2483 | 0 | } |
2484 | |
|
2485 | |
@Override |
2486 | |
public void visitForeachLoop(JCEnhancedForLoop tree) { |
2487 | 0 | assert false : "should not be in JavaFX AST"; |
2488 | 0 | } |
2489 | |
|
2490 | |
@Override |
2491 | |
public void visitForLoop(JCForLoop tree) { |
2492 | 0 | assert false : "should not be in JavaFX AST"; |
2493 | 0 | } |
2494 | |
|
2495 | |
@Override |
2496 | |
public void visitIf(JCIf tree) { |
2497 | 0 | assert false : "should not be in JavaFX AST"; |
2498 | 0 | } |
2499 | |
|
2500 | |
@Override |
2501 | |
public void visitImport(JCImport tree) { |
2502 | 0 | JCTree qualid = translate(tree.qualid); |
2503 | 0 | result = make.at(tree.pos).Import(qualid, tree.staticImport); |
2504 | 0 | } |
2505 | |
|
2506 | |
@Override |
2507 | |
public void visitIndexed(JCArrayAccess tree) { |
2508 | 0 | assert false : "should not be in JavaFX AST"; |
2509 | 0 | } |
2510 | |
|
2511 | |
@Override |
2512 | |
public void visitTypeTest(JCInstanceOf tree) { |
2513 | 30 | JCTree clazz = this.makeTypeTree( tree,tree.clazz.type); |
2514 | 30 | JCExpression expr = translate(tree.expr); |
2515 | 30 | if (types.isSequence(tree.expr.type) && ! types.isSequence(tree.clazz.type)) |
2516 | 2 | expr = callExpression(tree.expr, |
2517 | |
makeQualifiedTree(tree.expr, "com.sun.javafx.runtime.sequence.Sequences"), |
2518 | |
"getSingleValue", expr); |
2519 | 30 | result = make.at(tree.pos).TypeTest(expr, clazz); |
2520 | 30 | } |
2521 | |
|
2522 | 0 | abstract static class TypeCastTranslator extends Translator { |
2523 | |
|
2524 | |
protected final JCTypeCast tree; |
2525 | |
|
2526 | |
TypeCastTranslator(final JCTypeCast tree, JavafxToJava toJava) { |
2527 | 121 | super(tree.pos(), toJava); |
2528 | 121 | this.tree = tree; |
2529 | 121 | } |
2530 | |
|
2531 | |
abstract protected JCExpression translatedExpr(); |
2532 | |
|
2533 | |
protected JCExpression doit() { |
2534 | 121 | Type clazztype = tree.clazz.type; |
2535 | 121 | if (clazztype.isPrimitive() && !tree.expr.type.isPrimitive()) { |
2536 | 11 | clazztype = types.boxedClass(clazztype).type; |
2537 | |
} |
2538 | 121 | JCTree clazz = makeExpression(clazztype); |
2539 | 121 | return m().TypeCast(clazz, translatedExpr()); |
2540 | |
} |
2541 | |
} |
2542 | |
|
2543 | |
@Override |
2544 | |
public void visitTypeCast(final JCTypeCast tree) { |
2545 | 115 | result = new TypeCastTranslator(tree, this) { |
2546 | |
protected JCExpression translatedExpr() { |
2547 | 115 | return translate(tree.expr); |
2548 | |
} |
2549 | |
}.doit(); |
2550 | 115 | } |
2551 | |
|
2552 | |
@Override |
2553 | |
public void visitLabelled(JCLabeledStatement tree) { |
2554 | 0 | assert false : "should not be in JavaFX AST"; |
2555 | 0 | } |
2556 | |
|
2557 | |
@Override |
2558 | |
public void visitLiteral(JCLiteral tree) { |
2559 | 4900 | if (tree.typetag == TypeTags.BOT && types.isSequence(tree.type)) { |
2560 | 6 | Type elemType = elementType(tree.type); |
2561 | 6 | result = makeEmptySequenceCreator(tree.pos(), elemType); |
2562 | 6 | } |
2563 | |
else |
2564 | 4894 | result = make.at(tree.pos).Literal(tree.typetag, tree.value); |
2565 | 4900 | } |
2566 | |
|
2567 | |
@Override |
2568 | |
public void visitMethodDef(JCMethodDecl tree) { |
2569 | 0 | assert false : "should not be in JavaFX AST"; |
2570 | 0 | } |
2571 | |
|
2572 | |
abstract static class FunctionCallTranslator extends Translator { |
2573 | |
|
2574 | |
protected final JCExpression meth; |
2575 | |
protected final JCExpression selector; |
2576 | |
protected final MethodSymbol msym; |
2577 | |
protected final boolean renameToSuper; |
2578 | |
protected final boolean superToStatic; |
2579 | |
protected final List<Type> formals; |
2580 | |
protected final boolean usesVarArgs; |
2581 | |
protected final boolean useInvoke; |
2582 | |
protected final boolean selectorMutable; |
2583 | |
protected final boolean callBound; |
2584 | |
|
2585 | |
FunctionCallTranslator(final JCMethodInvocation tree, JavafxToJava toJava) { |
2586 | 3289 | super(tree.pos(), toJava); |
2587 | 3289 | meth = tree.meth; |
2588 | 3289 | JCFieldAccess fieldAccess = meth.getTag() == JavafxTag.SELECT ? (JCFieldAccess) meth : null; |
2589 | 3289 | selector = fieldAccess != null ? fieldAccess.getExpression() : null; |
2590 | 3289 | Symbol sym = toJava.expressionSymbol(meth); |
2591 | 3289 | msym = (sym instanceof MethodSymbol) ? (MethodSymbol) sym : null; |
2592 | 3289 | Name selectorIdName = (selector != null && selector.getTag() == JavafxTag.IDENT) ? ((JCIdent) selector).getName() : null; |
2593 | 3289 | boolean thisCall = selectorIdName == toJava.names._this; |
2594 | 3289 | boolean superCall = selectorIdName == toJava.names._super; |
2595 | 3289 | ClassSymbol csym = toJava.attrEnv.enclClass.sym; |
2596 | |
|
2597 | 3289 | boolean namedSuperCall = |
2598 | |
selector != null && msym != null && !msym.isStatic() && |
2599 | |
toJava.expressionSymbol(selector) instanceof ClassSymbol && |
2600 | |
|
2601 | |
types.isSuperType(toJava.expressionSymbol(selector).type, csym); |
2602 | 3289 | renameToSuper = namedSuperCall && !types.isCompoundClass(csym); |
2603 | 3289 | superToStatic = (superCall || namedSuperCall) && !renameToSuper; |
2604 | 3289 | formals = meth.type.getParameterTypes(); |
2605 | |
|
2606 | 3289 | usesVarArgs = tree.args != null && msym != null && |
2607 | |
(msym.flags() & VARARGS) != 0 && |
2608 | |
(formals.size() != tree.args.size() || |
2609 | |
types.isConvertible(tree.args.last().type, |
2610 | |
types.elemtype(formals.last()))); |
2611 | |
|
2612 | 3289 | useInvoke = meth.type instanceof FunctionType; |
2613 | 3289 | selectorMutable = msym != null && |
2614 | |
!sym.isStatic() && selector != null && !superCall && !namedSuperCall && |
2615 | |
!thisCall && !renameToSuper; |
2616 | 3289 | callBound = msym != null && !useInvoke && |
2617 | |
((msym.flags() & JavafxFlags.BOUND) != 0); |
2618 | 3289 | } |
2619 | |
} |
2620 | |
|
2621 | |
|
2622 | |
private boolean isJavaLangObjectType(Type type) { |
2623 | 0 | return type.toString().equals("java.lang.Object"); |
2624 | |
} |
2625 | |
|
2626 | |
|
2627 | |
@Override |
2628 | |
public void visitApply(final JCMethodInvocation tree) { |
2629 | 3191 | result = (new FunctionCallTranslator( tree, this ) { |
2630 | |
|
2631 | 3191 | private final boolean hasSideEffects = selectorMutable && hasSideEffects(selector); |
2632 | |
|
2633 | |
public JCTree doit() { |
2634 | 3191 | JCVariableDecl selectorVar = null; |
2635 | |
JCExpression transMeth; |
2636 | 3191 | if (renameToSuper) { |
2637 | 2 | transMeth = make.at(selector).Select(make.Select(makeTypeTree( selector,currentClass.sym.type, false), names._super), msym); |
2638 | |
} else { |
2639 | 3189 | transMeth = translate(meth); |
2640 | 3189 | if (hasSideEffects && !selector.type.isPrimitive() && transMeth.getTag() == JavafxTag.SELECT) { |
2641 | |
|
2642 | 41 | JCFieldAccess transMethFA = (JCFieldAccess) transMeth; |
2643 | 41 | selectorVar = makeTmpVar(diagPos, "select", selector.type, transMethFA.getExpression()); |
2644 | 41 | transMeth = m().Select(m().Ident(selectorVar.name), transMethFA.name); |
2645 | |
} |
2646 | |
} |
2647 | |
|
2648 | |
|
2649 | |
|
2650 | 3191 | if (superToStatic) { |
2651 | 11 | Name name = functionName(msym, superToStatic, callBound); |
2652 | 11 | if (transMeth.getTag() == JavafxTag.IDENT) { |
2653 | 0 | transMeth = m().Ident(name); |
2654 | 11 | } else if (transMeth.getTag() == JavafxTag.SELECT) { |
2655 | 11 | transMeth = m().Select(makeTypeTree(diagPos, msym.owner.type, false), name); |
2656 | |
} |
2657 | 11 | } else |
2658 | 3180 | if (callBound && ! renameToSuper) { |
2659 | 19 | Name name = functionName(msym, superToStatic, callBound); |
2660 | 19 | if (transMeth.getTag() == JavafxTag.IDENT) { |
2661 | 0 | transMeth = m().Ident(name); |
2662 | 19 | } else if (transMeth.getTag() == JavafxTag.SELECT) { |
2663 | 19 | JCFieldAccess faccess = (JCFieldAccess) transMeth; |
2664 | 19 | transMeth = m().Select(faccess.getExpression(), name); |
2665 | |
} |
2666 | |
} |
2667 | 3191 | if (useInvoke) { |
2668 | 40 | transMeth = make.Select(transMeth, defs.invokeName); |
2669 | |
} |
2670 | |
|
2671 | 3191 | JCMethodInvocation app = m().Apply( translate(tree.typeargs), transMeth, determineArgs()); |
2672 | 3191 | JCExpression fresult = app; |
2673 | 3191 | if (callBound) { |
2674 | 19 | fresult = makeBoundCall(app); |
2675 | |
} |
2676 | 3191 | if (useInvoke) { |
2677 | 40 | if (tree.type.tag != TypeTags.VOID) { |
2678 | 26 | fresult = castFromObject(fresult, tree.type); |
2679 | |
} |
2680 | |
} |
2681 | |
|
2682 | |
|
2683 | |
|
2684 | 3191 | if (wrap == Wrapped.InLocation && !callBound && msym != null) { |
2685 | 0 | TypeMorphInfo returnTypeInfo = typeMorpher.typeMorphInfo(msym.getReturnType()); |
2686 | 0 | fresult = makeUnboundLocation(diagPos, returnTypeInfo, fresult); |
2687 | |
} |
2688 | 3191 | if (selectorMutable && !selector.type.isPrimitive()) { |
2689 | 2113 | JCExpression toTest = hasSideEffects? |
2690 | |
m().Ident(selectorVar.name) : |
2691 | |
translate(selector); |
2692 | |
|
2693 | 2113 | JCExpression cond = m().Binary(JCTree.NE, toTest, make.Literal(TypeTags.BOT, null)); |
2694 | 2113 | if (msym.getReturnType() == syms.voidType) { |
2695 | |
|
2696 | 1750 | JCStatement stmt = make.If(cond, make.Exec(fresult), null); |
2697 | 1750 | assert yield == Yield.ToExecStatement : "Yield from a void call should always be a statement"; |
2698 | |
|
2699 | 1750 | if (hasSideEffects) { |
2700 | |
|
2701 | |
|
2702 | 7 | return m().Block(0L, List.<JCStatement>of(selectorVar, stmt)); |
2703 | |
} else { |
2704 | 1743 | return stmt; |
2705 | |
} |
2706 | |
} else { |
2707 | |
|
2708 | |
|
2709 | 363 | TypeMorphInfo returnTypeInfo = typeMorpher.typeMorphInfo(msym.getReturnType()); |
2710 | 363 | JCExpression defaultExpr = makeDefaultValue(diagPos, returnTypeInfo); |
2711 | 363 | if (wrap == Wrapped.InLocation) { |
2712 | 0 | defaultExpr = makeUnboundLocation(diagPos, returnTypeInfo, defaultExpr); |
2713 | |
} |
2714 | 363 | fresult = m().Conditional(cond, fresult, defaultExpr); |
2715 | 363 | if (hasSideEffects) { |
2716 | |
|
2717 | |
|
2718 | 34 | fresult = fxmake.at(diagPos).BlockExpression(0L, List.<JCStatement>of(selectorVar), fresult); |
2719 | |
} |
2720 | |
} |
2721 | |
} |
2722 | 1441 | return fresult; |
2723 | |
} |
2724 | |
|
2725 | |
|
2726 | |
|
2727 | |
|
2728 | |
|
2729 | |
List<JCExpression> determineArgs() { |
2730 | |
List<JCExpression> args; |
2731 | 3191 | if (callBound) { |
2732 | 19 | ListBuffer<JCExpression> targs = ListBuffer.lb(); |
2733 | 19 | List<Type> formal = formals; |
2734 | 19 | for (JCExpression arg : tree.args) { |
2735 | 0 | switch (arg.getTag()) { |
2736 | |
case JavafxTag.IDENT: |
2737 | |
case JavafxTag.SELECT: |
2738 | |
case JavafxTag.APPLY: |
2739 | |
|
2740 | |
|
2741 | |
|
2742 | |
|
2743 | |
|
2744 | |
|
2745 | |
|
2746 | 0 | if (arg.type.equals(formal.head) || |
2747 | |
types.isSequence(formal.head) || |
2748 | |
isJavaLangObjectType(formal.head) |
2749 | |
) { |
2750 | 0 | targs.append(translate(arg, Wrapped.InLocation)); |
2751 | 0 | break; |
2752 | |
} |
2753 | |
|
2754 | |
|
2755 | |
|
2756 | |
|
2757 | |
default: |
2758 | |
{ |
2759 | 0 | targs.append(makeUnboundLocation( |
2760 | |
arg.pos(), |
2761 | |
typeMorpher.typeMorphInfo(formal.head), |
2762 | |
translate(arg, arg.type))); |
2763 | |
} |
2764 | |
} |
2765 | 0 | formal = formal.tail; |
2766 | |
} |
2767 | 19 | args = targs.toList(); |
2768 | 19 | } else { |
2769 | 3172 | ListBuffer<JCExpression> translated = ListBuffer.lb(); |
2770 | 3172 | boolean handlingVarargs = false; |
2771 | 3172 | Type formal = null; |
2772 | 3172 | List<Type> t = formals; |
2773 | 6645 | for (List<JCExpression> l = tree.args; l.nonEmpty(); l = l.tail) { |
2774 | 3473 | if (! handlingVarargs) { |
2775 | 3470 | formal = t.head; |
2776 | 3470 | t = t.tail; |
2777 | 3470 | if (usesVarArgs && t.isEmpty()) { |
2778 | 1 | formal = types.elemtype(formal); |
2779 | 1 | handlingVarargs = true; |
2780 | |
} |
2781 | |
} |
2782 | 3473 | translated.append( translate(l.head, formal) ); |
2783 | |
} |
2784 | 3172 | args = translated.toList(); |
2785 | |
} |
2786 | |
|
2787 | |
|
2788 | |
|
2789 | 3191 | if (superToStatic) { |
2790 | 11 | args = args.prepend(make.Ident(defs.receiverName)); |
2791 | |
} |
2792 | |
|
2793 | 3191 | return args; |
2794 | |
} |
2795 | |
|
2796 | |
|
2797 | |
JCExpression makeBoundCall(JCExpression applyExpression) { |
2798 | 19 | JavafxTypeMorpher.TypeMorphInfo tmi = typeMorpher.typeMorphInfo(msym.getReturnType()); |
2799 | 19 | return wrap == Wrapped.InLocation ? applyExpression : callExpression(diagPos, |
2800 | |
m().Parens(applyExpression), |
2801 | |
defs.locationGetMethodName[tmi.getTypeKind()]); |
2802 | |
} |
2803 | |
|
2804 | |
}).doit(); |
2805 | 3191 | } |
2806 | |
|
2807 | |
@Override |
2808 | |
public void visitModifiers(JCModifiers tree) { |
2809 | 0 | List<JCAnnotation> annotations = translate(tree.annotations); |
2810 | 0 | result = make.at(tree.pos).Modifiers(tree.flags, annotations); |
2811 | 0 | } |
2812 | |
|
2813 | |
@Override |
2814 | |
public void visitNewArray(JCNewArray tree) { |
2815 | 0 | assert false : "should not be in JavaFX AST"; |
2816 | 0 | } |
2817 | |
|
2818 | |
@Override |
2819 | |
public void visitNewClass(JCNewClass tree) { |
2820 | 0 | assert false : "should not be in JavaFX AST"; |
2821 | 0 | } |
2822 | |
|
2823 | |
@Override |
2824 | |
public void visitSkip(JCSkip tree) { |
2825 | 0 | result = make.at(tree.pos).Skip(); |
2826 | 0 | } |
2827 | |
|
2828 | |
@Override |
2829 | |
public void visitSwitch(JCSwitch tree) { |
2830 | 0 | assert false : "should not be in JavaFX AST"; |
2831 | 0 | } |
2832 | |
|
2833 | |
@Override |
2834 | |
public void visitSynchronized(JCSynchronized tree) { |
2835 | 0 | assert false : "should not be in JavaFX AST"; |
2836 | 0 | } |
2837 | |
|
2838 | |
@Override |
2839 | |
public void visitThrow(JCThrow tree) { |
2840 | 24 | JCTree expr = translate(tree.expr); |
2841 | 24 | result = make.at(tree.pos).Throw(expr); |
2842 | 24 | } |
2843 | |
|
2844 | |
@Override |
2845 | |
public void visitTry(JCTry tree) { |
2846 | 24 | JCBlock body = translate(tree.body); |
2847 | 24 | List<JCCatch> catchers = translate(tree.catchers); |
2848 | 24 | JCBlock finalizer = translate(tree.finalizer); |
2849 | 24 | result = make.at(tree.pos).Try(body, catchers, finalizer); |
2850 | 24 | } |
2851 | |
|
2852 | |
@Override |
2853 | |
public void visitTypeApply(JCTypeApply tree) { |
2854 | 0 | JCExpression clazz = translate(tree.clazz); |
2855 | 0 | List<JCExpression> arguments = translate(tree.arguments); |
2856 | 0 | result = make.at(tree.pos).TypeApply(clazz, arguments); |
2857 | 0 | } |
2858 | |
|
2859 | |
@Override |
2860 | |
public void visitTypeArray(JCArrayTypeTree tree) { |
2861 | 0 | assert false : "should not be in JavaFX AST"; |
2862 | 0 | } |
2863 | |
|
2864 | |
@Override |
2865 | |
public void visitTypeBoundKind(TypeBoundKind tree) { |
2866 | 0 | assert false : "should not be in JavaFX AST"; |
2867 | 0 | } |
2868 | |
|
2869 | |
@Override |
2870 | |
public void visitTypeIdent(JCPrimitiveTypeTree tree) { |
2871 | 0 | result = make.at(tree.pos).TypeIdent(tree.typetag); |
2872 | 0 | } |
2873 | |
|
2874 | |
@Override |
2875 | |
public void visitTypeParameter(JCTypeParameter tree) { |
2876 | 0 | List<JCExpression> bounds = translate(tree.bounds); |
2877 | 0 | result = make.at(tree.pos).TypeParameter(tree.name, bounds); |
2878 | 0 | } |
2879 | |
|
2880 | |
@Override |
2881 | |
public void visitUnary(final JCUnary tree) { |
2882 | 696 | result = (new Translator( tree.pos(), this ) { |
2883 | |
|
2884 | 696 | private final JCExpression expr = tree.getExpression(); |
2885 | 696 | private final JCExpression transExpr = translate(expr); |
2886 | |
|
2887 | |
private JCExpression doVanilla() { |
2888 | 209 | return m().Unary(tree.getTag(), transExpr); |
2889 | |
} |
2890 | |
|
2891 | |
private JCExpression callSetMethod(JCExpression target, List<JCExpression> args) { |
2892 | 219 | JCExpression transTarget = translate(target, Wrapped.InLocation); |
2893 | 219 | JCFieldAccess setSelect = m().Select(transTarget, |
2894 | |
args.size() == 1 |
2895 | |
? defs.locationSetMethodName[typeMorpher.typeMorphInfo(target.type).getTypeKind()] |
2896 | |
: defs.setMethodName); |
2897 | 219 | return m().Apply(null, setSelect, args); |
2898 | |
} |
2899 | |
|
2900 | |
private JCExpression doIncDec(int binaryOp, boolean postfix) { |
2901 | 254 | final Symbol sym = expressionSymbol(expr); |
2902 | 254 | final VarSymbol vsym = (sym != null && (sym instanceof VarSymbol)) ? (VarSymbol) sym : null; |
2903 | 254 | final JCExpression one = m().Literal(1); |
2904 | 254 | final JCExpression combined = m().Binary(binaryOp, transExpr, one); |
2905 | |
JCExpression ret; |
2906 | |
|
2907 | 254 | if (expr.getTag() == JavafxTag.SEQUENCE_INDEXED) { |
2908 | |
|
2909 | 4 | JFXSequenceIndexed si = (JFXSequenceIndexed) expr; |
2910 | 4 | JCExpression index = translate(si.getIndex()); |
2911 | 4 | ret = callSetMethod( si.getSequence(), List.of(index, combined) ); |
2912 | 4 | } else if (shouldMorph(vsym)) { |
2913 | |
|
2914 | 215 | ret = callSetMethod( expr, List.of(combined) ); |
2915 | |
} else { |
2916 | |
|
2917 | 35 | return doVanilla(); |
2918 | |
} |
2919 | 219 | if (postfix) { |
2920 | |
|
2921 | 212 | return m().Binary(binaryOp, ret, m().Literal(-1)); |
2922 | |
} else { |
2923 | |
|
2924 | 7 | return ret; |
2925 | |
} |
2926 | |
} |
2927 | |
|
2928 | |
public JCTree doit() { |
2929 | 696 | switch (tree.getTag()) { |
2930 | |
case JavafxTag.SIZEOF: |
2931 | 201 | return callExpression(diagPos, |
2932 | |
makeQualifiedTree(diagPos, "com.sun.javafx.runtime.sequence.Sequences"), |
2933 | |
defs.sizeMethodName, transExpr); |
2934 | |
case JavafxTag.REVERSE: |
2935 | 67 | return callExpression(diagPos, |
2936 | |
makeQualifiedTree(diagPos, "com.sun.javafx.runtime.sequence.Sequences"), |
2937 | |
"reverse", transExpr); |
2938 | |
case JCTree.PREINC: |
2939 | 10 | return doIncDec(JCTree.PLUS, false); |
2940 | |
case JCTree.PREDEC: |
2941 | 4 | return doIncDec(JCTree.MINUS, false); |
2942 | |
case JCTree.POSTINC: |
2943 | 234 | return doIncDec(JCTree.PLUS, true); |
2944 | |
case JCTree.POSTDEC: |
2945 | 6 | return doIncDec(JCTree.MINUS, true); |
2946 | |
case JCTree.NEG: |
2947 | 140 | if (types.isSameType(tree.type, syms.javafx_DurationType)) { |
2948 | 0 | return m().Apply(null, |
2949 | |
m().Select(translate(tree.arg), Name.fromString(names, "negate")), List.<JCExpression>nil()); |
2950 | |
} |
2951 | |
default: |
2952 | 174 | return doVanilla(); |
2953 | |
} |
2954 | |
} |
2955 | |
}).doit(); |
2956 | 696 | } |
2957 | |
|
2958 | |
|
2959 | |
@Override |
2960 | |
public void visitVarDef(JCVariableDecl tree) { |
2961 | 0 | assert false : "should not be in JavaFX AST"; |
2962 | 0 | } |
2963 | |
|
2964 | |
@Override |
2965 | |
public void visitWhileLoop(JCWhileLoop tree) { |
2966 | 11 | JCStatement body = translate(tree.body); |
2967 | 11 | JCExpression cond = translate(tree.cond); |
2968 | 11 | result = make.at(tree.pos).WhileLoop(cond, body); |
2969 | 11 | } |
2970 | |
|
2971 | |
@Override |
2972 | |
public void visitWildcard(JCWildcard tree) { |
2973 | 0 | TypeBoundKind kind = make.at(tree.kind.pos).TypeBoundKind(tree.kind.kind); |
2974 | 0 | JCTree inner = translate(tree.inner); |
2975 | 0 | result = make.at(tree.pos).Wildcard(kind, inner); |
2976 | 0 | } |
2977 | |
|
2978 | |
@Override |
2979 | |
public void visitLetExpr(LetExpr tree) { |
2980 | 0 | assert false : "should not be in JavaFX AST"; |
2981 | 0 | } |
2982 | |
|
2983 | |
@Override |
2984 | |
public void visitTree(JCTree tree) { |
2985 | 0 | assert false : "should not be in JavaFX AST"; |
2986 | 0 | } |
2987 | |
|
2988 | |
|
2989 | |
|
2990 | |
public void visitSetAttributeToObjectBeingInitialized(JFXSetAttributeToObjectBeingInitialized that) { |
2991 | 0 | assert false : "yeah, right"; |
2992 | 0 | } |
2993 | |
|
2994 | |
public void visitObjectLiteralPart(JFXObjectLiteralPart that) { |
2995 | 0 | assert false : "should be processed by parent tree"; |
2996 | 0 | } |
2997 | |
|
2998 | |
public void visitTypeAny(JFXTypeAny that) { |
2999 | 0 | assert false : "should be processed by parent tree"; |
3000 | 0 | } |
3001 | |
|
3002 | |
public void visitTypeClass(JFXTypeClass that) { |
3003 | 0 | assert false : "should be processed by parent tree"; |
3004 | 0 | } |
3005 | |
|
3006 | |
public void visitTypeFunctional(JFXTypeFunctional that) { |
3007 | 0 | assert false : "should be processed by parent tree"; |
3008 | 0 | } |
3009 | |
|
3010 | |
public void visitTypeUnknown(JFXTypeUnknown that) { |
3011 | 0 | assert false : "should be processed by parent tree"; |
3012 | 0 | } |
3013 | |
|
3014 | |
public void visitForExpressionInClause(JFXForExpressionInClause that) { |
3015 | 0 | assert false : "should be processed by parent tree"; |
3016 | 0 | } |
3017 | |
|
3018 | |
|
3019 | |
|
3020 | |
|
3021 | |
|
3022 | |
|
3023 | |
|
3024 | |
private JCBlock runMethodBody(JFXBlockExpression bexpr) { |
3025 | 340 | DiagnosticPosition diagPos = bexpr.pos(); |
3026 | 340 | List<JCStatement> stats = translateStatements(bexpr.stats); |
3027 | 340 | boolean nullReturnNeeded = true; |
3028 | 340 | if (bexpr.value != null) { |
3029 | 224 | Type valueType = bexpr.value.type; |
3030 | 224 | if (valueType == syms.voidType) { |
3031 | |
|
3032 | 187 | stats = stats.append( translateExpressionToStatement(bexpr.value, valueType) ); |
3033 | |
} else { |
3034 | |
|
3035 | |
|
3036 | 37 | if (valueType.isPrimitive()) { |
3037 | 10 | JCExpression boxedExpr = makeBox(diagPos, translate(bexpr.value), valueType); |
3038 | 10 | stats = stats.append( make.Return( boxedExpr ) ); |
3039 | 10 | } else { |
3040 | 27 | stats = stats.append( translateExpressionToStatement(bexpr.value, valueType) ); |
3041 | |
} |
3042 | 37 | nullReturnNeeded = false; |
3043 | |
} |
3044 | |
} |
3045 | 340 | if (nullReturnNeeded) { |
3046 | 303 | stats = stats.append( make.Return(make.Literal(TypeTags.BOT, null)) ); |
3047 | |
} |
3048 | 340 | return make.at(diagPos).Block(0L, stats); |
3049 | |
} |
3050 | |
|
3051 | |
protected String getSyntheticPrefix() { |
3052 | 1288 | return "jfx$"; |
3053 | |
} |
3054 | |
|
3055 | |
boolean shouldMorph(VarSymbol vsym) { |
3056 | 1152 | if (vsym == null) { |
3057 | 0 | return false; |
3058 | |
} |
3059 | 1152 | VarMorphInfo vmi = typeMorpher.varMorphInfo(vsym); |
3060 | 1152 | return shouldMorph(vmi); |
3061 | |
} |
3062 | |
|
3063 | |
boolean shouldMorph(VarMorphInfo vmi) { |
3064 | 18628 | if ( vmi.mustMorph() ) |
3065 | 7541 | return true; |
3066 | |
else |
3067 | 11087 | return locallyBound != null ? locallyBound.contains(vmi.getSymbol()) : false; |
3068 | |
} |
3069 | |
|
3070 | |
JCExpression convertVariableReference(DiagnosticPosition diagPos, |
3071 | |
JCExpression varRef, Symbol sym, |
3072 | |
boolean wantLocation) { |
3073 | |
|
3074 | 19089 | JCExpression expr = varRef; |
3075 | |
|
3076 | 19089 | boolean staticReference = sym.isStatic(); |
3077 | 19089 | if (sym instanceof VarSymbol) { |
3078 | 12038 | VarSymbol vsym = (VarSymbol) sym; |
3079 | 12038 | VarMorphInfo vmi = typeMorpher.varMorphInfo(vsym); |
3080 | 12038 | if (shouldMorph(vmi)) { |
3081 | 4601 | if (sym.owner.kind == Kinds.TYP && !staticReference) { |
3082 | |
|
3083 | 2209 | assert varRef.getTag() == JCTree.SELECT : "attribute must be accessed through receiver"; |
3084 | 2209 | JCFieldAccess select = (JCFieldAccess) varRef; |
3085 | 2209 | Name attrAccessName = names.fromString(attributeGetMethodNamePrefix + select.name.toString()); |
3086 | 2209 | select = make.at(diagPos).Select(select.getExpression(), attrAccessName); |
3087 | 2209 | List<JCExpression> emptyArgs = List.nil(); |
3088 | 2209 | expr = make.at(diagPos).Apply(null, select, emptyArgs); |
3089 | |
} |
3090 | |
|
3091 | 4601 | if (wantLocation) { |
3092 | |
|
3093 | |
} else { |
3094 | |
|
3095 | 2621 | JCFieldAccess getSelect = make.Select(expr, defs.locationGetMethodName[vmi.getTypeKind()]); |
3096 | 2621 | List<JCExpression> getArgs = List.nil(); |
3097 | 2621 | expr = make.at(diagPos).Apply(null, getSelect, getArgs); |
3098 | 2621 | } |
3099 | |
} else { |
3100 | |
|
3101 | 7437 | if (wantLocation) { |
3102 | 88 | expr = makeUnboundLocation(diagPos, vmi, expr); |
3103 | |
} |
3104 | |
} |
3105 | 12038 | } else if (sym instanceof MethodSymbol) { |
3106 | 3210 | if (staticReference) { |
3107 | 785 | Name name = functionName((MethodSymbol)sym); |
3108 | 785 | if (expr.getTag() == JCTree.SELECT) { |
3109 | 785 | JCFieldAccess select = (JCFieldAccess) expr; |
3110 | 785 | expr = make.at(diagPos).Select(select.getExpression(), name); |
3111 | 785 | } else if (expr.getTag() == JCTree.IDENT) { |
3112 | 0 | expr = make.at(diagPos).Ident(name); |
3113 | |
} |
3114 | |
} |
3115 | |
} |
3116 | 19089 | return expr; |
3117 | |
} |
3118 | |
|
3119 | |
|
3120 | |
|
3121 | |
|
3122 | |
|
3123 | |
private JCExpression makeReceiver(DiagnosticPosition pos, Symbol treeSym, Symbol siteOwner) { |
3124 | 1999 | JCExpression ret = null; |
3125 | 1999 | if (treeSym != null && siteOwner != null) { |
3126 | |
|
3127 | 1999 | ret = make.Ident(defs.receiverName); |
3128 | 1999 | ret.type = siteOwner.type; |
3129 | |
|
3130 | |
|
3131 | 1999 | if (siteOwner != treeSym.owner) { |
3132 | 204 | Symbol siteCursor = siteOwner; |
3133 | 204 | boolean foundOwner = false; |
3134 | 204 | int numOfOuters = 0; |
3135 | |
ownerSearch: |
3136 | 256 | while (siteCursor.kind != Kinds.PCK) { |
3137 | 256 | ListBuffer<Type> supertypes = ListBuffer.lb(); |
3138 | 256 | Set<Type> superSet = new HashSet<Type>(); |
3139 | 256 | if (siteCursor.type != null) { |
3140 | 230 | supertypes.append(siteCursor.type); |
3141 | 230 | superSet.add(siteCursor.type); |
3142 | |
} |
3143 | |
|
3144 | 256 | if (siteCursor.kind == Kinds.TYP) { |
3145 | 230 | types.getSupertypes(siteCursor, supertypes, superSet); |
3146 | |
} |
3147 | |
|
3148 | 256 | for (Type supType : supertypes) { |
3149 | 586 | if (types.isSameType(supType, treeSym.owner.type)) { |
3150 | 204 | foundOwner = true; |
3151 | 204 | break ownerSearch; |
3152 | |
} |
3153 | |
} |
3154 | |
|
3155 | 52 | if (siteCursor.kind == Kinds.TYP) { |
3156 | 26 | numOfOuters++; |
3157 | |
} |
3158 | |
|
3159 | 52 | siteCursor = siteCursor.owner; |
3160 | 52 | } |
3161 | |
|
3162 | 204 | if (foundOwner) { |
3163 | |
|
3164 | 204 | siteCursor = siteOwner; |
3165 | 230 | while (numOfOuters > 0) { |
3166 | 26 | if (siteCursor.kind == Kinds.TYP) { |
3167 | 26 | ret = callExpression(pos, ret, initBuilder.outerAccessorName); |
3168 | 26 | ret.type = siteCursor.type; |
3169 | |
} |
3170 | |
|
3171 | 26 | if (siteCursor.kind == Kinds.TYP) { |
3172 | 26 | numOfOuters--; |
3173 | |
} |
3174 | 26 | siteCursor = siteCursor.owner; |
3175 | |
} |
3176 | |
} |
3177 | |
} |
3178 | |
} |
3179 | 1999 | return ret; |
3180 | |
} |
3181 | |
|
3182 | |
private void fillClassesWithOuters(JCCompilationUnit tree) { |
3183 | 340 | class FillClassesWithOuters extends JavafxTreeScanner { |
3184 | |
JFXClassDeclaration currentClass; |
3185 | |
|
3186 | |
@Override |
3187 | |
public void visitClassDeclaration(JFXClassDeclaration tree) { |
3188 | 613 | JFXClassDeclaration prevClass = currentClass; |
3189 | |
try { |
3190 | 613 | currentClass = tree; |
3191 | 613 | super.visitClassDeclaration(tree); |
3192 | |
} |
3193 | |
finally { |
3194 | 613 | currentClass = prevClass; |
3195 | 613 | } |
3196 | 613 | } |
3197 | |
|
3198 | |
@Override |
3199 | |
public void visitIdent(JCIdent tree) { |
3200 | 10879 | super.visitIdent(tree); |
3201 | 10879 | if (currentClass != null && tree.sym.kind != Kinds.TYP) { |
3202 | 7926 | addOutersForOuterAccess(tree.sym, currentClass.sym); |
3203 | |
} |
3204 | 10879 | } |
3205 | |
|
3206 | |
@Override |
3207 | |
public void visitInstanciate(JFXInstanciate tree) { |
3208 | 632 | super.visitInstanciate(tree); |
3209 | 632 | super.scan(tree.getArgs()); |
3210 | 632 | } |
3211 | |
|
3212 | |
private void addOutersForOuterAccess(Symbol sym, Symbol currentClass) { |
3213 | 7926 | if (sym != null && sym.owner != null && sym.owner.type != null |
3214 | |
&& !sym.isStatic() && currentClass != null) { |
3215 | 5357 | Symbol outerSym = currentClass; |
3216 | 5357 | ListBuffer<ClassSymbol> potentialOuters = new ListBuffer<ClassSymbol>(); |
3217 | 5357 | boolean foundOuterOwner = false; |
3218 | 16119 | while (outerSym != null) { |
3219 | 12656 | if (outerSym.kind == Kinds.TYP) { |
3220 | 5497 | ClassSymbol outerCSym = (ClassSymbol) outerSym; |
3221 | 5497 | if (types.isSuperType(sym.owner.type, outerCSym)) { |
3222 | 1797 | foundOuterOwner = true; |
3223 | 1797 | break; |
3224 | |
} |
3225 | 3700 | potentialOuters.append(outerCSym); |
3226 | 3700 | } |
3227 | 7159 | else if (sym.owner == outerSym) |
3228 | 97 | break; |
3229 | 10762 | outerSym = outerSym.owner; |
3230 | |
} |
3231 | |
|
3232 | 5357 | if (foundOuterOwner) { |
3233 | 1797 | for (ClassSymbol cs : potentialOuters) { |
3234 | 26 | hasOuters.add(cs); |
3235 | |
} |
3236 | |
} |
3237 | |
} |
3238 | 7926 | } |
3239 | |
} |
3240 | |
|
3241 | 340 | new FillClassesWithOuters().scan(tree); |
3242 | 340 | } |
3243 | |
|
3244 | |
public void visitTimeLiteral(JFXTimeLiteral tree) { |
3245 | |
|
3246 | 22 | JCFieldAccess clsname = (JCFieldAccess) fxmake.at(tree.pos()).Type(syms.javafx_DurationType); |
3247 | 22 | clsname.sym = syms.javafx_DurationType.tsym; |
3248 | 22 | Name attribute = names.fromString("millis"); |
3249 | 22 | Symbol symMillis = syms.javafx_DurationType.tsym.members().lookup(attribute).sym; |
3250 | 22 | JFXObjectLiteralPart objLiteral = fxmake.at(tree.pos()).ObjectLiteralPart(attribute, tree.value, JavafxBindStatus.UNBOUND); |
3251 | 22 | objLiteral.sym = symMillis; |
3252 | 22 | JFXInstanciate inst = fxmake.at(tree.pos).Instanciate(clsname, null, List.of((JCTree)objLiteral)); |
3253 | 22 | inst.type = clsname.type; |
3254 | |
|
3255 | |
|
3256 | 22 | visitInstanciate(inst); |
3257 | 22 | } |
3258 | |
|
3259 | |
public void visitInterpolate(JFXInterpolate tree) { |
3260 | 0 | throw new UnsupportedOperationException("Not supported yet."); |
3261 | |
} |
3262 | |
|
3263 | |
public void visitInterpolateValue(final JFXInterpolateValue tree) { |
3264 | 5 | DiagnosticPosition diagPos = tree.pos(); |
3265 | 5 | JCExpression clsname = fxmake.at(diagPos).Type(syms.javafx_KeyValueType); |
3266 | 5 | ((JCFieldAccess) clsname).sym = syms.javafx_KeyValueType.tsym; |
3267 | 5 | JCExpression interp = tree.interpolation; |
3268 | 5 | if (interp == null) |
3269 | 4 | interp = fxmake.at(tree.pos).Literal(TypeTags.BOT, null); |
3270 | 5 | final Symbol targetSymbol = syms.javafx_KeyValueType.tsym.members().lookup(defs.targetName).sym; |
3271 | 5 | JFXObjectLiteralPart targetLiteral = fxmake.at(tree.pos()).ObjectLiteralPart(defs.targetName, tree.attribute); |
3272 | 5 | targetLiteral.sym = targetSymbol; |
3273 | 5 | JFXObjectLiteralPart valueLiteral = |
3274 | |
fxmake.at(tree.pos()).ObjectLiteralPart(defs.valueName, tree.value, JavafxBindStatus.UNIDIBIND); |
3275 | 5 | valueLiteral.sym = syms.javafx_KeyValueType.tsym.members().lookup(defs.valueName).sym; |
3276 | |
List<JCTree> parts; |
3277 | 5 | if (tree.interpolation == null) |
3278 | 4 | parts = List.<JCTree>of(targetLiteral, valueLiteral); |
3279 | |
else { |
3280 | 1 | JFXObjectLiteralPart interpolateLiteral = |
3281 | |
fxmake.at(tree.pos()).ObjectLiteralPart(defs.interpolateName, tree.interpolation, JavafxBindStatus.UNIDIBIND); |
3282 | 1 | interpolateLiteral.sym = syms.javafx_KeyValueType.tsym.members().lookup(defs.interpolateName).sym; |
3283 | 1 | parts = List.<JCTree>of(targetLiteral, valueLiteral, interpolateLiteral); |
3284 | |
} |
3285 | |
|
3286 | 5 | JFXInstanciate inst = fxmake.at(diagPos).Instanciate(clsname, null, parts); |
3287 | 5 | inst.type = clsname.type; |
3288 | 5 | result = new InstanciateTranslator(inst, this) { |
3289 | |
protected void processLocalVar(JFXVar var) { |
3290 | 0 | } |
3291 | |
|
3292 | |
protected JCStatement translateAttributeSet(JCExpression init, JavafxBindStatus bindStatus, VarSymbol vsym, JCExpression instance) { |
3293 | 11 | if (targetSymbol==vsym) { |
3294 | 5 | JCExpression target = translate(init, Wrapped.InLocation); |
3295 | 5 | target = callExpression(diagPos, make.Type(syms.javafx_PointerType), "make", target); |
3296 | 5 | VarMorphInfo vmi = typeMorpher.varMorphInfo(vsym); |
3297 | |
JCExpression localAttr; |
3298 | |
|
3299 | |
|
3300 | 5 | if (vsym.owner.kind == Kinds.TYP) { |
3301 | 5 | if ((vsym.flags() & STATIC) != 0) { |
3302 | |
|
3303 | 0 | localAttr = make.Ident(vsym); |
3304 | |
} else { |
3305 | 5 | String attrAccess = attributeGetMethodNamePrefix + vsym; |
3306 | 5 | localAttr = callExpression(diagPos, instance, attrAccess); |
3307 | 5 | } |
3308 | |
} else { |
3309 | |
|
3310 | 0 | assert( (vsym.flags() & Flags.PARAMETER) == 0): "Parameters are not initialized"; |
3311 | 0 | localAttr = make.at(diagPos).Ident(vsym); |
3312 | |
} |
3313 | 5 | return make.at(diagPos).Exec(callExpression(diagPos, localAttr, defs.locationSetMilieuMethodName[vmi.getTypeKind()][FROM_LITERAL_MILIEU], target)); |
3314 | |
} else { |
3315 | 6 | return toJava.translateDefinitionalAssignmentToSet(diagPos, init, bindStatus, |
3316 | |
vsym, instance, FROM_LITERAL_MILIEU); |
3317 | |
} |
3318 | |
} |
3319 | |
}.doit(); |
3320 | 5 | } |
3321 | |
|
3322 | |
public void visitKeyFrameLiteral(JFXKeyFrameLiteral tree) { |
3323 | 0 | throw new UnsupportedOperationException("Not supported yet."); |
3324 | |
} |
3325 | |
} |