History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/tools/tree/Expression.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/tools/tree/Expression.java+775−0
@@ -0,0 +1,775 @@
1+/*
2+ * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.tree;
27+
28+import sun.tools.java.*;
29+import sun.tools.asm.Label;
30+import sun.tools.asm.Assembler;
31+import java.io.PrintStream;
32+import java.util.Hashtable;
33+
34+/**
35+ * WARNING: The contents of this source file are not part of any
36+ * supported API. Code that depends on them does so at its own risk:
37+ * they are subject to change or removal without notice.
38+ */
39+public
40+class Expression extends Node {
41+ Type type;
42+
43+ /**
44+ * Constructor
45+ */
46+ Expression(int op, long where, Type type) {
47+ super(op, where);
48+ this.type = type;
49+ }
50+
51+ /**
52+ * Type checking may assign a more complex implementation
53+ * to an innocuous-looking expression (like an identifier).
54+ * Return that implementation, or the original expression itself
55+ * if there is no special implementation.
56+ * <p>
57+ * This appears at present to be dead code, and is not called
58+ * from within javac. Access to the implementation generally
59+ * occurs within the same class, and thus uses the underlying
60+ * field directly.
61+ */
62+ public Expression getImplementation() {
63+ return this;
64+ }
65+
66+ public Type getType() {
67+ return type;
68+ }
69+
70+ /**
71+ * Return the precedence of the operator
72+ */
73+ int precedence() {
74+ return (op < opPrecedence.length) ? opPrecedence[op] : 100;
75+ }
76+
77+ /**
78+ * Order the expression based on precedence
79+ */
80+ public Expression order() {
81+ return this;
82+ }
83+
84+ /**
85+ * Return true if constant, according to JLS 15.27.
86+ * A constant expression must inline away to a literal constant.
87+ */
88+ public boolean isConstant() {
89+ return false;
90+ }
91+
92+ /**
93+ * Return the constant value.
94+ */
95+ public Object getValue() {
96+ return null;
97+ }
98+
99+ /**
100+ * Check if the expression is known to be equal to a given value.
101+ * Returns false for any expression other than a literal constant,
102+ * thus should be called only after simplification (inlining) has
103+ * been performed.
104+ */
105+ public boolean equals(int i) {
106+ return false;
107+ }
108+ public boolean equals(boolean b) {
109+ return false;
110+ }
111+ public boolean equals(Identifier id) {
112+ return false;
113+ }
114+ public boolean equals(String s) {
115+ return false;
116+ }
117+
118+ /**
119+ * Check if the expression must be a null reference.
120+ */
121+ public boolean isNull() {
122+ return false;
123+ }
124+
125+ /**
126+ * Check if the expression cannot be a null reference.
127+ */
128+ public boolean isNonNull() {
129+ return false;
130+ }
131+
132+ /**
133+ * Check if the expression is equal to its default static value
134+ */
135+ public boolean equalsDefault() {
136+ return false;
137+ }
138+
139+
140+ /**
141+ * Convert an expresion to a type
142+ */
143+ Type toType(Environment env, Context ctx) {
144+ env.error(where, "invalid.type.expr");
145+ return Type.tError;
146+ }
147+
148+ /**
149+ * Convert an expresion to a type in a context where a qualified
150+ * type name is expected, e.g., in the prefix of a qualified type
151+ * name.
152+ */
153+ /*-----------------------------------------------------*
154+ Type toQualifiedType(Environment env, Context ctx) {
155+ env.error(where, "invalid.type.expr");
156+ return Type.tError;
157+ }
158+ *-----------------------------------------------------*/
159+
160+ /**
161+ * See if this expression fits in the given type.
162+ * This is useful because some larger numbers fit into
163+ * smaller types.
164+ * <p>
165+ * If it is an "int" constant expression, inline it, if necessary,
166+ * to examine its numerical value. See JLS 5.2 and 15.24.
167+ */
168+ public boolean fitsType(Environment env, Context ctx, Type t) {
169+ try {
170+ if (env.isMoreSpecific(this.type, t)) {
171+ return true;
172+ }
173+ if (this.type.isType(TC_INT) && this.isConstant() && ctx != null) {
174+ // Tentative inlining is harmless for constant expressions.
175+ Expression n = this.inlineValue(env, ctx);
176+ if (n != this && n instanceof ConstantExpression) {
177+ return n.fitsType(env, ctx, t);
178+ }
179+ }
180+ return false;
181+ } catch (ClassNotFound e) {
182+ return false;
183+ }
184+ }
185+
186+ /** @deprecated (for backward compatibility) */
187+ @Deprecated
188+ public boolean fitsType(Environment env, Type t) {
189+ return fitsType(env, (Context) null, t);
190+ }
191+
192+ /**
193+ * Check an expression
194+ */
195+ public Vset checkValue(Environment env, Context ctx, Vset vset, Hashtable exp) {
196+ return vset;
197+ }
198+ public Vset checkInitializer(Environment env, Context ctx, Vset vset, Type t, Hashtable exp) {
199+ return checkValue(env, ctx, vset, exp);
200+ }
201+ public Vset check(Environment env, Context ctx, Vset vset, Hashtable exp) {
202+ throw new CompilerError("check failed");
203+ }
204+
205+ public Vset checkLHS(Environment env, Context ctx,
206+ Vset vset, Hashtable exp) {
207+ env.error(where, "invalid.lhs.assignment");
208+ type = Type.tError;
209+ return vset;
210+ }
211+
212+ /**
213+ * Return a <code>FieldUpdater</code> object to be used in updating the
214+ * value of the location denoted by <code>this</code>, which must be an
215+ * expression suitable for the left-hand side of an assignment.
216+ * This is used for implementing assignments to private fields for which
217+ * an access method is required. Returns null if no access method is
218+ * needed, in which case the assignment is handled in the usual way, by
219+ * direct access. Only simple assignment expressions are handled here
220+ * Assignment operators and pre/post increment/decrement operators are
221+ * are handled by 'getUpdater' below.
222+ * <p>
223+ * Called during the checking phase.
224+ */
225+
226+ public FieldUpdater getAssigner(Environment env, Context ctx) {
227+ throw new CompilerError("getAssigner lhs");
228+ }
229+
230+ /**
231+ * Return a <code>FieldUpdater</code> object to be used in updating the value of the
232+ * location denoted by <code>this</code>, which must be an expression suitable for the
233+ * left-hand side of an assignment. This is used for implementing the assignment
234+ * operators and the increment/decrement operators on private fields that require an
235+ * access method, e.g., uplevel from an inner class. Returns null if no access method
236+ * is needed.
237+ * <p>
238+ * Called during the checking phase.
239+ */
240+
241+ public FieldUpdater getUpdater(Environment env, Context ctx) {
242+ throw new CompilerError("getUpdater lhs");
243+ }
244+
245+ public Vset checkAssignOp(Environment env, Context ctx,
246+ Vset vset, Hashtable exp, Expression outside) {
247+ if (outside instanceof IncDecExpression)
248+ env.error(where, "invalid.arg", opNames[outside.op]);
249+ else
250+ env.error(where, "invalid.lhs.assignment");
251+ type = Type.tError;
252+ return vset;
253+ }
254+
255+ /**
256+ * Check something that might be an AmbiguousName (refman 6.5.2).
257+ * A string of dot-separated identifiers might be, in order of preference:
258+ * <nl>
259+ * <li> a variable name followed by fields or types
260+ * <li> a type name followed by fields or types
261+ * <li> a package name followed a type and then fields or types
262+ * </nl>
263+ * If a type name is found, it rewrites itself as a <tt>TypeExpression</tt>.
264+ * If a node decides it can only be a package prefix, it sets its
265+ * type to <tt>Type.tPackage</tt>. The caller must detect this
266+ * and act appropriately to verify the full package name.
267+ * @arg loc the expression containing the ambiguous expression
268+ */
269+ public Vset checkAmbigName(Environment env, Context ctx, Vset vset, Hashtable exp,
270+ UnaryExpression loc) {
271+ return checkValue(env, ctx, vset, exp);
272+ }
273+
274+ /**
275+ * Check a condition. Return a ConditionVars(), which indicates when
276+ * which variables are set if the condition is true, and which are set if
277+ * the condition is false.
278+ */
279+ public ConditionVars checkCondition(Environment env, Context ctx,
280+ Vset vset, Hashtable exp) {
281+ ConditionVars cvars = new ConditionVars();
282+ checkCondition(env, ctx, vset, exp, cvars);
283+ return cvars;
284+ }
285+
286+ /*
287+ * Check a condition.
288+ *
289+ * cvars is modified so that
290+ * cvar.vsTrue indicates variables with a known value if result = true
291+ * cvars.vsFalse indicates variables with a known value if !result
292+ *
293+ * The default action is to simply call checkValue on the expression, and
294+ * to see both vsTrue and vsFalse to the result.
295+ */
296+
297+ public void checkCondition(Environment env, Context ctx,
298+ Vset vset, Hashtable exp, ConditionVars cvars) {
299+ cvars.vsTrue = cvars.vsFalse = checkValue(env, ctx, vset, exp);
300+ // unshare side effects:
301+ cvars.vsFalse = cvars.vsFalse.copy();
302+ }
303+
304+ /**
305+ * Evaluate.
306+ *
307+ * Attempt to compute the value of an expression node. If all operands are
308+ * literal constants of the same kind (e.g., IntegerExpression nodes), a
309+ * new constant node of the proper type is returned representing the value
310+ * as computed at compile-time. Otherwise, the original node 'this' is
311+ * returned.
312+ */
313+ Expression eval() {
314+ return this;
315+ }
316+
317+ /**
318+ * Simplify.
319+ *
320+ * Attempt to simplify an expression node by returning a semantically-
321+ * equivalent expression that is presumably less costly to execute. There
322+ * is some overlap with the intent of 'eval', as compile-time evaluation of
323+ * conditional expressions and the short-circuit boolean operators is
324+ * performed here. Other simplifications include logical identities
325+ * involving logical negation and comparisons. If no simplification is
326+ * possible, the original node 'this' is returned. It is assumed that the
327+ * children of the node have previously been recursively simplified and
328+ * evaluated. A result of 'null' indicates that the expression may be
329+ * elided entirely.
330+ */
331+ Expression simplify() {
332+ return this;
333+ }
334+
335+ /**
336+ * Inline.
337+ *
338+ * Recursively simplify each child of an expression node, destructively
339+ * replacing the child with the simplified result. Also attempts to
340+ * simplify the current node 'this', and returns the simplified result.
341+ *
342+ * The name 'inline' is somthing of a misnomer, as these methods are
343+ * responsible for compile-time expression simplification in general.
344+ * The 'eval' and 'simplify' methods apply to a single expression node
345+ * only -- it is 'inline' and 'inlineValue' that drive the simplification
346+ * of entire expressions.
347+ */
348+ public Expression inline(Environment env, Context ctx) {
349+ return null;
350+ }
351+ public Expression inlineValue(Environment env, Context ctx) {
352+ return this;
353+ }
354+
355+ /**
356+ * Attempt to evaluate this expression. If this expression
357+ * yields a value, append it to the StringBuffer `buffer'.
358+ * If this expression cannot be evaluated at this time (for
359+ * example if it contains a division by zero, a non-constant
360+ * subexpression, or a subexpression which "refuses" to evaluate)
361+ * then return `null' to indicate failure.
362+ *
363+ * It is anticipated that this method will be called to evaluate
364+ * concatenations of compile-time constant strings. The call
365+ * originates from AddExpression#inlineValue().
366+ *
367+ * See AddExpression#inlineValueSB() for detailed comments.
368+ */
369+ protected StringBuffer inlineValueSB(Environment env,
370+ Context ctx,
371+ StringBuffer buffer) {
372+ Expression inlined = inlineValue(env, ctx);
373+ Object val = inlined.getValue();
374+
375+ if (val == null && !inlined.isNull()){
376+ // This (supposedly constant) expression refuses to yield
377+ // a value. This can happen, in particular, when we are
378+ // trying to evaluate a division by zero. It can also
379+ // happen in cases where isConstant() is able to classify
380+ // expressions as constant that the compiler's inlining
381+ // mechanisms aren't able to evaluate; this is rare,
382+ // and all such cases that we have found so far
383+ // (e.g. 4082814, 4106244) have been plugged up.
384+ //
385+ // We return a null to indicate that we have failed to
386+ // evaluate the concatenation.
387+ return null;
388+ }
389+
390+ // For boolean and character expressions, getValue() returns
391+ // an Integer. We need to take care, when appending the result
392+ // of getValue(), that we preserve the type.
393+ // Fix for 4103959, 4102672.
394+ if (type == Type.tChar) {
395+ buffer.append((char)((Integer)val).intValue());
396+ } else if (type == Type.tBoolean) {
397+ buffer.append(((Integer)val).intValue() != 0);
398+ } else {
399+ buffer.append(val);
400+ }
401+
402+ return buffer;
403+ }
404+
405+ public Expression inlineLHS(Environment env, Context ctx) {
406+ return null;
407+ }
408+
409+ /**
410+ * The cost of inlining this expression.
411+ * This cost controls the inlining of methods, and does not determine
412+ * the compile-time simplifications performed by 'inline' and friends.
413+ */
414+ public int costInline(int thresh, Environment env, Context ctx) {
415+ return 1;
416+ }
417+
418+ /**
419+ * Code
420+ */
421+ void codeBranch(Environment env, Context ctx, Assembler asm, Label lbl, boolean whenTrue) {
422+ if (type.isType(TC_BOOLEAN)) {
423+ codeValue(env, ctx, asm);
424+ asm.add(where, whenTrue ? opc_ifne : opc_ifeq, lbl, whenTrue);
425+ } else {
426+ throw new CompilerError("codeBranch " + opNames[op]);
427+ }
428+ }
429+ public void codeValue(Environment env, Context ctx, Assembler asm) {
430+ if (type.isType(TC_BOOLEAN)) {
431+ Label l1 = new Label();
432+ Label l2 = new Label();
433+
434+ codeBranch(env, ctx, asm, l1, true);
435+ asm.add(true, where, opc_ldc, new Integer(0));
436+ asm.add(true, where, opc_goto, l2);
437+ asm.add(l1);
438+ asm.add(true, where, opc_ldc, new Integer(1));
439+ asm.add(l2);
440+ } else {
441+ throw new CompilerError("codeValue");
442+ }
443+ }
444+ public void code(Environment env, Context ctx, Assembler asm) {
445+ codeValue(env, ctx, asm);
446+
447+ switch (type.getTypeCode()) {
448+ case TC_VOID:
449+ break;
450+
451+ case TC_DOUBLE:
452+ case TC_LONG:
453+ asm.add(where, opc_pop2);
454+ break;
455+
456+ default:
457+ asm.add(where, opc_pop);
458+ break;
459+ }
460+ }
461+ int codeLValue(Environment env, Context ctx, Assembler asm) {
462+ print(System.out);
463+ throw new CompilerError("invalid lhs");
464+ }
465+ void codeLoad(Environment env, Context ctx, Assembler asm) {
466+ print(System.out);
467+ throw new CompilerError("invalid load");
468+ }
469+ void codeStore(Environment env, Context ctx, Assembler asm) {
470+ print(System.out);
471+ throw new CompilerError("invalid store");
472+ }
473+
474+ /**
475+ * Convert this expression to a string.
476+ */
477+ void ensureString(Environment env, Context ctx, Assembler asm)
478+ throws ClassNotFound, AmbiguousMember
479+ {
480+ if (type == Type.tString && isNonNull()) {
481+ return;
482+ }
483+ // Make sure it's a non-null string.
484+ ClassDefinition sourceClass = ctx.field.getClassDefinition();
485+ ClassDeclaration stClass = env.getClassDeclaration(Type.tString);
486+ ClassDefinition stClsDef = stClass.getClassDefinition(env);
487+ // FIX FOR 4071548
488+ // We use 'String.valueOf' to do the conversion, in order to
489+ // correctly handle null references and efficiently handle
490+ // primitive types. For reference types, we force the argument
491+ // to be interpreted as of 'Object' type, thus avoiding the
492+ // the special-case overloading of 'valueOf' for character arrays.
493+ // This special treatment would conflict with JLS 15.17.1.1.
494+ if (type.inMask(TM_REFERENCE)) {
495+ // Reference type
496+ if (type != Type.tString) {
497+ // Convert non-string object to string. If object is
498+ // a string, we don't need to convert it, except in the
499+ // case that it is null, which is handled below.
500+ Type argType1[] = {Type.tObject};
501+ MemberDefinition f1 =
502+ stClsDef.matchMethod(env, sourceClass, idValueOf, argType1);
503+ asm.add(where, opc_invokestatic, f1);
504+ }
505+ // FIX FOR 4030173
506+ // If the argument was null, then value is "null", but if the
507+ // argument was not null, 'toString' was called and could have
508+ // returned null. We call 'valueOf' again to make sure that
509+ // the result is a non-null string. See JLS 15.17.1.1. The
510+ // approach taken here minimizes code size -- open code would
511+ // be faster. The 'toString' method for an array class cannot
512+ // be overridden, thus we know that it will never return null.
513+ if (!type.inMask(TM_ARRAY|TM_NULL)) {
514+ Type argType2[] = {Type.tString};
515+ MemberDefinition f2 =
516+ stClsDef.matchMethod(env, sourceClass, idValueOf, argType2);
517+ asm.add(where, opc_invokestatic, f2);
518+ }
519+ } else {
520+ // Primitive type
521+ Type argType[] = {type};
522+ MemberDefinition f =
523+ stClsDef.matchMethod(env, sourceClass, idValueOf, argType);
524+ asm.add(where, opc_invokestatic, f);
525+ }
526+ }
527+
528+ /**
529+ * Convert this expression to a string and append it to the string
530+ * buffer on the top of the stack.
531+ * If the needBuffer argument is true, the string buffer needs to be
532+ * created, initialized, and pushed on the stack, first.
533+ */
534+ void codeAppend(Environment env, Context ctx, Assembler asm,
535+ ClassDeclaration sbClass, boolean needBuffer)
536+ throws ClassNotFound, AmbiguousMember
537+ {
538+ ClassDefinition sourceClass = ctx.field.getClassDefinition();
539+ ClassDefinition sbClsDef = sbClass.getClassDefinition(env);
540+ MemberDefinition f;
541+ if (needBuffer) {
542+ // need to create the string buffer
543+ asm.add(where, opc_new, sbClass); // create the class
544+ asm.add(where, opc_dup);
545+ if (equals("")) {
546+ // make an empty string buffer
547+ f = sbClsDef.matchMethod(env, sourceClass, idInit);
548+ } else {
549+ // optimize by initializing the buffer with the string
550+ codeValue(env, ctx, asm);
551+ ensureString(env, ctx, asm);
552+ Type argType[] = {Type.tString};
553+ f = sbClsDef.matchMethod(env, sourceClass, idInit, argType);
554+ }
555+ asm.add(where, opc_invokespecial, f);
556+ } else {
557+ // append this item to the string buffer
558+ codeValue(env, ctx, asm);
559+ // FIX FOR 4071548
560+ // 'StringBuffer.append' converts its argument as if by
561+ // 'valueOf', treating character arrays specially. This
562+ // violates JLS 15.17.1.1, which requires that concatenation
563+ // convert non-primitive arguments using 'toString'. We force
564+ // the treatment of all reference types as type 'Object', thus
565+ // invoking an overloading of 'append' that has the required
566+ // semantics.
567+ Type argType[] =
568+ { (type.inMask(TM_REFERENCE) && type != Type.tString)
569+ ? Type.tObject
570+ : type };
571+ f = sbClsDef.matchMethod(env, sourceClass, idAppend, argType);
572+ asm.add(where, opc_invokevirtual, f);
573+ }
574+ }
575+
576+ /**
577+ * Code
578+ */
579+ void codeDup(Environment env, Context ctx, Assembler asm, int items, int depth) {
580+ switch (items) {
581+ case 0:
582+ return;
583+
584+ case 1:
585+ switch (depth) {
586+ case 0:
587+ asm.add(where, opc_dup);
588+ return;
589+ case 1:
590+ asm.add(where, opc_dup_x1);
591+ return;
592+ case 2:
593+ asm.add(where, opc_dup_x2);
594+ return;
595+
596+ }
597+ break;
598+ case 2:
599+ switch (depth) {
600+ case 0:
601+ asm.add(where, opc_dup2);
602+ return;
603+ case 1:
604+ asm.add(where, opc_dup2_x1);
605+ return;
606+ case 2:
607+ asm.add(where, opc_dup2_x2);
608+ return;
609+
610+ }
611+ break;
612+ }
613+ throw new CompilerError("can't dup: " + items + ", " + depth);
614+ }
615+
616+ void codeConversion(Environment env, Context ctx, Assembler asm, Type f, Type t) {
617+ int from = f.getTypeCode();
618+ int to = t.getTypeCode();
619+
620+ switch (to) {
621+ case TC_BOOLEAN:
622+ if (from != TC_BOOLEAN) {
623+ break;
624+ }
625+ return;
626+ case TC_BYTE:
627+ if (from != TC_BYTE) {
628+ codeConversion(env, ctx, asm, f, Type.tInt);
629+ asm.add(where, opc_i2b);
630+ }
631+ return;
632+ case TC_CHAR:
633+ if (from != TC_CHAR) {
634+ codeConversion(env, ctx, asm, f, Type.tInt);
635+ asm.add(where, opc_i2c);
636+ }
637+ return;
638+ case TC_SHORT:
639+ if (from != TC_SHORT) {
640+ codeConversion(env, ctx, asm, f, Type.tInt);
641+ asm.add(where, opc_i2s);
642+ }
643+ return;
644+ case TC_INT:
645+ switch (from) {
646+ case TC_BYTE:
647+ case TC_CHAR:
648+ case TC_SHORT:
649+ case TC_INT:
650+ return;
651+ case TC_LONG:
652+ asm.add(where, opc_l2i);
653+ return;
654+ case TC_FLOAT:
655+ asm.add(where, opc_f2i);
656+ return;
657+ case TC_DOUBLE:
658+ asm.add(where, opc_d2i);
659+ return;
660+ }
661+ break;
662+ case TC_LONG:
663+ switch (from) {
664+ case TC_BYTE:
665+ case TC_CHAR:
666+ case TC_SHORT:
667+ case TC_INT:
668+ asm.add(where, opc_i2l);
669+ return;
670+ case TC_LONG:
671+ return;
672+ case TC_FLOAT:
673+ asm.add(where, opc_f2l);
674+ return;
675+ case TC_DOUBLE:
676+ asm.add(where, opc_d2l);
677+ return;
678+ }
679+ break;
680+ case TC_FLOAT:
681+ switch (from) {
682+ case TC_BYTE:
683+ case TC_CHAR:
684+ case TC_SHORT:
685+ case TC_INT:
686+ asm.add(where, opc_i2f);
687+ return;
688+ case TC_LONG:
689+ asm.add(where, opc_l2f);
690+ return;
691+ case TC_FLOAT:
692+ return;
693+ case TC_DOUBLE:
694+ asm.add(where, opc_d2f);
695+ return;
696+ }
697+ break;
698+ case TC_DOUBLE:
699+ switch (from) {
700+ case TC_BYTE:
701+ case TC_CHAR:
702+ case TC_SHORT:
703+ case TC_INT:
704+ asm.add(where, opc_i2d);
705+ return;
706+ case TC_LONG:
707+ asm.add(where, opc_l2d);
708+ return;
709+ case TC_FLOAT:
710+ asm.add(where, opc_f2d);
711+ return;
712+ case TC_DOUBLE:
713+ return;
714+ }
715+ break;
716+
717+ case TC_CLASS:
718+ switch (from) {
719+ case TC_NULL:
720+ return;
721+ case TC_CLASS:
722+ case TC_ARRAY:
723+ try {
724+ if (!env.implicitCast(f, t)) {
725+ asm.add(where, opc_checkcast, env.getClassDeclaration(t));
726+ }
727+ } catch (ClassNotFound e) {
728+ throw new CompilerError(e);
729+ }
730+ return;
731+ }
732+
733+ break;
734+
735+ case TC_ARRAY:
736+ switch (from) {
737+ case TC_NULL:
738+ return;
739+ case TC_CLASS:
740+ case TC_ARRAY:
741+ try {
742+ if (!env.implicitCast(f, t)) {
743+ asm.add(where, opc_checkcast, t);
744+ }
745+ return;
746+ } catch (ClassNotFound e) {
747+ throw new CompilerError(e);
748+ }
749+ }
750+ break;
751+ }
752+ throw new CompilerError("codeConversion: " + from + ", " + to);
753+ }
754+
755+ /**
756+ * Check if the first thing is a constructor invocation
757+ */
758+ public Expression firstConstructor() {
759+ return null;
760+ }
761+
762+ /**
763+ * Create a copy of the expression for method inlining
764+ */
765+ public Expression copyInline(Context ctx) {
766+ return (Expression)clone();
767+ }
768+
769+ /**
770+ * Print
771+ */
772+ public void print(PrintStream out) {
773+ out.print(opNames[op]);
774+ }
775+}