/* * Janino - An embedded Java[TM] compiler * * Copyright (c) 2001-2010, Arno Unkrig * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the * following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the * following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the * following disclaimer in the documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ package org.codehaus.janino; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import org.codehaus.commons.compiler.CompileException; import org.codehaus.commons.compiler.Location; import org.codehaus.janino.CodeContext.Offset; import org.codehaus.janino.IClass.IMethod; import org.codehaus.janino.Java.FunctionDeclarator.FormalParameter; import org.codehaus.janino.Java.FunctionDeclarator.FormalParameters; import org.codehaus.janino.Visitor.BlockStatementVisitor; import org.codehaus.janino.Visitor.ElementValueVisitor; import org.codehaus.janino.Visitor.TypeArgumentVisitor; import org.codehaus.janino.util.Traverser; import org.codehaus.janino.util.iterator.ReverseListIterator; /** * This wrapper class defines classes that represent the elements of the * Java™ programming language. *
* Notice: *
* 'JLS7' refers to the Java Language Specification, Java SE 7
* Edition.
*/
@SuppressWarnings({ "rawtypes", "unchecked" }) public final
class Java {
private Java() {} // Don't instantiate me.
/** Representation of a Java™ 'scope', e.g. a compilation unit, type, method or block. */
public
interface Scope {
/** @return The scope that encloses this scope, or {@code null} */
Scope getEnclosingScope();
}
/** This interface is implemented by objects which are associated with a location in the source code. */
public
interface Locatable {
/** @return The location of this object */
Location getLocation();
/**
* Throw a {@link CompileException} with the given message and this
* object's location.
*
* @param message The message to report
*/
void throwCompileException(String message) throws CompileException;
}
/** Abstract implementation of {@link Locatable}. */
public abstract static
class Located implements Locatable {
/** Indication of 'no' or 'unknown' location. */
public static final Located NOWHERE = new Located(Location.NOWHERE) {};
private final Location location;
protected
Located(Location location) {
//assert location != null;
this.location = location;
}
// Implement "Locatable".
@Override public Location
getLocation() { return this.location; }
@Override public void
throwCompileException(String message) throws CompileException {
throw new CompileException(message, this.location);
}
}
/** Holds the result of {@link Parser#parseCompilationUnit}. */
public static final
class CompilationUnit implements Scope {
/** A string that explains the 'file' (or similar resource) where this CU was loaded from. */
public final String optionalFileName;
/** The package declaration at the very top of this CU (if any). */
public PackageDeclaration optionalPackageDeclaration;
/** The IMPORT declarations in this CU. */
public final List
* If a synthetic field with the same name exists already, then it must have the same
* type and the redefinition is ignored.
* @param iField
*/
void defineSyntheticField(IClass.IField iField) throws CompileException;
}
/** Abstract implementation of {@link TypeDeclaration}. */
public abstract static
class AbstractTypeDeclaration implements TypeDeclaration {
private final Location location;
private final Modifiers modifiers;
private final List
* This class is mis-named; according to JLS7 8.8.7 and 14.2, its name should be 'BlockStatement'.
*/
public abstract static
class Statement extends Located implements BlockStatement {
private Scope enclosingScope;
protected
Statement(Location location) { super(location); }
// Implement "BlockStatement".
@Override public void
setEnclosingScope(Scope enclosingScope) {
if (this.enclosingScope != null && enclosingScope != this.enclosingScope) {
throw new JaninoRuntimeException(
"Enclosing scope is already set for statement \""
+ this.toString()
+ "\" at "
+ this.getLocation()
);
}
this.enclosingScope = enclosingScope;
}
@Override public Scope
getEnclosingScope() { return this.enclosingScope; }
// Compile time members
/** The map of currently visible local variables. */
public Map
* The statements that the block defines are executed in sequence.
*/
public static final
class Block extends Statement {
/** The list of statements that comprise the body of the block. */
public final List
* According JLS7 14.15, statements that can be terminated abnormally with a "break" statement are
*
* According to the JLS7 14.16, these are "for", "do" and "while".
*/
public abstract static
class ContinuableStatement extends BreakableStatement {
protected
ContinuableStatement(Location location, BlockStatement body) {
super(location);
(this.body = body).setEnclosingScope(this);
}
/**
* This one's filled in by the first CONTINUE statement, and is {@link Offset#set()} by this continuable
* statement.
*/
protected CodeContext.Offset whereToContinue;
/** The body of this continuable statement. */
public final BlockStatement body;
}
/** Representation of the JLS7 14.8 'expression statement'. */
public static final
class ExpressionStatement extends Statement {
/** The rvalue that is evaluated when the statement is executed. */
public final Rvalue rvalue;
public
ExpressionStatement(Rvalue rvalue) throws CompileException {
super(rvalue.getLocation());
if (!(
rvalue instanceof Java.Assignment
|| rvalue instanceof Java.Crement
|| rvalue instanceof Java.MethodInvocation
|| rvalue instanceof Java.SuperclassMethodInvocation
|| rvalue instanceof Java.NewClassInstance
|| rvalue instanceof Java.NewAnonymousClassInstance
)) {
String expressionType = rvalue.getClass().getName();
expressionType = expressionType.substring(expressionType.lastIndexOf('.') + 1);
this.throwCompileException(
expressionType
+ " is not allowed as an expression statement. "
+ "Expressions statements must be one of assignments, method invocations, or object allocations."
);
}
(this.rvalue = rvalue).setEnclosingBlockStatement(this);
}
@Override public String
toString() { return this.rvalue.toString() + ';'; }
// Compile time members:
@Override public void
accept(Visitor.BlockStatementVisitor visitor) { visitor.visitExpressionStatement(this); }
}
/** Representation of the JLS7 14.3 'local class declaration statement'. */
public static final
class LocalClassDeclarationStatement extends Statement {
/** The class declaration that poses the body of the statement. */
public final LocalClassDeclaration lcd;
public
LocalClassDeclarationStatement(Java.LocalClassDeclaration lcd) {
super(lcd.getLocation());
(this.lcd = lcd).setEnclosingScope(this);
}
@Override public String
toString() { return this.lcd.toString(); }
@Override public void
accept(Visitor.BlockStatementVisitor visitor) { visitor.visitLocalClassDeclarationStatement(this); }
}
/** Representation of a JLS7 14.9 IF statement. */
public static final
class IfStatement extends Statement {
/** The condition of the IF statement. */
public final Rvalue condition;
/** The 'then statement', which is executed iff the condition evaluates to TRUE. */
public final BlockStatement thenStatement;
/** The optional ELSE statement, which is executed iff the condition evaluates to FALSE. */
public final BlockStatement optionalElseStatement;
/**
* Notice that the
* This class is special: It does not extend/implement the {@link Atom} subclasses, but overrides {@link Atom}'s
* "{@code to...()}" methods.
*/
public static final
class AmbiguousName extends Lvalue {
/** The first {@link #n} of these identifiers comprise this ambiguous name. */
public final String[] identifiers;
/** @see #identifiers */
public final int n;
public
AmbiguousName(Location location, String[] identifiers) {
this(location, identifiers, identifiers.length);
}
public
AmbiguousName(Location location, String[] identifiers, int n) {
super(location);
this.identifiers = identifiers;
this.n = n;
}
// Override "Atom.toType()".
private Type type;
@Override public Type
toType() {
if (this.type == null) {
String[] is = new String[this.n];
System.arraycopy(this.identifiers, 0, is, 0, this.n);
this.type = new ReferenceType(this.getLocation(), is, null);
this.type.setEnclosingScope(this.getEnclosingBlockStatement());
}
return this.type;
}
// Compile time members.
@Override public String
toString() { return Java.join(this.identifiers, ".", 0, this.n); }
@Override public Lvalue
toLvalue() {
if (this.reclassified != null) { return this.reclassified.toLvalue(); }
return this;
}
@Override public Rvalue
toRvalue() {
if (this.reclassified != null) { return this.reclassified.toRvalue(); }
return this;
}
/** The result of 'ambiguous name resolution' furing compilation. */
Atom reclassified;
@Override public void
accept(Visitor.AtomVisitor visitor) { visitor.visitAmbiguousName(this); }
@Override public void
accept(Visitor.RvalueVisitor visitor) { visitor.visitAmbiguousName(this); }
@Override public void
accept(Visitor.LvalueVisitor visitor) { visitor.visitAmbiguousName(this); }
@Override public void
accept(Visitor.ElementValueVisitor visitor) { visitor.visitAmbiguousName(this); }
}
/** Representation of a JLS7 6.5.2.1.5 'package name'. */
public static final
class Package extends Atom {
/** The complete name of a package, e.g. 'java' or 'java.util'. */
public final String name;
public
Package(Location location, String name) {
super(location);
this.name = name;
}
@Override public String
toString() { return this.name; }
@Override public void
accept(Visitor.AtomVisitor visitor) { visitor.visitPackage(this); }
}
/** Representation of a local variable access -- used during compilation. */
public static final
class LocalVariableAccess extends Lvalue {
/** The local variable that is accessed. */
public final LocalVariable localVariable;
public
LocalVariableAccess(Location location, LocalVariable localVariable) {
super(location);
this.localVariable = localVariable;
}
// Compile time members.
@Override public String
toString() { return this.localVariable.toString(); }
@Override public void
accept(Visitor.LvalueVisitor visitor) { visitor.visitLocalVariableAccess(this); }
@Override public void
accept(Visitor.RvalueVisitor visitor) { visitor.visitLocalVariableAccess(this); }
@Override public void
accept(Visitor.AtomVisitor visitor) { visitor.visitLocalVariableAccess(this); }
@Override public void
accept(ElementValueVisitor visitor) { visitor.visitLocalVariableAccess(this); }
}
/**
* Representation of an access to a field of a class or an interface. (Does not implement the {@link ArrayLength},
* e.g. "myArray.length".)
*/
public static final
class FieldAccess extends Lvalue {
/**
* The left-hand-side of the field access - either a type or an rvalue (which includes all
* lvalues).
*/
public final Atom lhs;
/** The field within the class or instance identified by the {@link #lhs}. */
public final IClass.IField field;
public
FieldAccess(Location location, Atom lhs, IClass.IField field) {
super(location);
this.lhs = lhs;
this.field = field;
}
// Compile time members.
// Implement "Atom".
@Override public String
toString() { return this.lhs.toString() + '.' + this.field.getName(); }
@Override public void
accept(Visitor.AtomVisitor visitor) { visitor.visitFieldAccess(this); }
@Override public void
accept(Visitor.RvalueVisitor visitor) { visitor.visitFieldAccess(this); }
@Override public void
accept(Visitor.LvalueVisitor visitor) { visitor.visitFieldAccess(this); }
@Override public void
accept(ElementValueVisitor visitor) { visitor.visitFieldAccess(this); }
}
/** Representation of the JLS7 10.7 array type 'length' pseudo-member. */
public static final
class ArrayLength extends Rvalue {
/** The rvalue identifying the array to determine the length of. */
public final Rvalue lhs;
public
ArrayLength(Location location, Rvalue lhs) {
super(location);
this.lhs = lhs;
}
// Compile time members.
// Implement "Atom".
@Override public String
toString() { return this.lhs.toString() + ".length"; }
@Override public void
accept(Visitor.AtomVisitor visitor) { visitor.visitArrayLength(this); }
@Override public void
accept(Visitor.RvalueVisitor visitor) { visitor.visitArrayLength(this); }
@Override public void
accept(ElementValueVisitor visitor) { visitor.visitArrayLength(this); }
}
/** Representation of an JLS7 15.8.3 access to the innermost enclosing instance. */
public static final
class ThisReference extends Rvalue {
public
ThisReference(Location location) { super(location); }
// Compile time members.
/** A cache for the type of the instance that 'this' refers to. */
IClass iClass;
// Implement "Atom".
@Override public String
toString() { return "this"; }
@Override public void
accept(Visitor.AtomVisitor visitor) { visitor.visitThisReference(this); }
@Override public void
accept(Visitor.RvalueVisitor visitor) { visitor.visitThisReference(this); }
@Override public void
accept(ElementValueVisitor visitor) { visitor.visitThisReference(this); }
}
/** Representation of an JLS7 15.8.4 access to the current object or an enclosing instance. */
public static final
class QualifiedThisReference extends Rvalue {
/** The qualification left from the 'this' keyword. */
public final Type qualification;
public
QualifiedThisReference(Location location, Type qualification) {
super(location);
if (qualification == null) throw new NullPointerException();
this.qualification = qualification;
}
// Compile time members.
/** The innermost enclosing class declaration. */
ClassDeclaration declaringClass;
/**
* The innermost 'type body declaration' enclosing this 'qualified this reference', i.e. the method,
* type initializer or field initializer.
*/
TypeBodyDeclaration declaringTypeBodyDeclaration;
/** The resolved {@link #qualification}. */
IClass targetIClass;
// Implement "Atom".
@Override public String
toString() { return this.qualification.toString() + ".this"; }
@Override public void
accept(Visitor.AtomVisitor visitor) { visitor.visitQualifiedThisReference(this); }
@Override public void
accept(Visitor.RvalueVisitor visitor) { visitor.visitQualifiedThisReference(this); }
@Override public void
accept(ElementValueVisitor visitor) { visitor.visitQualifiedThisReference(this); }
}
/** Representation of a JLS7 15.8.2 'class literal'. */
public static final
class ClassLiteral extends Rvalue {
/** The type left of the '.class' suffix. */
public final Type type;
public
ClassLiteral(Location location, Type type) {
super(location);
this.type = type;
}
// Implement "Atom".
@Override public String
toString() { return this.type.toString() + ".class"; }
@Override public void
accept(Visitor.AtomVisitor visitor) { visitor.visitClassLiteral(this); }
@Override public void
accept(Visitor.RvalueVisitor visitor) { visitor.visitClassLiteral(this); }
@Override public void
accept(ElementValueVisitor visitor) { visitor.visitClassLiteral(this); }
}
/** Representation of all JLS7 15.26 assignments. */
public static final
class Assignment extends Rvalue {
/** The lvalue to assign to. */
public final Lvalue lhs;
/**
* The assignment operator; either the 'simple assignment operator ('=', JLS7 15.26.1) or one of the 'compound
* assignment operators (JLS7 15.26.2).
*/
public final String operator;
/** The rvalue that is assigned. */
public final Rvalue rhs;
public
Assignment(Location location, Lvalue lhs, String operator, Rvalue rhs) {
super(location);
this.lhs = lhs;
this.operator = operator;
this.rhs = rhs;
}
// Compile time members.
// Implement "Atom".
@Override public String
toString() { return this.lhs.toString() + ' ' + this.operator + ' ' + this.rhs.toString(); }
@Override public void
accept(Visitor.AtomVisitor visitor) { visitor.visitAssignment(this); }
@Override public void
accept(Visitor.RvalueVisitor visitor) { visitor.visitAssignment(this); }
@Override public void
accept(ElementValueVisitor visitor) { visitor.visitAssignment(this); }
}
/** Representation of a JLS7 15.25 'conditional operation'. */
public static final
class ConditionalExpression extends Rvalue {
/** Left-hand side of this conditional operation. */
public final Rvalue lhs;
/** Middle-hand side of this conditional operation. */
public final Rvalue mhs;
/** Right-hand side of this conditional operation. */
public final Rvalue rhs;
public
ConditionalExpression(Location location, Rvalue lhs, Rvalue mhs, Rvalue rhs) {
super(location);
this.lhs = lhs;
this.mhs = mhs;
this.rhs = rhs;
}
// Implement "Atom".
@Override public String
toString() { return this.lhs.toString() + " ? " + this.mhs.toString() + " : " + this.rhs.toString(); }
@Override public void
accept(Visitor.AtomVisitor visitor) { visitor.visitConditionalExpression(this); }
@Override public void
accept(Visitor.RvalueVisitor visitor) { visitor.visitConditionalExpression(this); }
@Override public void
accept(ElementValueVisitor visitor) { visitor.visitConditionalExpression(this); }
}
/**
* Representation of a JLS7 15.14.2 'postfix increment operation', a JLS7 15.14.3 'postfix decrement operation', a
* JLS7 15.15.1 'prefix increment operation' or a JLS7 15.15.2 'prefix decrement operation'.
*/
public static final
class Crement extends Rvalue {
/** Whether this operation is 'pre' (TRUE) or 'post' (FALSE). */
public final boolean pre;
/** The operator; either "++" or "--". */
public final String operator;
/** The lvalue to operate upon. */
public final Lvalue operand;
public
Crement(Location location, String operator, Lvalue operand) {
super(location);
this.pre = true;
this.operator = operator;
this.operand = operand;
}
public
Crement(Location location, Lvalue operand, String operator) {
super(location);
this.pre = false;
this.operator = operator;
this.operand = operand;
}
// Compile time members.
// Implement "Atom".
@Override public String
toString() { return this.pre ? this.operator + this.operand : this.operand + this.operator; }
@Override public void
accept(Visitor.AtomVisitor visitor) { visitor.visitCrement(this); }
@Override public void
accept(Visitor.RvalueVisitor visitor) { visitor.visitCrement(this); }
@Override public void
accept(ElementValueVisitor visitor) { visitor.visitCrement(this); }
}
/** Representation of a JLS7 15.13 'array access expression'. */
public static final
class ArrayAccessExpression extends Lvalue {
/** The array to access (must be an {@link Lvalue} if the access is modifying). */
public final Rvalue lhs;
/** The index value to use. */
public final Rvalue index;
public
ArrayAccessExpression(Location location, Rvalue lhs, Rvalue index) {
super(location);
this.lhs = lhs;
this.index = index;
}
// Compile time members:
// Implement "Atom".
@Override public String
toString() { return this.lhs.toString() + '[' + this.index + ']'; }
@Override public void
accept(Visitor.AtomVisitor visitor) { visitor.visitArrayAccessExpression(this); }
@Override public void
accept(Visitor.RvalueVisitor visitor) { visitor.visitArrayAccessExpression(this); }
@Override public void
accept(Visitor.LvalueVisitor visitor) { visitor.visitArrayAccessExpression(this); }
@Override public void
accept(ElementValueVisitor visitor) { visitor.visitArrayAccessExpression(this); }
}
/** Representation of a JLS7 15.11 'field access expression', including the "array length" pseudo field access. */
public static final
class FieldAccessExpression extends Lvalue {
/** {@link Type}, {@link Rvalue} or {@link Lvalue} to operate upon. */
public final Atom lhs;
/** Name of the field within the {@link #lhs} to access. */
public final String fieldName;
public
FieldAccessExpression(Location location, Atom lhs, String fieldName) {
super(location);
this.lhs = lhs;
this.fieldName = fieldName;
}
// Compile time members:
// Implement "Atom".
@Override public String
toString() { return this.lhs.toString() + '.' + this.fieldName; }
@Override public void
accept(Visitor.AtomVisitor visitor) { visitor.visitFieldAccessExpression(this); }
@Override public void
accept(Visitor.RvalueVisitor visitor) { visitor.visitFieldAccessExpression(this); }
@Override public void
accept(Visitor.LvalueVisitor visitor) { visitor.visitFieldAccessExpression(this); }
@Override public void
accept(ElementValueVisitor visitor) { visitor.visitFieldAccessExpression(this); }
/** The {@link ArrayLength} or {@link FieldAccess} resulting from this 'field access expression'. */
Rvalue value;
}
/** Representation of an JLS7 'superclass field access expression', e.g. "super.fld" and "Type.super.fld". */
public static final
class SuperclassFieldAccessExpression extends Lvalue {
/** The optional qualification before '.super.fld'. */
public final Type optionalQualification;
/** The name of the field to access. */
public final String fieldName;
public
SuperclassFieldAccessExpression(Location location, Type optionalQualification, String fieldName) {
super(location);
this.optionalQualification = optionalQualification;
this.fieldName = fieldName;
}
// Compile time members.
// Implement "Atom".
@Override public String
toString() {
return (
this.optionalQualification == null
? "super."
: this.optionalQualification.toString() + ".super."
) + this.fieldName;
}
@Override public void
accept(Visitor.AtomVisitor visitor) { visitor.visitSuperclassFieldAccessExpression(this); }
@Override public void
accept(Visitor.RvalueVisitor visitor) { visitor.visitSuperclassFieldAccessExpression(this); }
@Override public void
accept(Visitor.LvalueVisitor visitor) { visitor.visitSuperclassFieldAccessExpression(this); }
@Override public void
accept(ElementValueVisitor visitor) { visitor.visitSuperclassFieldAccessExpression(this); }
/** The {@link FieldAccess} that implements this {@link FieldAccessExpression}. */
Rvalue value;
}
/**
* Representation of a JLS7 15.15.3 'unary plus operator', a JLS7 15.15.4 'unary minus operator', a JLS7 15.15.5
* 'bitwise complement operator' or a JLS7 15.15.6 'logical complement operator'.
*/
public static final
class UnaryOperation extends BooleanRvalue {
/** The operator (either "+", "-", "~" or "!"). */
public final String operator;
/** The rvalue to operate upon. */
public final Rvalue operand;
public
UnaryOperation(Location location, String operator, Rvalue operand) {
super(location);
this.operator = operator;
this.operand = operand;
}
// Implement "Atom".
@Override public String
toString() { return this.operator + this.operand.toString(); }
@Override public void
accept(Visitor.AtomVisitor visitor) { visitor.visitUnaryOperation(this); }
@Override public void
accept(Visitor.RvalueVisitor visitor) { visitor.visitUnaryOperation(this); }
@Override public void
accept(ElementValueVisitor visitor) { visitor.visitUnaryOperation(this); }
}
/** Representation of a JLS7 15.20.2 'type comparison operation'. */
public static final
class Instanceof extends Rvalue {
/** The rvalue who's type is to be compared. */
public final Rvalue lhs;
/** The type that the {@link #lhs} is checked against. */
public final Type rhs;
public
Instanceof(Location location, Rvalue lhs, Type rhs) {
super(location);
this.lhs = lhs;
this.rhs = rhs;
}
// Compile time members.
// Implement "Atom".
@Override public String
toString() { return this.lhs.toString() + " instanceof " + this.rhs.toString(); }
@Override public void
accept(Visitor.AtomVisitor visitor) { visitor.visitInstanceof(this); }
@Override public void
accept(Visitor.RvalueVisitor visitor) { visitor.visitInstanceof(this); }
@Override public void
accept(ElementValueVisitor visitor) { visitor.visitInstanceof(this); }
}
/**
* Representation of all non-operand-modifying binary operations.
*
* Operations with boolean result:
*
* e.g. byte[12][][] is created with
*
* Allocates an array and initializes its members with (not necessarily
* constant) values.
*/
public static final
class ArrayInitializer extends Located implements ArrayInitializerOrRvalue {
/** The values to assign to the array elements. */
public final ArrayInitializerOrRvalue[] values;
public
ArrayInitializer(Location location, ArrayInitializerOrRvalue[] values) {
super(location);
this.values = values;
}
@Override public String
toString() { return " { (" + this.values.length + " values) }"; }
}
/** The union of {@link ArrayInitializer} and {@link Rvalue}. */
public
interface ArrayInitializerOrRvalue extends Locatable {
}
/** Abstract base class for the various Java™ literals; see JLS7 3.10. */
public abstract static
class Literal extends Rvalue {
/** The text of the literal token, as in the source code. */
public final String value;
/** @param value The text of the literal token, as in the source code */
public Literal(Location location, String value) { super(location); this.value = value; }
// Implement "Atom".
@Override public String
toString() { return this.value; }
}
/** Representation of an "integer literal" (JLS7 3.10.1) (types {@code int} and {@code long}). */
public static final
class IntegerLiteral extends Literal {
public IntegerLiteral(Location location, String value) { super(location, value); }
@Override public void
accept(Visitor.AtomVisitor visitor) { visitor.visitIntegerLiteral(this); }
@Override public void
accept(Visitor.RvalueVisitor visitor) { visitor.visitIntegerLiteral(this); }
@Override public void
accept(ElementValueVisitor visitor) { visitor.visitIntegerLiteral(this); }
}
/** Representation of a "floating-point literal" (JLS7 3.10.2) (types {@code float} and {@code double}). */
public static final
class FloatingPointLiteral extends Literal {
public FloatingPointLiteral(Location location, String value) { super(location, value); }
@Override public void
accept(Visitor.AtomVisitor visitor) { visitor.visitFloatingPointLiteral(this); }
@Override public void
accept(Visitor.RvalueVisitor visitor) { visitor.visitFloatingPointLiteral(this); }
@Override public void
accept(ElementValueVisitor visitor) { visitor.visitFloatingPointLiteral(this); }
}
/** Representation of a "boolean literal" (JLS7 3.10.3) (type {@code boolean}). */
public static final
class BooleanLiteral extends Literal {
public BooleanLiteral(Location location, String value) { super(location, value); }
@Override public void
accept(Visitor.AtomVisitor visitor) { visitor.visitBooleanLiteral(this); }
@Override public void
accept(Visitor.RvalueVisitor visitor) { visitor.visitBooleanLiteral(this); }
@Override public void
accept(ElementValueVisitor visitor) { visitor.visitBooleanLiteral(this); }
}
/** Representation of a "character literal" (JLS7 3.10.4) (type {@code char}). */
public static final
class CharacterLiteral extends Literal {
public CharacterLiteral(Location location, String value) { super(location, value); }
@Override public void
accept(Visitor.AtomVisitor visitor) { visitor.visitCharacterLiteral(this); }
@Override public void
accept(Visitor.RvalueVisitor visitor) { visitor.visitCharacterLiteral(this); }
@Override public void
accept(ElementValueVisitor visitor) { visitor.visitCharacterLiteral(this); }
}
/** Representation of a "string literal" (JLS7 3.10.5) (type {@link String}). */
public static final
class StringLiteral extends Literal {
public StringLiteral(Location location, String value) { super(location, value); }
@Override public void
accept(Visitor.AtomVisitor visitor) { visitor.visitStringLiteral(this); }
@Override public void
accept(Visitor.RvalueVisitor visitor) { visitor.visitStringLiteral(this); }
@Override public void
accept(ElementValueVisitor visitor) { visitor.visitStringLiteral(this); }
}
/** Representation of a "null literal" (JLS7 3.10.7). */
public static final
class NullLiteral extends Literal {
public NullLiteral(Location location, String value) { super(location, value); }
@Override public void
accept(Visitor.AtomVisitor visitor) { visitor.visitNullLiteral(this); }
@Override public void
accept(Visitor.RvalueVisitor visitor) { visitor.visitNullLiteral(this); }
@Override public void
accept(ElementValueVisitor visitor) { visitor.visitNullLiteral(this); }
}
/** This class is not used when code is parsed; it is intended for "programmatic" literals. */
public static final
class SimpleConstant extends Rvalue {
/**
* The value represented by this constant; either {@code null} (representing the {@code null} literal), a
* {@link Byte}, {@link Short}, {@link Integer}, {@link Long}, {@link Float}, {@link Double}, {@link
* Character}, {@link Boolean} or {@link String}.
*
* @see #SimpleConstant(Location)
* @see #SimpleConstant(Location,byte)
* @see #SimpleConstant(Location,short)
* @see #SimpleConstant(Location,int)
* @see #SimpleConstant(Location,long)
* @see #SimpleConstant(Location,float)
* @see #SimpleConstant(Location,double)
* @see #SimpleConstant(Location,char)
* @see #SimpleConstant(Location,boolean)
* @see #SimpleConstant(Location,String)
*/
final Object value;
/** Equivalent of the {@code null} literal. */
public SimpleConstant(Location location) { super(location); this.value = null; }
/** Equivalent of an literal, casted to {@code byte}. */
public SimpleConstant(Location location, byte value) { super(location); this.value = value; }
/** Equivalent of an literal, casted to {@code short}. */
public SimpleConstant(Location location, short value) { super(location); this.value = value; }
/** Equivalent of an {@link IntegerLiteral} with type {@code int}. */
public SimpleConstant(Location location, int value) { super(location); this.value = value; }
/** Equivalent of an {@link IntegerLiteral} with type {@code long}. */
public SimpleConstant(Location location, long value) { super(location); this.value = value; }
/**
* Equivalent of a {@link FloatingPointLiteral} with type {@code float}.
* Notice that this class supports the special values {@link Float#NaN}, {@link Float#NEGATIVE_INFINITY} and
* {@link Float#POSITIVE_INFINITY}, which can not be represented with a {@link FloatingPointLiteral}.
*/
public SimpleConstant(Location location, float value) { super(location); this.value = value; }
/**
* Equivalent of a {@link FloatingPointLiteral} with type {@code double}.
* Notice that this class supports the special values {@link Double#NaN}, {@link Double#NEGATIVE_INFINITY} and
* {@link Double#POSITIVE_INFINITY}, which can not be represented with a {@link FloatingPointLiteral}.
*/
public SimpleConstant(Location location, double value) { super(location); this.value = value; }
/** Equivalent of a {@link CharacterLiteral}. */
public SimpleConstant(Location location, char value) { super(location); this.value = value; }
/** Equivalent of a {@link BooleanLiteral}. */
public SimpleConstant(Location location, boolean value) { super(location); this.value = value; }
/**
* Equivalent of a {@link StringLiteral}, or, if {@code value} is null, the equivalent of a {@link
* NullLiteral}.
*/
public SimpleConstant(Location location, String value) { super(location); this.value = value; }
@Override public void
accept(Visitor.AtomVisitor visitor) { visitor.visitSimpleConstant(this); }
@Override public void
accept(Visitor.RvalueVisitor visitor) { visitor.visitSimpleConstant(this); }
@Override public void
accept(ElementValueVisitor visitor) { visitor.visitSimpleConstant(this); }
@Override public String
toString() { return "[" + this.value + ']'; }
}
/**
* All local variables have a slot number; local variables that get written into the 'localvariabletable'
* also have a start and end offset that defines the variable's extent in the bytecode. If the name is null,
* or variable debugging is not on, then the variable won't be written into the localvariabletable and the
* offsets can be ignored.
*/
public static
class LocalVariableSlot {
private short slotIndex = -1;
private String name;
private final IClass type;
private Offset start, end;
public
LocalVariableSlot(String name, short slotNumber, IClass type) {
this.name = name;
this.slotIndex = slotNumber;
this.type = type;
}
@Override public String
toString() {
StringBuilder buf = new StringBuilder("local var(").append(this.name).append(", ").append(this.slotIndex);
if (this.name != null) {
buf.append(", ").append(this.type);
buf.append(", ").append(this.start.offset);
buf.append(", ").append(this.end.offset);
}
buf.append(")");
return buf.toString();
}
/** @return The 'local variable index' associated with this local variable */
public short getSlotIndex() { return this.slotIndex; }
/** @param slotIndex The 'local variable index' to associate with this local variable */
public void setSlotIndex(short slotIndex) { this.slotIndex = slotIndex; }
/** @return The name of this local variable */
public String getName() { return this.name; }
/** @param name The name of this local variable */
public void setName(String name) { this.name = name; }
/** @return The {@link Offset} from which this local variable is visible */
public Offset getStart() { return this.start; }
/** @param start The {@link Offset} from which this local variable is visible */
public void setStart(Offset start) { this.start = start; }
/** @return The {@link Offset} up to which this local variable is visible */
public Offset getEnd() { return this.end; }
/** @param end The {@link Offset} up to which this local variable is visible */
public void setEnd(Offset end) { this.end = end; }
/** @return the resolved type of this local variable */
public IClass getType() { return this.type; }
}
/** Representation of a local variable while it is in scope during compilation. */
public static
class LocalVariable {
/** Whether this local variable has the FINAL modifier flag. */
public final boolean finaL;
/** The type of this local variable. */
public final IClass type;
/** The slot reserved for this local variable. */
public LocalVariableSlot slot;
public
LocalVariable(boolean finaL, IClass type) {
this.finaL = finaL;
this.type = type;
}
@Override public String
toString() {
StringBuilder sb = new StringBuilder();
if (this.finaL) sb.append("final ");
sb.append(this.type).append(" ");
return sb.toString();
}
/** @param slot The slot to reserve for this local variable */
public void setSlot(LocalVariableSlot slot) { this.slot = slot; }
/** @return The slot reserved for this local variable */
public short
getSlotIndex() {
if (this.slot == null) return -1;
return this.slot.getSlotIndex();
}
}
/** Representation of a JLS7 4.5.1 'wildcard'. */
public static
class Wildcard implements TypeArgument {
/**
* Value for {@link #bounds} indicating that this wildcard has no bounds; {@link #referenceType} is irrelevant
* in this case.
*/
public static final int BOUNDS_NONE = 0;
/** Value for {@link #bounds} indicating that this wildcard has 'extends' bounds. */
public static final int BOUNDS_EXTENDS = 1;
/** Value for {@link #bounds} indicating that this wildcard has 'super' bounds. */
public static final int BOUNDS_SUPER = 2;
/**
* The kind of bounds that this wildcard has.
*
* @see #BOUNDS_NONE
* @see #BOUNDS_EXTENDS
* @see #BOUNDS_SUPER
*/
public final int bounds;
/** The reference type of this wildcard's EXTENDS or SUPER bounds. */
public final ReferenceType referenceType;
public
Wildcard() {
this.bounds = Wildcard.BOUNDS_NONE;
this.referenceType = null;
}
public
Wildcard(int bounds, ReferenceType referenceType) {
assert bounds == Wildcard.BOUNDS_EXTENDS || bounds == Wildcard.BOUNDS_SUPER;
this.bounds = bounds;
assert referenceType != null;
this.referenceType = referenceType;
}
@Override public void
accept(TypeArgumentVisitor visitor) { visitor.visitWildcard(this); }
@Override public String
toString() {
return (
this.bounds == Wildcard.BOUNDS_EXTENDS ? "? extends " + this.referenceType :
this.bounds == Wildcard.BOUNDS_SUPER ? "? super " + this.referenceType :
"?"
);
}
}
/**
* @return {@code null} iff {@code a == null}, or "" iff {@code a.length == 0}, or the elements of {@code a},
* converted to strings concatenated and separated with the {@code separator}
*/
public static String
join(Object[] a, String separator) {
return Java.join(a, separator, 0, a.length);
}
/**
* @return {@code null} iff {@code a == null}, or "" iff {@code off >= len}, or element {@code off ... len-1} of
* {@code a}, converted to strings concatenated and separated with the {@code separator}
*/
public static String
join(Object[] a, String separator, int off, int len) {
if (a == null) return ("(null)");
if (off >= len) return "";
StringBuilder sb = new StringBuilder(a[off].toString());
for (++off; off < len; ++off) {
sb.append(separator);
sb.append(a[off]);
}
return sb.toString();
}
}
null
if a package member type with that name is not declared in this compilation unit
*/
public PackageMemberTypeDeclaration
getPackageMemberTypeDeclaration(String name) {
for (PackageMemberTypeDeclaration pmtd : this.packageMemberTypeDeclarations) {
if (pmtd.getName().equals(name)) return pmtd;
}
return null;
}
/** Represents a 'single-type import declaration' like '{@code import java.util.Map;}'. */
public static
class SingleTypeImportDeclaration extends ImportDeclaration {
/** The identifiers that constitute the type to be imported, e.g. 'java', 'util', 'Map'. */
public final String[] identifiers;
public
SingleTypeImportDeclaration(Location location, String[] identifiers) {
super(location);
this.identifiers = identifiers;
}
@Override public final void
accept(Visitor.ImportVisitor visitor) { visitor.visitSingleTypeImportDeclaration(this); }
@Override public String
toString() { return "import " + Java.join(this.identifiers, ".") + ';'; }
}
/** Represents a type-import-on-demand declaration like {@code import java.util.*;}. */
public static
class TypeImportOnDemandDeclaration extends ImportDeclaration {
/** The identifiers that constitute the package or type to import from, e.g. 'java', 'util'. */
public final String[] identifiers;
public
TypeImportOnDemandDeclaration(Location location, String[] identifiers) {
super(location);
this.identifiers = identifiers;
}
@Override public final void
accept(Visitor.ImportVisitor visitor) {
visitor.visitTypeImportOnDemandDeclaration(this);
}
@Override public String
toString() { return "import " + Java.join(this.identifiers, ".") + ".*;"; }
}
/**
* Represents a single static import declaration like
* import java.util.Collections.EMPTY_MAP;
*/
public static
class SingleStaticImportDeclaration extends ImportDeclaration {
/**
* The identifiers that constitute the member to be imported, e.g. 'java', 'util', 'Collections',
* 'EMPTY_MAP'.
*/
public final String[] identifiers;
public
SingleStaticImportDeclaration(Location location, String[] identifiers) {
super(location);
this.identifiers = identifiers;
}
@Override public final void
accept(Visitor.ImportVisitor visitor) {
visitor.visitSingleStaticImportDeclaration(this);
}
}
/**
* Represents a static-import-on-demand declaration like
* import java.util.Collections.*;
*/
public static
class StaticImportOnDemandDeclaration extends ImportDeclaration {
/** The identifiers that constitute the type to import from, e.g. 'java', 'util', 'Collections'. */
public final String[] identifiers;
public
StaticImportOnDemandDeclaration(Location location, String[] identifiers) {
super(location);
this.identifiers = identifiers;
}
@Override public final void
accept(Visitor.ImportVisitor visitor) {
visitor.visitStaticImportOnDemandDeclaration(this);
}
}
/** Base class for the various IMPORT declarations. */
public abstract static
class ImportDeclaration extends Java.Located {
public
ImportDeclaration(Location location) { super(location); }
/**
* Invokes the '{@code visit...()}' method of {@link Visitor.ImportVisitor} for the concrete {@link
* ImportDeclaration} type.
*/
public abstract void accept(Visitor.ImportVisitor visitor);
}
}
/** Representation of a Java ™ annotation. */
public
interface Annotation extends ElementValue {
/**
* Invokes the '{@code visit...()}' method of {@link Visitor.AnnotationVisitor} for the concrete {@link
* Annotation} type.
*/
void accept(Visitor.AnnotationVisitor visitor);
/** Sets the enclosing scope for this annotation. */
void setEnclosingScope(Scope enclosingScope);
/** @return The type of this annotation */
Type getType();
}
/** Repreentation of a 'marker annotation', i.e. an annotation without any elements in parentheses. */
public static final
class MarkerAnnotation implements Annotation {
/** The type of this marker annotation. */
public final Type type;
public
MarkerAnnotation(Type type) { this.type = type; }
@Override public void
setEnclosingScope(Scope enclosingScope) { this.type.setEnclosingScope(enclosingScope); }
@Override public String toString() { return "@" + this.type; }
@Override public Type
getType() { return this.type; }
@Override public void
accept(Visitor.AnnotationVisitor visitor) { visitor.visitMarkerAnnotation(this); }
@Override public void
accept(Visitor.ElementValueVisitor visitor) { visitor.visitMarkerAnnotation(this); }
}
/**
* Representation of a 'single-element annotation', i.e. an annotation followed by a single element in parentheses.
*/
public static final
class SingleElementAnnotation implements Annotation {
/** The type of this single-element annotation. */
public final Type type;
/** The element value associated with this single-element annotation. */
public final ElementValue elementValue;
public
SingleElementAnnotation(Type type, ElementValue elementValue) {
this.type = type;
this.elementValue = elementValue;
}
@Override public void
setEnclosingScope(Scope enclosingScope) { this.type.setEnclosingScope(enclosingScope); }
@Override public String toString() { return "@" + this.type + '(' + this.elementValue + ')'; }
@Override public Type
getType() { return this.type; }
@Override public void
accept(Visitor.AnnotationVisitor visitor) { visitor.visitSingleElementAnnotation(this); }
@Override public void
accept(Visitor.ElementValueVisitor visitor) { visitor.visitSingleElementAnnotation(this); }
}
/** A 'normal annotation', i.e. an annotation with multiple elements in parentheses and curly braces. */
public static final
class NormalAnnotation implements Annotation {
/** The type of this normal annotation. */
public final Type type;
/** The element-value-pairs associated with this annotation. */
public final ElementValuePair[] elementValuePairs;
public
NormalAnnotation(Type type, ElementValuePair[] elementValuePairs) {
this.type = type;
this.elementValuePairs = elementValuePairs;
}
@Override public Type
getType() { return this.type; }
@Override public String
toString() {
switch (this.elementValuePairs.length) {
case 0: return "@" + this.type + "()";
case 1: return "@" + this.type + "(" + this.elementValuePairs[0] + ")";
default: return "@" + this.type + "(" + this.elementValuePairs[0] + ", ...)";
}
}
@Override public void
setEnclosingScope(Scope enclosingScope) { this.setEnclosingScope(enclosingScope); }
@Override public void
accept(Visitor.AnnotationVisitor visitor) { visitor.visitNormalAnnotation(this); }
@Override public void
accept(Visitor.ElementValueVisitor visitor) { visitor.visitNormalAnnotation(this); }
}
/** Representation of the modifier flags and annotations that are associated with a declaration. */
public static
class Modifiers {
/** The or'ed constants declared in {@link Mod}. */
public final short flags;
/** The annotations. */
public final Annotation[] annotations;
/** A 'blank' {@link Modifiers} object: No flags, no annotations. */
public
Modifiers() {
this.flags = Mod.NONE;
this.annotations = new Annotation[0];
}
public
Modifiers(short modifiers) {
this.flags = modifiers;
this.annotations = new Annotation[0];
}
public
Modifiers(short modifiers, Annotation[] annotations) {
this.flags = modifiers;
this.annotations = annotations;
}
/** @return This object, with the given {@code modifiersToAdd} added. */
public Modifiers
add(int modifiersToAdd) {
return new Modifiers((short) (this.flags | modifiersToAdd), this.annotations);
}
/** @return This object, with the given {@code modifiersToRemove} removed. */
public Modifiers
remove(int modifiersToRemove) {
return new Modifiers((short) (this.flags & ~modifiersToRemove), this.annotations);
}
/**
* @param newAccess One of {@link Mod#PUBLIC}, {@link Mod#PRIVATE}, {@link Mod#PROTECTED}, {@link Mod#PACKAGE}
* @return This object, with the access changed to {@code newAccess}
*/
public Modifiers
changeAccess(int newAccess) {
return new Modifiers((short) (this.flags & ~Mod.PPP | newAccess), this.annotations);
}
}
/** Representation of a 'name = value' element in a {@link NormalAnnotation}. */
public static
class ElementValuePair {
/** The element name. */
public final String identifier;
/** The element value. */
public final ElementValue elementValue;
public
ElementValuePair(String identifier, ElementValue elementValue) {
this.identifier = identifier;
this.elementValue = elementValue;
}
@Override public String
toString() { return this.identifier + " = " + this.elementValue; }
}
/** Base of the possible element values in a {@link NormalAnnotation}. */
public
interface ElementValue {
/**
* Invokes the '{@code visit...()}' method of {@link Visitor.ElementValueVisitor} for the concrete {@link
* ElementValue} type.
*/
void accept(Visitor.ElementValueVisitor visitor);
}
/**
* An element value in the form of an array initializer, e.g. 'SuppressWarnings({ "null", "unchecked"
* })
'.
*/
public static
class ElementValueArrayInitializer implements ElementValue {
/** The element values in the body of the array initializer. */
public final ElementValue[] elementValues;
public
ElementValueArrayInitializer(ElementValue[] elementValues) {
this.elementValues = elementValues;
}
@Override public String
toString() {
switch (this.elementValues.length) {
case 0: return "{}";
case 1: return "{ " + this.elementValues[0] + " }";
default: return "{ " + this.elementValues[0] + ", ... }";
}
}
@Override public void
accept(Visitor.ElementValueVisitor visitor) { visitor.visitElementValueArrayInitializer(this); }
}
/** Representation of a package declaration like {@code package com.acme.tools;}. */
public static
class PackageDeclaration extends Located {
/** The package name, e.g. '{@code com.acme.tools}'. */
public final String packageName;
public
PackageDeclaration(Location location, String packageName) {
super(location);
this.packageName = packageName;
}
}
/** Base for the various kinds of type declarations, e.g. top-level class, member interface, local class. */
public
interface TypeDeclaration extends Locatable, Scope {
/** @return The or'ed modifier flags of the type, as defined in {@link Mod} */
short getModifierFlags();
/** @return The annotations of this {@link TypeDeclaration} */
Annotation[] getAnnotations();
/**
* Return the member type with the given name.
* @return null
if a member type with that name is not declared
*/
MemberTypeDeclaration getMemberTypeDeclaration(String name);
/** @return The (possibly empty) set of member types declared inside this {@link TypeDeclaration} */
Collectionnull
if a method with this name is not declared
*/
MethodDeclarator getMethodDeclaration(String name);
/**
* @return The list of methods declared in this {@link TypeDeclaration}, not including methods declared in
* supertypes
*/
List/** ...
* */
').
*/
public
interface DocCommentable {
/** @return The doc comment of the object or {@code null} */
String getDocComment();
/**
* Returns true
if the object has a doc comment and
* the @deprecated
tag appears in the doc
* comment.
*/
boolean hasDeprecatedDocTag();
}
/**
* Represents a class or interface declaration on compilation unit level. These are called "package member types"
* because they are immediate members of a package.
*/
public
interface PackageMemberTypeDeclaration extends NamedTypeDeclaration {
/** Sets the {@link CompilationUnit} in which this top-level type is declared. */
void setDeclaringCompilationUnit(CompilationUnit declaringCompilationUnit);
/** @return The {@link CompilationUnit} in which this top-level type is declared. */
CompilationUnit getDeclaringCompilationUnit();
}
/**
* Represents a class or interface declaration where the immediately enclosing scope is
* another class or interface declaration.
*/
public interface MemberTypeDeclaration extends NamedTypeDeclaration, TypeBodyDeclaration {}
/**
* Represents the declaration of a class or an interface that has a name. (All type
* declarations are named, except for anonymous classes.)
*/
public
interface NamedTypeDeclaration extends TypeDeclaration {
/** @return The declared (not the fully qualified) name of the class or interface */
String getName();
/** @return The declared type parameters */
TypeParameter[] getOptionalTypeParameters();
}
/**
* Represents the declaration of an inner class, i.e. a class that exists in the context of
* zero or more "enclosing instances". These are anonymous classes, local classes and member
* classes.
*/
interface InnerClassDeclaration extends TypeDeclaration {
/**
* Inner classes have zero or more synthetic fields that hold references to their enclosing
* context:
*
*
* Notice that these fields are not included in the {@link IClass.IField} array returned
* by {@link IClass#getDeclaredIFields2()}.
* this$n
n
is
* N-1 for the Nth nesting level; e.g. the public non-static member class of a
* package member class has a synthetic field this$0
.
* val$local-variable-name
final
local variables of the defining context.
*
*
*/
public
interface TypeBodyDeclaration extends Locatable, Scope {
/** Sets the type declaration that this declaration belongs to. */
void setDeclaringType(TypeDeclaration declaringType);
/** @return The type declaration that this declaration belongs to. */
TypeDeclaration getDeclaringType();
/** @return Whether this declaration has the STATIC modifier */
boolean isStatic();
/**
* Invokes the '{@code visit...()}' method of {@link Visitor.TypeBodyDeclarationVisitor} for the concrete
* {@link TypeBodyDeclaration} type.
*/
void accept(Visitor.TypeBodyDeclarationVisitor visitor);
}
/** Abstract implementation of {@link TypeBodyDeclaration}. */
public abstract static
class AbstractTypeBodyDeclaration extends Located implements TypeBodyDeclaration {
private TypeDeclaration declaringType;
/** Whether this declaration has the STATIC modifier */
public final boolean statiC;
protected
AbstractTypeBodyDeclaration(Location location, boolean statiC) {
super(location);
this.statiC = statiC;
}
// Implement TypeBodyDeclaration.
@Override public void
setDeclaringType(TypeDeclaration declaringType) {
if (this.declaringType != null && declaringType != null) {
throw new JaninoRuntimeException(
"Declaring type for type body declaration \""
+ this.toString()
+ "\"at "
+ this.getLocation()
+ " is already set"
);
}
this.declaringType = declaringType;
}
@Override public TypeDeclaration
getDeclaringType() { return this.declaringType; }
@Override public boolean
isStatic() { return this.statiC; }
/** Forward-implements {@link BlockStatement#setEnclosingScope(Java.Scope)}. */
public void
setEnclosingScope(Scope enclosingScope) { this.declaringType = (TypeDeclaration) enclosingScope; }
// Implement 'Scope'.
@Override public Scope
getEnclosingScope() { return this.declaringType; }
}
/** Representation of an 'instance initializer' (JLS7 8.6) or 'static initializer' (JLS7 8.7). */
public static final
class Initializer extends AbstractTypeBodyDeclaration implements BlockStatement {
/** The block that poses the initializer. */
public final Block block;
public
Initializer(Location location, boolean statiC, Block block) {
super(location, statiC);
(this.block = block).setEnclosingScope(this);
}
@Override public String
toString() { return this.statiC ? "static " + this.block : this.block.toString(); }
// Implement BlockStatement.
@Override public void
accept(Visitor.TypeBodyDeclarationVisitor visitor) { visitor.visitInitializer(this); }
@Override public void
accept(Visitor.BlockStatementVisitor visitor) { visitor.visitInitializer(this); }
@Override public Java.LocalVariable
findLocalVariable(String name) { return this.block.findLocalVariable(name); }
}
/** Abstract base class for {@link Java.ConstructorDeclarator} and {@link Java.MethodDeclarator}. */
public abstract static
class FunctionDeclarator extends AbstractTypeBodyDeclaration implements DocCommentable {
private final String optionalDocComment;
/** The {@link Modifiers} of this declarator. */
public final Modifiers modifiers;
/** The return type of the function (VOID for constructors). */
public final Type type;
/** The name of the function ("
*
*/
public abstract static
class BreakableStatement extends Statement {
protected
BreakableStatement(Location location) { super(location); }
/**
* This one's filled in by the first BREAK statement, and is {@link Offset#set()} by this breakable statement.
*/
CodeContext.Offset whereToBreak;
}
/**
* Base class for statements that support the 'continue' statement.
* elseStatement
is mandatory; for an if statement without
* an "else" clause, a dummy {@link Java.EmptyStatement} should be passed.
*/
public
IfStatement(
Location location,
Rvalue condition,
BlockStatement thenStatement,
BlockStatement optionalElseStatement
) {
super(location);
(this.condition = condition).setEnclosingBlockStatement(this);
(this.thenStatement = thenStatement).setEnclosingScope(this);
this.optionalElseStatement = optionalElseStatement;
if (optionalElseStatement != null) optionalElseStatement.setEnclosingScope(this);
}
@Override public String
toString() { return this.optionalElseStatement == null ? "if" : "if ... else"; }
// Compile time members:
@Override public void
accept(Visitor.BlockStatementVisitor visitor) { visitor.visitIfStatement(this); }
}
/** Representation of a JLS7 14.14.1 'basic FOR statement'. */
public static final
class ForStatement extends ContinuableStatement {
/** The optional 'init' part of the 'basic FOR statement'. */
public final BlockStatement optionalInit;
/** The optional 'condition' part of the 'basic FOR statement'. */
public final Rvalue optionalCondition;
/** The optional 'update' part of the 'basic FOR statement'. */
public final Rvalue[] optionalUpdate;
public
ForStatement(
Location location,
BlockStatement optionalInit,
Rvalue optionalCondition,
Rvalue[] optionalUpdate,
BlockStatement body
) {
super(location, body);
this.optionalInit = optionalInit;
if (optionalInit != null) optionalInit.setEnclosingScope(this);
this.optionalCondition = optionalCondition;
if (optionalCondition != null) optionalCondition.setEnclosingBlockStatement(this);
this.optionalUpdate = optionalUpdate;
if (optionalUpdate != null) for (Rvalue rv : optionalUpdate) rv.setEnclosingBlockStatement(this);
}
@Override public String
toString() { return "for (...; ...; ...) ..."; }
// Compile time members:
@Override public void
accept(Visitor.BlockStatementVisitor visitor) { visitor.visitForStatement(this); }
}
/** Representation of a JLS7 14.14.2 'enhanced FOR statement'. */
public static final
class ForEachStatement extends ContinuableStatement {
/** The 'current element local variable declaration' part of the 'enhanced FOR statement'. */
public final FormalParameter currentElement;
/** The 'expression' part of the 'enhanced FOR statement'. */
public final Rvalue expression;
public
ForEachStatement(Location location, FormalParameter currentElement, Rvalue expression, BlockStatement body) {
super(location, body);
(this.currentElement = currentElement).type.setEnclosingScope(this);
(this.expression = expression).setEnclosingBlockStatement(this);
}
@Override public String
toString() { return "for (... : ...) ..."; }
// Compile time members:
@Override public void
accept(Visitor.BlockStatementVisitor visitor) { visitor.visitForEachStatement(this); }
}
/** Representation of the JLS7 14.2 WHILE statement. */
public static final
class WhileStatement extends ContinuableStatement {
/** The 'condition' of the WHILE statement. */
public final Rvalue condition;
public
WhileStatement(Location location, Rvalue condition, BlockStatement body) {
super(location, body);
(this.condition = condition).setEnclosingBlockStatement(this);
}
@Override public String
toString() { return "while (" + this.condition + ") " + this.body + ';'; }
// Compile time members:
@Override public void
accept(Visitor.BlockStatementVisitor visitor) { visitor.visitWhileStatement(this); }
}
/** Representation of a JLS7 14.20 TRY statement. */
public static final
class TryStatement extends Statement {
/** The body of the TRY statement. */
public final BlockStatement body;
/** The list of catch clauses (including the 'default' clause) of the TRY statement. */
public final List
*
* Operations with non-boolean result:
*
*
*/
public static final
class BinaryOperation extends BooleanRvalue {
/** The left hand side operand. */
public final Rvalue lhs;
/** The operator; one of thos described in {@link BinaryOperation}. */
public final String op;
/** The right hand side operand. */
public final Rvalue rhs;
public
BinaryOperation(Location location, Rvalue lhs, String op, Rvalue rhs) {
super(location);
this.lhs = lhs;
this.op = op;
this.rhs = rhs;
}
// Compile time members.
// Implement "Atom".
@Override public String
toString() { return this.lhs.toString() + ' ' + this.op + ' ' + this.rhs.toString(); }
/** Returns an {@link Iterator} over a left-to-right sequence of {@link Java.Rvalue}s. */
public Iterator
* new NewArray(
* null,
* Java.BasicType(NULL, Java.BasicType.BYTE),
* new Rvalue[] { new Java.Literal(null, Integer.valueOf(12) },
* 2
* )
*
*
* @param location the location of this element
* @param type the base type of the array
* @param dimExprs sizes for dimensions being allocated with specific sizes
* @param dims the number of dimensions that are not yet allocated
*/
public
NewArray(Location location, Type type, Rvalue[] dimExprs, int dims) {
super(location);
this.type = type;
this.dimExprs = dimExprs;
this.dims = dims;
}
// Implement "Atom".
@Override public String
toString() { return "new " + this.type.toString() + "[]..."; }
@Override public void
accept(Visitor.AtomVisitor visitor) { visitor.visitNewArray(this); }
// Implement "Rvalue".
@Override public void
accept(Visitor.RvalueVisitor visitor) { visitor.visitNewArray(this); }
@Override public void
accept(ElementValueVisitor visitor) { visitor.visitNewArray(this); }
}
/** Representation of a JLS7 15.10 'array creation expression'. */
public static final
class NewInitializedArray extends Rvalue {
/** The array type to be instantiated. */
public final ArrayType arrayType;
/** The (mandatory) initializer for the array. */
public final ArrayInitializer arrayInitializer;
/** The resolved {@link #arrayType}. */
public final IClass arrayIClass;
public
NewInitializedArray(Location location, ArrayType arrayType, ArrayInitializer arrayInitializer) {
super(location);
this.arrayType = arrayType;
this.arrayInitializer = arrayInitializer;
this.arrayIClass = null;
}
NewInitializedArray(Location location, IClass arrayIClass, ArrayInitializer arrayInitializer) {
super(location);
this.arrayType = null;
this.arrayInitializer = arrayInitializer;
this.arrayIClass = arrayIClass;
}
// Implement "Atom".
@Override public String
toString() { return "new " + this.arrayType.toString() + " { ... }"; }
@Override public void
accept(Visitor.AtomVisitor visitor) { visitor.visitNewInitializedArray(this); }
// Implement "Rvalue".
@Override public void
accept(Visitor.RvalueVisitor visitor) { visitor.visitNewInitializedArray(this); }
@Override public void
accept(ElementValueVisitor visitor) { visitor.visitNewInitializedArray(this); }
}
/**
* Representation of a JLS7 10.6 'array initializer'.
*