/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/** This pass translates away some syntactic sugar: inner classes,
* class literals, assertions, foreach loops, etc.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
return instance;
}
private boolean allowEnums;
private boolean debugLower;
classDollar = names.
}
/** The currently enclosing class.
*/
/** A queue of all translated classes.
*/
/** Environment for symbol lookup, set by translateTopLevelClass.
*/
/** A hash table mapping syntax trees to their ending source positions.
*/
/**************************************************************************
* Global mappings
*************************************************************************/
/** A hash table mapping local classes to their definitions.
*/
/** A hash table mapping virtual accessed symbols in outer subclasses
* to the actually referred symbol in superclasses.
*/
/** The current method definition.
*/
/** The current method symbol.
*/
/** The currently enclosing outermost class definition.
*/
/** The currently enclosing outermost member definition.
*/
/** A navigator class for assembling a mapping from local class symbols
* to class definition trees.
* There is only one case; all other cases simply traverse down the tree.
*/
/** All encountered class defs are entered into classdefs table.
*/
super.visitClassDef(tree);
}
}
/** Map a class symbol to its definition.
* @param c The class symbol of which we want to determine the definition.
*/
// First lookup the class in the classdefs table.
// If this fails, traverse outermost member definition, entering all
// local classes into classdefs, and try again.
}
// If this fails, traverse outermost class definition, entering all
// local classes into classdefs, and try again.
}
return def;
}
/** A hash table mapping class symbols to lists of free variables.
* accessed by them. Only free variables of the method immediately containing
* a class are associated with that class.
*/
/** A navigator class for collecting the free variables accessed
* from a local class.
* There is only one case; all other cases simply traverse down the tree.
*/
/** The owner of the local class.
*/
/** The local class.
*/
/** The list of owner's variables accessed from within the local class,
* without any duplicates.
*/
}
/** Add free variable to fvs list unless it is already there.
*/
if (l.head == v) return;
}
/** Add all free variables of class c to fvs list
* unless they are already there.
*/
addFreeVar(l.head);
}
}
}
/** If tree refers to a variable in owner of local class, add it to
* free variables list.
*/
}
// where
if (v.getConstValue() == null) {
addFreeVar(v);
}
} else {
}
}
}
/** If tree refers to a class instance creation expression
* add all free variables of the freshly created class.
*/
addFreeVars(c);
c.hasOuterInstance() &&
super.visitNewClass(tree);
}
/** If tree refers to a qualified this or super expression
* for anything but the current class, add the outer this
* stack as a free variable.
*/
super.visitSelect(tree);
}
/** If tree refers to a superclass constructor call,
* add all free variables of the superclass.
*/
if (c.hasOuterInstance() &&
}
super.visitApply(tree);
}
}
/** Return the variables accessed from within a local class, which
* are declared in the local class' owner.
* (in reverse order of first access).
*/
}
return fvs;
} else {
}
}
return map;
}
/** This map gives a translation table to be used for enum
* switches.
*
* <p>For each enum that appears as the type of a switch
* expression, we maintain an EnumMapping to assist in the
* translation, as exemplified by the following example:
*
* <p>we translate
* <pre>
* switch(colorExpression) {
* case red: stmt1;
* case green: stmt2;
* }
* </pre>
* into
* <pre>
* switch(Outer$0.$EnumMap$Color[colorExpression.ordinal()]) {
* case 1: stmt1;
* case 2: stmt2
* }
* </pre>
* with the auxiliary table initialized as follows:
* <pre>
* class Outer$0 {
* synthetic final int[] $EnumMap$Color = new int[Color.values().length];
* static {
* try { $EnumMap$Color[red.ordinal()] = 1; } catch (NoSuchFieldError ex) {}
* try { $EnumMap$Color[green.ordinal()] = 2; } catch (NoSuchFieldError ex) {}
* }
* }
* </pre>
* class EnumMapping provides mapping data and support methods for this translation.
*/
class EnumMapping {
"SwitchMap" +
}
// the next value to use
// the enum for which this is a map
// the field containing the map
// the mapped values
}
// generate the field initializer for the map
void translate() {
// synthetic static final int[] $SwitchMap$Color = new int[Color.values().length];
// try { $SwitchMap$Color[red.ordinal()] = 1; } catch (java.lang.NoSuchFieldError ex) {}
null),
ordinalMethod))),
}
}
}
/**************************************************************************
* Tree building blocks
*************************************************************************/
/** Equivalent to make.at(pos.getStartPosition()) with side effect of caching
* pos as make_pos, for use in diagnostics.
**/
}
/** Make an attributed tree representing a literal. This will be an
* Ident node in the case of boolean literals, a Literal node in all
* other cases.
* @param type The literal's type.
* @param value The literal's value.
*/
}
/** Make an attributed tree representing null.
*/
}
/** Make an attributed class instance creation expression.
* @param ctype The class type.
* @param args The constructor arguments.
*/
return tree;
}
/** Make an attributed unary expression.
* @param optag The operators tree tag.
* @param arg The operator's argument.
*/
return tree;
}
/** Make an attributed binary expression.
* @param optag The operators tree tag.
* @param lhs The operator's left argument.
* @param rhs The operator's right argument.
*/
return tree;
}
/** Make an attributed assignop expression.
* @param optag The operators tree tag.
* @param lhs The operator's left argument.
* @param rhs The operator's right argument.
*/
return tree;
}
/** Convert tree into string object, unless it has already a
* reference type..
*/
return tree;
} else {
}
}
/** Create an empty anonymous class definition and enter and complete
* its symbol. Return the class definition's symbol.
* and create
* @param flags The class symbol's flags
* @param owner The class symbol's owner
*/
// Create class symbol.
c.members_field = new Scope(c);
c.flags_field = flags;
// Enter class symbol in owner scope and compiled table.
// Create class definition tree.
// Append class definition tree to owner's definitions.
return c;
}
/**************************************************************************
* Symbol manipulation utilities
*************************************************************************/
/** Enter a synthetic symbol in a given scope, but complain if there was already one there.
* @param pos Position for error reporting.
* @param sym The symbol.
* @param s The scope.
*/
}
/** Create a fresh synthetic name within a given scope - the unique name is
* obtained by appending '$' chars at the end of the name until no match
* is found.
*
* @param name base name
* @param s scope in which the name has to be unique
* @return fresh synthetic name
*/
do {
return name;
}
/** Check whether synthetic symbols generated during lowering conflict
* with user-defined symbols.
*
* @param translatedTrees lowered class trees
*/
for (JCTree t : translatedTrees) {
}
}
super.visitMethodDef(that);
}
}
super.visitVarDef(that);
}
try {
super.visitClassDef(that);
}
finally {
}
}
};
/** Look up a synthetic name in a given scope.
* @param scope The scope.
* @param name The name.
*/
}
/** Look up a method in a given scope.
*/
}
/** Look up a constructor.
*/
}
/** Look up a field.
*/
}
/** Anon inner classes are used as access constructor tags.
* accessConstructorTag will use an existing anon class if one is available,
* and synthethise a class (with makeEmptyClass) if one is not available.
* However, there is a small possibility that an existing class will not
* be generated as expected if it is inside a conditional with a constant
* expression. If that is found to be the case, create an empty class here.
*/
private void checkAccessConstructorTags() {
ClassSymbol c = l.head;
if (isTranslatedClassAvailable(c))
continue;
// Create class definition tree.
// add it to the list of classes to be generated
}
}
// where
return true;
}
}
return false;
}
/**************************************************************************
* Access methods
*************************************************************************/
/** Access codes for dereferencing, assignment,
* Access codes for assignment operations are determined by method accessCode
* below.
*
* All access codes for accesses to the current class are even.
* If a member of the superclass should be accessed instead (because
* access was via a qualified super), add one to the corresponding code
* for the current class, making the number odd.
* This numbering scheme is used by the backend to decide whether
* to issue an invokevirtual or invokespecial call.
*
* @see Gen.visitSelect(Select tree)
*/
private static final int
/** Number of access codes
*/
/** A mapping from symbols to their access numbers.
*/
/** A mapping from symbols to an array of access symbols, indexed by
* access code.
*/
/** A mapping from (constructor) symbols to access constructor symbols.
*/
/** A list of all class symbols used for access constructor tags.
*/
/** A queue for all accessed symbols.
*/
/** Map bytecode of binary operation to access code of corresponding
* assignment operation. This is always an even number.
*/
else
return -1;
}
/** return access code for identifier,
* @param tree The tree representing the identifier use.
* @param enclOp The closest enclosing operation node of tree,
* null if tree is not a subtree of an operation.
*/
return DEREFcode;
return ASSIGNcode;
else
return DEREFcode;
}
/** Return binary operator that corresponds to given access code.
*/
e != null;
e = e.sibling) {
if (e.sym instanceof OperatorSymbol) {
}
}
return null;
}
/** Return tree tag for assignment operation corresponding
* to given binary operator.
*/
return JCTree.BITXOR_ASG;
return JCTree.BITAND_ASG;
case ByteCodes.string_add:
default:
throw new AssertionError();
}
}
/** The name of the access method with number `anum' and access code `acode'.
*/
return names.fromString(
}
/** Return access symbol for a private or protected symbol from an inner class.
* @param sym The accessed private symbol.
* @param tree The accessing tree.
* @param enclOp The closest enclosing operation node of tree,
* null if tree is not a subtree of an operation.
* @param protAccess Is access to a protected symbol in another
* package?
* @param refSuper Is access via a (qualified) C.super?
*/
boolean protAccess, boolean refSuper) {
// For access via qualified super (T.super.x), place the
// access symbol on T.
// Otherwise pretend that the owner of an accessed
// protected symbol is the enclosing class of the current
// class which is a subclass of the symbol's owner.
}
// System.out.println("accessing " + vsym + " in " + vsym.location());
}
int acode; // The access code of the access method.
case VAR:
if (acode >= FIRSTASGOPcode) {
else
} else if (acode == ASSIGNcode)
else
break;
case MTH:
break;
default:
throw new AssertionError();
}
// For references via qualified super, increment acode by one,
// making it odd.
// Instance access methods get instance as first parameter.
// For protected symbols this needs to be the instance as a member
// of the type containing the accessed symbol, not the class
// containing the access method.
}
accessor = new MethodSymbol(
accOwner);
}
return accessor;
}
/** The qualifier to be used for accessing a symbol in an outer class.
* This is either C.sym or C.this.sym, depending on whether or not
* sym is static.
* @param sym The accessed symbol.
*/
}
/** Do we need an access method to reference private symbol?
*/
return false;
// private constructor in local class: relax protection
return false;
} else {
return true;
}
}
/** Do we need an access method to reference symbol in other package?
*/
return false;
return true;
return false;
}
/** The class in which an access method for given symbol goes.
* @param sym The access symbol
* @param protAccess Is access to a protected symbol in another
* package?
*/
if (protAccess) {
ClassSymbol c = currentClass;
}
return c;
} else {
}
}
return c;
} else {
// the symbol is private
}
}
/** Ensure that identifier is accessible, return tree accessing the identifier.
* @param sym The accessed symbol.
* @param tree The tree referring to the symbol.
* @param enclOp The closest enclosing operation node of tree,
* null if tree is not a subtree of an operation.
* @param refSuper Is access via a (qualified) C.super?
*/
// Access a free variable via its proxy, or its proxy's proxy
// A constant is replaced by its constant value.
}
// Otherwise replace the variable by its proxy.
}
case TYP:
// Convert type idents to
// <flat name> or <package name> . <flat name>
: null;
}
} else {
}
}
break;
// Access methods are required for
// - private members,
// - protected members in a superclass of an
// enclosing class contained in another package.
// - all non-private members accessed via a qualified super.
// A base has to be supplied for
// - simple identifiers accessing variables in outer classes.
boolean baseReq =
// Constants are replaced by their constant value.
}
// Private variables and methods are replaced by calls
// to their access methods.
if (accReq) {
// Instance access methods get instance
// as first parameter.
}
refSuper);
access);
// Other accesses to members of outer classes get a
// qualifier.
} else if (baseReq) {
}
}
}
}
return tree;
}
/** Ensure that identifier is accessible, return tree accessing the identifier.
* @param tree The identifier tree.
*/
}
/** Return access constructor for a private constructor,
* or the constructor itself, if no access constructor is needed.
* @param pos The position to report diagnostics, if any.
* @param constr The private constructor.
*/
if (needsPrivateAccess(constr)) {
aconstr = new MethodSymbol(
new MethodType(
accOwner);
}
return aconstr;
} else {
return constr;
}
}
/** Return an anonymous class nested in this toplevel class.
*/
"1");
// keep a record of all tags, to verify that all are generated as required
return ctag;
}
/** Add all required access methods for a private symbol to enclosing class.
* @param sym The symbol.
*/
} else {
for (int i = 0; i < NCODES; i++) {
}
}
}
/** Construct definition of an access method.
* @param pos The source code position of the definition.
* @param vsym The private or protected symbol.
* @param accessor The access method for the symbol.
* @param acode The access code.
*/
// System.err.println("access " + vsym + " with " + accessor);//DEBUG
// Find actual symbol
} else {
}
// Normalize out all odd access codes by taking floor modulo 2:
switch (acode1) {
case DEREFcode:
break;
case ASSIGNcode:
break;
break;
default:
}
} else {
}
// Make sure all parameters, result types and thrown exceptions
// are accessible.
return md;
}
/** Construct definition of an access constructor.
* @param pos The source code position of the definition.
* @param constr The private constructor.
* @param accessor The access method for the constructor.
*/
null);
return md;
}
/**************************************************************************
* Free variables proxies and this$n
*************************************************************************/
/** A scope containing all free variable proxies for currently translated
* class, as well as its this$n symbol (if needed).
* Proxy scopes are nested in the same way classes are.
* Inside a constructor, proxies and any this$n symbol are duplicated
* in an additional innermost scope, where they represent the constructor
* parameters.
*/
* exception variables for translated TWR blocks
*/
/** A stack containing the this$n field of the currently translated
* classes (if needed) in innermost first order.
* Inside a constructor, proxies and any this$n symbol are duplicated
* in an additional innermost scope, where they represent the constructor
* parameters.
*/
/** The name of a free variable proxy.
*/
}
/** Proxy definitions for all free variables in given list, in reverse order.
* @param pos The source code position of the definition.
* @param freevars The free variables.
* @param owner The class in which the definitions go.
*/
}
return defs;
}
/** The name of a this$n field
* @param type The class referenced by the this$n field
*/
int nestingLevel = 0;
t = t.getEnclosingType();
nestingLevel++;
}
return result;
}
/** Definition for this$n field.
* @param pos The source code position of the definition.
* @param owner The class in which the definition goes.
*/
return vd;
}
/** Return a list of trees that load the free variables in given list,
* in reverse order.
* @param pos The source code position to be used for the trees.
* @param freevars The list of free variables.
*/
return args;
}
//where
}
/** Construct a tree simulating the expression <C.this>.
* @param pos The source code position to be used for the tree.
* @param c The qualifier class.
*/
if (currentClass == c) {
// in this case, `this' works fine
} else {
// need to go via this$n
return makeOuterThis(pos, c);
}
}
/**
* Optionally replace a try statement with the desugaring of a
* try-with-resources statement. The canonical desugaring of
*
* try ResourceSpecification
* Block
*
* is
*
* {
* final VariableModifiers_minus_final R #resource = Expression;
* Throwable #primaryException = null;
*
* try ResourceSpecificationtail
* Block
* catch (Throwable #t) {
* #primaryException = t;
* throw #t;
* } finally {
* if (#resource != null) {
* if (#primaryException != null) {
* try {
* #resource.close();
* } catch(Throwable #suppressedException) {
* #primaryException.addSuppressed(#suppressedException);
* }
* } else {
* #resource.close();
* }
* }
* }
*
* @param tree The try statement to inspect.
* @return A a desugared try-with-resources tree, or the original
* try block if there are no resources to manage.
*/
else
return result;
}
return block;
// Add resource declaration or expression to block statements
if (resource instanceof JCVariableDecl) {
} else {
}
// Add primaryException declaration
// Create catch clause that saves exception and then rethrows it
}
// primaryException.addSuppressed(catchException);
// try { resource.close(); } catch (e) { primaryException.addSuppressed(e); }
// if (primaryException != null) {try...} else resourceClose;
// if (#resource != null) { if (primaryException ... }
null)));
}
// create resource.close() method invocation
}
}
/** Construct a tree that represents the outer instance
* <C.this>. Never pick the current `this'.
* @param pos The source code position to be used for the tree.
* @param c The qualifier class.
*/
return makeNull();
}
while (otc != c) {
do {
"no.encl.instance.of.type.in.scope",
c);
return tree;
}
return makeNull();
}
}
return tree;
}
/** Construct a tree that represents the closest outer instance
* <C.this> such that the given symbol is a member of C.
* @param pos The source code position to be used for the tree.
* @param sym The accessed symbol.
* @param preciseMatch should we accept a type that is a subtype of
* sym's owner, even if it doesn't contain sym
* due to hiding, overriding, or non-inheritance
* due to protection?
*/
// in this case, `this' works fine
} else {
// need to go via this$n
}
}
/**
* Similar to makeOwnerThis but will never pick "this".
*/
return makeNull();
}
do {
"no.encl.instance.of.type.in.scope",
c);
return tree;
}
}
return tree;
}
/** Return tree simulating the assignment <this.name = name>, where
* name is the name of a free variable.
*/
return
}
/** Return tree simulating the assignment <this.this$n = this$n>.
*/
return
}
/**************************************************************************
* Code for .class
*************************************************************************/
/** Return the symbol of a class to contain a cache of
* compiler-generated statics such as class$ and the
* $assertionsDisabled flag. We create an anonymous nested class
* (unless one already exists) and return its symbol. However,
* for backward compatibility in 1.4 and earlier we use the
* top-level class itself.
*/
}
/** Return symbol for "class$" method. If there is no method definition
* for class$, construct one as follows:
*
* class class$(String x0) {
* try {
* return Class.forName(x0);
* } catch (ClassNotFoundException x1) {
* throw new NoClassDefFoundError(x1.getMessage());
* }
* }
*/
if (classDollarSym == null) {
classDollarSym = new MethodSymbol(
new MethodType(
try {
} catch (CompletionFailure ex) {
}
}
return classDollarSym;
}
/** Generate code for class$(String name). */
// in 1.4.2 and above, we use
// Class.forName(String name, boolean init, ClassLoader loader);
// which requires we cache the current loader in cl$
if (target.classLiteralsNoInit()) {
// clsym = "private static ClassLoader cl$"
// emit "private static ClassLoader cl$;"
// newcache := "new cache$1[0]"
null);
// forNameSym := java.lang.Class.forName(
// String s,boolean init,ClassLoader loader)
// clvalue := "(cl$ == null) ?
// $newcache.getClass().getComponentType().getClassLoader() : cl$"
// returnResult := "{ return Class.forName(param1, false, cl$); }"
clvalue);
returnResult = make.
} else {
// forNameSym := java.lang.Class.forName(String s)
// returnResult := "{ return Class.forName(param1); }"
returnResult = make.
}
// catchParam := ClassNotFoundException e1
if (target.hasInitCause()) {
// rethrow = "throw new NoClassDefFoundError().initCause(e);
} else {
// getMessageSym := ClassNotFoundException.getMessage()
// rethrow = "throw new NoClassDefFoundError(e.getMessage());"
}
// rethrowStmt := "( $rethrow )"
// catchBlock := "catch ($catchParam) $rethrowStmt"
// tryCatch := "try $returnResult $catchBlock"
}
// where
/** Create an attributed tree of the form left.name(). */
}
/** The Name Of The variable to cache T.class values.
* @param sig The signature of type T.
*/
}
}
} else {
}
}
/** The variable symbol that caches T.class values.
* If none exists yet, create a definition.
* @param sig The signature of type T.
* @param pos The position to report diagnostics, if any.
*/
}
return cacheSym;
}
/** The tree simulating a T.class expression.
* @param clazz The tree identifying type T.
*/
}
// replace with <BoxedClass>.TYPE
if (target.hasClassLiterals()) {
}
// replace with <cache == null ? cache = class$(tsig) : cache>
// where
// - <tsig> is the type signature of T,
// - <cache> is the cache variable for tsig.
default:
throw new AssertionError();
}
}
/**************************************************************************
*************************************************************************/
// This code is not particularly robust if the user has
// previously declared a member named '$assertionsDisabled'.
// The same faulty idiom also appears in the translation of
// class literals above. We should report an error if a
// previous declaration is not synthetic.
// Outermost class may be either true class or an interface.
// note that this is a class, as an interface can't contain a statement.
if (assertDisabledSym == null) {
containerDef.pos()),
}
}
/**************************************************************************
* Building blocks for let expressions
*************************************************************************/
interface TreeBuilder {
}
/** Construct an expression using the builder, with the given rval
* expression as an argument to the builder. However, the rval
* expression must be computed only once, even if used multiple
* times in the result of the builder. We do that by
* constructing a "let" expression that saves the rvalue into a
* temporary variable and then uses the temporary variable in
* place of the expression built by the builder. The complete
* resulting expression is of the form
* <pre>
* (let <b>TYPE</b> <b>TEMP</b> = <b>RVAL</b>;
* in (<b>BUILDER</b>(<b>TEMP</b>)))
* </pre>
* where <code><b>TEMP</b></code> is a newly declared variable
* in the let expression.
*/
}
type,
return res;
}
// same as above, with the type of the temporary variable computed
}
// same as above, but for an expression that may be used as either
// an rvalue or an lvalue. This requires special handling for
// Select expressions, where we place the left-hand-side of the
// select in a temporary, and for Indexed expressions, where we
// place both the indexed expression and the index value in temps.
}
});
}
}
});
}
});
}
}
}
throw new AssertionError(lval);
}
// evaluate and discard the first expression, then evaluate the second.
return expr2;
}
});
}
/**************************************************************************
* Translation methods
*************************************************************************/
/** Visitor argument: enclosing operator node.
*/
/** Visitor method: Translate a single node.
* Attach the source position from the old tree to its replacement tree.
*/
return null;
} else {
}
return result;
}
}
/** Visitor method: Translate a single node, boxing or unboxing if needed.
*/
}
/** Visitor method: Translate tree.
*/
this.enclOp = prevEnclOp;
return res;
}
/** Visitor method: Translate list of trees.
*/
this.enclOp = prevEnclOp;
return res;
}
/** Visitor method: Translate list of trees.
*/
return trees;
}
if (needPackageInfoClass(tree)) {
if (target.isPackageInfoSynthetic())
// package-info is marked SYNTHETIC in JDK 1.6 and later releases
c.flags_field |= flags;
}
}
// where
switch (pkginfoOpt) {
case ALWAYS:
return true;
case LEGACY:
case NONEMPTY:
return true;
}
return false;
}
throw new AssertionError();
}
// If this is an enum definition
// If this is a nested class, define a this$n field for
// it and add to proxies.
if (currentClass.hasOuterInstance())
// If this is a local class, define proxies for all its free variables.
// Recursively translate superclass, interfaces.
if (currentClass.isLocal()) {
}
}
// Recursively translate members, taking into account that new members
// might be created during the translation and prepended to the member
// list `tree.defs'.
}
}
// Convert a protected modifier to public, mask static modifier.
// Convert name to flat representation, replacing '.' by '$'.
// Add this$n and free variables proxy definitions to class.
}
if (currentClass.hasOuterInstance()) {
}
// Append translated tree to `translated' queue.
// Return empty block {} as a placeholder for an inner class.
}
/** Translate an enum class. */
// add the supertype, if needed
// classOfType adds a cache field to tree.defs unless
// target.hasClassLiterals().
// process each enumeration constant, adding implicit constructor parameters
int nextOrdinal = 0;
} else {
}
}
// private static final T[] #VALUES = { a, b, c };
if (useClone()) {
// return (T[]) $VALUES.clone();
syms.arrayCloneMethod)));
} else {
// template: T[] $result = new T[$values.length];
null);
// template: System.arraycopy($VALUES, 0, $result, 0, $VALUES.length);
if (systemArraycopyMethod == null) {
}
// template: return $result;
}
if (debugLower)
/** The template for the following code is:
*
* public static E valueOf(String name) {
* return (E)Enum.valueOf(E.class, name);
* }
*
* where E is tree.sym
*/
if (debugLower)
// Add the necessary members for the EnumCompatibleMode
}
}
// where
private boolean useClone() {
try {
}
catch (CompletionFailure e) {
return false;
}
}
/** Translate an enumeration constant and its initializer. */
}
// Add "String $enum$name, int $enum$ordinal" to the beginning of the
// argument list for each constructor of an enum.
"ordinal"),
m.erasure_field = new MethodType(
// Initialize synthetic name field
// Initialize synthetic ordinal field
}
}
try {
} finally {
}
}
//where
(currentClass.isInner() ||
// We are seeing a constructor of an inner class.
// Push a new proxy scope for constructor parameters.
// and create definitions for any this$n and proxy parameters.
if (currentClass.hasOuterInstance())
// Recursively translate result type, parameters and thrown list.
// when compiling stubs, don't process body
return;
}
// Add this$n (if needed) in front of and free variables behind
// constructor parameter list.
if (currentClass.hasOuterInstance())
// If this is an initial constructor, i.e., it does not start with
// this(...), insert initializers for this$n and proxies
// before (pre-1.4, after) the call to superclass constructor.
}
m.erasure_field = new MethodType(
}
if (currentClass.hasOuterInstance() &&
{
}
// pop local variables from proxy stack
// recursively translate following local statements and
// combine with this- or super-call
else
} else {
super.visitMethodDef(tree);
}
}
else
}
// Box arguments, if necessary
// If created class is local, add free variables after
// explicit constructor arguments.
}
// If an access constructor is used, append null as a last argument.
}
// If created class has an outer instance, and new is qualified, pass
// qualifier as first argument. If new is not qualified, pass the
// correct outer instance as first argument.
if (c.hasOuterInstance()) {
// local class
} else {
// nested class
}
}
// If we have an anonymous class, create its flat version, rather
// than the class or interface following new.
} else {
}
}
// Simplify conditionals with known constant controlling expressions.
// This allows us to avoid generating supporting declarations for
// the dead code, which will not be eliminated during code generation.
// Note that Flow.isFalse and Flow.isTrue only return true
// for constant expressions in the sense of JLS 15.27, which
// are guaranteed to have no side-effects. More aggressive
// constant propagation would require that we take care to
// preserve possible side-effects in the condition expression.
/** Visitor method for conditional expressions.
*/
} else {
// Condition is not a compile-time constant.
}
}
//where
return tree;
: pt;
return result;
}
/** Visitor method for if statements.
*/
} else {
}
} else {
// Condition is not a compile-time constant.
}
}
/** Visitor method for assert statements. Translate them away.
*/
cond,
}
result =
null);
} else {
}
}
if (allowEnums &&
// We are seeing a this(...) or super(...) constructor call.
// If an access constructor is used, append null as a last argument.
if (constructor != meth) {
}
// If we are calling a constructor of a local class, add
// free variables after explicit constructor arguments.
}
// If we are calling a constructor of an enum class, pass
// along the name and ordinal arguments
}
// If we are calling a constructor of a class with an outer
// instance, and the call
// is qualified, pass qualifier as first argument in front of
// the explicit constructor arguments. If the call
// is not qualified, pass the correct outer instance as
// first argument.
if (c.hasOuterInstance()) {
// local class or this() call
} else {
// super() call of nested class - never pick 'this'
}
}
} else {
// We are seeing a normal method invocation; translate this as usual.
// If the translated method itself is an Apply tree, we are
// seeing an access method invocation. In this case, append
// the method arguments to the arguments of the access method.
return;
}
}
}
boolean anyChanges = false;
}
if (varargsElement != null) {
anyChanges = true;
}
} else {
if (!anyChanges) return _args;
}
}
/** Expand a boxing or unboxing conversion if needed. */
return tree;
if (havePrimitive) {
} else {
}
} else {
}
return tree;
}
/** Box up a single primitive expression. */
}
/** Box up a single primitive expression. */
if (target.boxWithConstructors()) {
box,
} else {
box,
}
}
/** Unbox an object to a primitive value. */
if (!unboxedType.isPrimitive())
throw new AssertionError(unboxedType);
} else {
// There must be a conversion from unboxedType to primitive.
throw new AssertionError(tree);
}
}
/** Visitor method for parenthesized expressions.
* If the subexpression has changed, omit the parens.
*/
}
}
// If translated left hand side is an Apply, we are
// seeing an access method invocation. In this case, append
// right hand side as last argument of the access method.
} else {
}
}
// boxing required; need to rewrite as x = (unbox typeof x)(x op y);
// or if x == (typeof x)z then z = (unbox typeof x)((typeof x)z op y)
// (but without recomputing x)
// Erasure (TransTypes) can change the type of
// tree.lhs. However, we can still get the
// unerased type of tree.lhs as it is stored
// in tree.type in Attr.
opResult);
}
});
return;
}
// If translated left hand side is an Apply, we are
// seeing an access method invocation. In this case, append
// right hand side as last argument of the access method.
// if operation is a += on strings,
// make sure to convert argument to string
} else {
}
}
/** Lower a tree of the form e++ or e-- where e is an object type */
// translate to tmp1=lval(e); tmp2=tmp1; tmp1 OP 1; tmp2
// or
// translate to tmp1=lval(e); tmp2=tmp1; (typeof tree)tmp1 OP 1; tmp2
// where OP is += or -=
: tmp1;
lhs,
}
});
}
});
}
boolean isUpdateOperator =
// translate to e += 1
// translate to e -= 1
{
return;
}
{
return;
}
}
throw new AssertionError(tree);
}
}
// If translated left hand side is an Apply, we are
// seeing an access method invocation. In this case, return
// that access method invocation as result.
} else {
}
}
return;
}
return;
}
break;
return;
}
return;
}
break;
}
}
}
/** Translate away the foreach loop. */
else
}
// where
/**
* A statement of the form
*
* <pre>
* for ( T v : arrayexpr ) stmt;
* </pre>
*
* (where arrayexpr is of an array type) gets translated to
*
* <pre>
* for ( { arraytype #arr = arrayexpr;
* int #len = array.length;
* int #i = 0; };
* #i < #len; i$++ ) {
* T v = arr$[#i];
* stmt;
* }
* </pre>
*
* where #arr, #len, and #i are freshly named synthetic local variables.
*/
cond,
body));
}
/** Patch up break and continue targets. */
class Patcher extends TreeScanner {
}
}
}
}
/**
* A statement of the form
*
* <pre>
* for ( T v : coll ) stmt ;
* </pre>
*
* (where coll implements Iterable<? extends T>) gets translated to
*
* <pre>
* for ( Iterator<? extends T> #i = coll.iterator(); #i.hasNext(); ) {
* T v = (T) #i.next();
* stmt;
* }
* </pre>
*
* where #i is a freshly named synthetic local variable.
*/
else
cond,
body));
}
if (currentMethodSym == null) {
// A class or instance field initializer.
}
}
if (currentMethodSym == null) {
// Block is a static or instance initializer.
}
super.visitBlock(tree);
}
}
}
}
}
if (enumSwitch) {
} else if (stringSwitch) {
} else {
}
}
ordinalMethod)));
} else {
}
}
return enumSwitch;
}
} else {
/*
* The general approach used is to translate a single
* string switch statement into a series of two chained
* switch statements: the first a synthesized statement
* switching on the argument string's hash value and
* computing a string's position in the list of original
* case labels, if any, followed by a second switch on the
* computed integer value. The second switch has the same
* code structure as the original string switch statement
* except that the string case labels are replaced with
* positional integer constants starting at 0.
*
* The first switch statement can be thought of as an
* inlined map from strings to their position in the case
* label list. An alternate implementation would use an
* actual Map for this purpose, as done for enum switches.
*
* With some additional effort, it would be possible to
* use a single switch statement on the hash code of the
* argument, but care would need to be taken to preserve
* the proper control flow in the presence of hash
* collisions and other complications, such as
* fallthroughs. Switch statements with one or two
* alternatives could also be specially translated into
* if-then statements to omit the computation of the hash
* code.
*
* The generated code assumes that the hashing algorithm
* of String is the same in the compilation environment as
* in the environment the code will run in. The string
* hashing algorithm in the SE JDK has been unchanged
* since at least JDK 1.2. Since the algorithm has been
* specified since that release as well, it is very
* unlikely to be changed in the future.
*
* Different hashing algorithms, such as the length of the
* strings or a perfect hashing algorithm over the
* particular set of case labels, could potentially be
* used instead of String.hashCode.
*/
// Map from String case labels to their original position in
// the list of case labels.
// Map of hash codes to the string case labels having that hashCode.
int casePosition = 0;
} else {
}
}
casePosition++;
}
// Synthesize a switch statement that has the effect of
// mapping from a string to the integer position of that
// string in the list of case labels. This is done by
// switching on the hashCode of the string followed by an
// if-then-else chain comparing the input for equality
// with all the case labels having that hash value.
/*
* s$ = top of stack;
* tmp$ = -1;
* switch($s.hashCode()) {
* case caseLabel.hashCode:
* if (s$.equals("caseLabel_1")
* tmp$ = caseLabelToPosition("caseLabel_1");
* else if (s$.equals("caseLabel_2"))
* tmp$ = caseLabelToPosition("caseLabel_2");
* ...
* break;
* ...
* }
*/
// hashCode will trigger nullcheck on original switch expression
caseBuffer.toList());
elsepart);
}
}
// Make isomorphic switch tree replacing string labels
// with corresponding integer ones from the label to
// position map.
// Rewire up old unlabeled break statements to the
// replacement switch being created.
if (isDefault)
else {
getExpression()).
type.constValue()));
}
oneCase.getStatements()));
}
}
}
}
// need to special case-access of the form C.super.x
// these will always need an access method.
boolean qualifiedSuperAccess =
else
}
}
// There ought to be nothing to rewrite here;
// we don't generate code.
}
} else {
}
}
/**************************************************************************
* main method
*************************************************************************/
/** Translate a toplevel class and return a list consisting of
* the translated class and translated versions of all inner classes.
* @param env The attribution environment current at the class definition.
* We need this for resolving some additional symbols.
* @param cdef The tree representing the class definition.
*/
try {
currentClass = null;
makeAccessible(l.head);
translated = this.translated;
} finally {
// note that recursive invocations of this method fail hard
endPositions = null;
currentClass = null;
this.translated = null;
freevarCache = null;
accessNums = null;
accessSyms = null;
}
return translated.toList();
}
//////////////////////////////////////////////////////////////
// The following contributed by Borland for bootstrapping purposes
//////////////////////////////////////////////////////////////
// Add the special enum fields
// Add the accessor methods for name and ordinal
// Add the toString method
// Add the compareTo method
}
return ordinal;
}
return name;
}
// Add the accessor methods for ordinal
return (MethodSymbol)ordinalSym;
}
// Add the accessor methods for name
return (MethodSymbol)nameSym;
}
if (toStringSym != null)
if (toStringDecl != null)
return (MethodSymbol)toStringSym;
return (MethodSymbol)toStringSym;
}
blockStatements.toList()));
return (MethodSymbol)compareToSym;
}
//////////////////////////////////////////////////////////////
// The above contributed by Borland for bootstrapping purposes
//////////////////////////////////////////////////////////////
}