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<Object, Object> exp) {
 196         return vset;
 197     }
 198     public Vset checkInitializer(Environment env, Context ctx, Vset vset, Type t, Hashtable<Object, Object> exp) {
 199         return checkValue(env, ctx, vset, exp);
 200     }
 201     public Vset check(Environment env, Context ctx, Vset vset, Hashtable<Object, Object> exp) {
 202         throw new CompilerError("check failed");
 203     }
 204 
 205     public Vset checkLHS(Environment env, Context ctx,
 206                             Vset vset, Hashtable<Object, Object> exp) {
 207         env.error(where, "invalid.lhs.assignment");
 208         type = Type.tError;
 209         return vset;
 210     }
 211 
 212     /**
 213      * Return a {@code FieldUpdater} object to be used in updating the
 214      * value of the location denoted by {@code this}, 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} object to be used in updating the value of the
 232      * location denoted by {@code this}, 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<Object, Object> 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 {@code TypeExpression}.
 264      * If a node decides it can only be a package prefix, it sets its
 265      * type to {@code Type.tPackage}.  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<Object, Object> 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<Object, Object> 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<Object, Object> 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, 0);
 436             asm.add(true, where, opc_goto, l2);
 437             asm.add(l1);
 438             asm.add(true, where, opc_ldc, 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 }