/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.visage.tools.comp;
import java.io.OutputStreamWriter;
import com.sun.tools.mjavac.code.*;
import com.sun.tools.mjavac.code.BoundKind;
import com.sun.tools.mjavac.code.Flags;
import com.sun.tools.mjavac.code.Kinds;
import com.sun.tools.mjavac.code.Symbol;
import com.sun.tools.mjavac.code.Symbol.*;
import com.sun.tools.mjavac.code.Type;
import com.sun.tools.mjavac.code.Type.*;
import com.sun.tools.mjavac.code.TypeTags;
import com.sun.tools.mjavac.tree.JCTree;
import com.sun.tools.mjavac.tree.JCTree.JCAnnotation;
import com.sun.tools.mjavac.tree.JCTree.JCClassDecl;
import com.sun.tools.mjavac.tree.JCTree.JCExpression;
import com.sun.tools.mjavac.tree.JCTree.JCIdent;
import com.sun.tools.mjavac.tree.JCTree.JCMethodDecl;
import com.sun.tools.mjavac.tree.JCTree.JCMethodInvocation;
import com.sun.tools.mjavac.tree.JCTree.JCModifiers;
import com.sun.tools.mjavac.tree.JCTree.JCStatement;
import com.sun.tools.mjavac.tree.JCTree.JCTypeParameter;
import com.sun.tools.mjavac.tree.JCTree.JCVariableDecl;
import com.sun.tools.mjavac.tree.Pretty;
import com.sun.tools.mjavac.tree.TreeMaker;
import com.sun.tools.mjavac.util.Context;
import com.sun.tools.mjavac.util.List;
import com.sun.tools.mjavac.util.ListBuffer;
import com.sun.tools.mjavac.util.Name;
import com.sun.tools.mjavac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.mjavac.util.Log;
import com.sun.tools.mjavac.util.Position;
import org.visage.tools.code.VisageFlags;
import org.visage.tools.code.VisageSymtab;
import org.visage.tools.code.VisageTypeRepresentation;
import org.visage.tools.code.VisageTypes;
import org.visage.tools.code.VisageVarSymbol;
import static org.visage.tools.comp.VisageDefs.*;
import org.visage.tools.tree.*;
import com.sun.tools.mjavac.tree.JCTree.JCAssert;
import com.sun.tools.mjavac.tree.JCTree.JCBlock;
import com.sun.tools.mjavac.tree.JCTree.JCCatch;
import com.sun.tools.mjavac.util.Options;
import java.util.Set;
import java.util.HashSet;
/**
* Common support routines needed for translation
*
* @author Robert Field
* @author Jim Laskey
*/
public abstract class VisageTranslationSupport {
protected final VisageDefs defs;
protected final Log log;
protected final VisageTreeMaker visagemake;
protected final TreeMaker make; // translation should yield a Java AST, use visagemake when building Visage trees
protected final Name.Table names;
protected final VisageResolve rs;
protected final VisageSymtab syms;
protected final VisageTypes types;
protected final Options options;
protected final VisagePreTranslationSupport preTrans;
/*
* other instance information
*/
private int syntheticNameCounter = 0;
protected VisageTranslationSupport(Context context) {
make = TreeMaker.instance(context);
visagemake = VisageTreeMaker.instance(context);
log = Log.instance(context);
names = Name.Table.instance(context);
types = VisageTypes.instance(context);
syms = (VisageSymtab)VisageSymtab.instance(context);
rs = VisageResolve.instance(context);
defs = VisageDefs.instance(context);
options = Options.instance(context);
preTrans = VisagePreTranslationSupport.instance(context);
syntheticNameCounter = 0;
}
public static class NotYetImplementedException extends RuntimeException {
NotYetImplementedException(String msg) {
super(msg);
}
}
static JCExpression TODO(String msg) {
throw new NotYetImplementedException("Not yet implemented: " + msg);
}
protected Symbol expressionSymbol(VisageExpression tree) {
if (tree == null) {
return null;
}
switch (tree.getVisageTag()) {
case IDENT:
return ((VisageIdent) tree).sym;
case SELECT:
return ((VisageSelect) tree).sym;
case TYPECAST:
//TODO: This is suspicious -- expressionSymbol should return
// a symbol which fully represents the expression. This is lossy.
return expressionSymbol(((VisageTypeCast)tree).getExpression());
default:
return null;
}
}
protected VisageVarSymbol varSymbol(VisageExpression tree) {
if (tree == null) {
return null;
}
Symbol sym;
switch (tree.getVisageTag()) {
case IDENT:
sym = ((VisageIdent) tree).sym;
break;
case SELECT:
sym = ((VisageSelect) tree).sym;
break;
default:
return null;
}
if (sym instanceof VisageVarSymbol)
return (VisageVarSymbol) sym;
else
return null;
}
protected boolean isValueFromJava(final VisageExpression expr) {
// The value could come from Java if it is a variable, or a function result.
Symbol sym = expressionSymbol(expr);
if (sym != null && !types.isVisageClass(sym.owner)) {
return true;
}
// test for function
if (expr.getVisageTag() == VisageTag.APPLY) {
VisageExpression func = ((VisageFunctionInvocation)expr).getMethodSelect();
if (isValueFromJava(func)) {
return true;
}
}
return false;
}
boolean hasSideEffects(VisageExpression expr) {
class SideEffectScanner extends VisageTreeScanner {
boolean hse = false;
private void markSideEffects() {
hse = true;
}
@Override
public void visitBlockExpression(VisageBlock tree) {
markSideEffects(); // maybe doesn't but covers all statements
}
@Override
public void visitUnary(VisageUnary tree) {
markSideEffects();
}
@Override
public void visitAssign(VisageAssign tree) {
markSideEffects();
}
@Override
public void visitAssignop(VisageAssignOp tree) {
markSideEffects();
}
@Override
public void visitInstanciate(VisageInstanciate tree) {
markSideEffects();
}
@Override
public void visitFunctionInvocation(VisageFunctionInvocation tree) {
markSideEffects();
}
@Override
public void visitSelect(VisageSelect tree) {
// Doesn't really have side-effects but the duplicate null checking is awful
// TODO: do this in a cleaner way
markSideEffects();
}
}
SideEffectScanner scanner = new SideEffectScanner();
scanner.scan(expr);
return scanner.hse;
}
/**
* Return the generated interface name corresponding to the class
* */
protected Name interfaceName(VisageClassDeclaration cDecl) {
Name name = cDecl.getName();
if (!cDecl.isMixinClass())
return name;
return names.fromString(name.toString() + mixinClassSuffix);
}
protected boolean isMixinClass(ClassSymbol sym) {
return (sym.flags_field & VisageFlags.MIXIN) != 0;
}
protected boolean isAnonClass(ClassSymbol sym) {
final long flags = (Flags.SYNTHETIC | Flags.FINAL);
return (sym.flags_field & flags) == flags;
}
protected boolean isLocalClass(ClassSymbol sym) {
return sym.owner.kind == Kinds.MTH;
}
protected boolean isBoundFuncClass(ClassSymbol sym) {
return (sym.flags_field & VisageFlags.VISAGE_BOUND_FUNCTION_CLASS) != 0L;
}
protected JCExpression makeIdentifier(DiagnosticPosition diagPos, String str) {
assert str.indexOf('<') < 0 : "attempt to parse a type with 'Identifier'. Use TypeTree";
JCExpression tree = null;
int inx;
int lastInx = 0;
do {
inx = str.indexOf('.', lastInx);
int endInx;
if (inx < 0) {
endInx = str.length();
} else {
endInx = inx;
}
String part = str.substring(lastInx, endInx);
Name partName = names.fromString(part);
tree = tree == null?
make.at(diagPos).Ident(partName) :
make.at(diagPos).Select(tree, partName);
lastInx = endInx + 1;
} while (inx >= 0);
return tree;
}
protected JCExpression makeQualifiedTree(DiagnosticPosition diagPos, String str) {
JCExpression tree = null;
int inx;
int lastInx = 0;
do {
inx = str.indexOf('.', lastInx);
int endInx;
if (inx < 0) {
endInx = str.length();
} else {
endInx = inx;
}
String part = str.substring(lastInx, endInx);
Name partName = names.fromString(part);
tree = tree == null?
makeIdentOfPresetKind(diagPos, partName, Kinds.PCK) :
make.at(diagPos).Select(tree, partName);
lastInx = endInx + 1;
} while (inx >= 0);
return tree;
}
protected JCExpression makeAccessExpression(DiagnosticPosition diagPos, Symbol sym, boolean makeIntf) {
Symbol owner = sym.owner;
Name name = sym.name;
switch (sym.kind) {
case Kinds.PCK:
if (name == null || name == name.table.empty) {
return null;
}
break;
case Kinds.TYP:
if (owner.type != null && owner.type.tag == TypeTags.TYPEVAR) {
throw new RuntimeException("TYPEVAR: " + owner.type);
}
if (makeIntf) {
name = names.fromString(name.toString() + mixinClassSuffix);
}
break;
default:
return null;
}
if (owner != null) {
JCExpression oExpr = makeAccessExpression(diagPos, owner, false);
if (oExpr != null) {
return make.at(diagPos).Select(oExpr, name);
}
}
if (sym.kind == Kinds.PCK) {
return makeIdentOfPresetKind(diagPos, name, Kinds.PCK);
} else {
return make.at(diagPos).Ident(name);
}
}
/**
* Build a Java AST representing the specified type.
* Convert Visage class references to interface references.
* */
public JCExpression makeType(DiagnosticPosition diagPos, Type t) {
return makeType(diagPos, t, true);
}
/**
* Build a Java AST representing the specified type.
* If "makeIntf" is set, convert Visage class references to interface references.
* */
public JCExpression makeType(DiagnosticPosition diagPos, Type t, boolean makeIntf) {
while (t instanceof CapturedType) {
WildcardType wtype = ((CapturedType) t).wildcard;
// A kludge for Class.newInstance (and maybe other cases):
// Applying newinstance of an object of type Class<? extends T>
// should yield an instance of T rather than a ? extends T,
// which would confuse the back-end.
t = wtype.kind == BoundKind.EXTENDS ? wtype.type : wtype;
}
JCExpression texp = makeTypeTreeInner(diagPos, t, makeIntf);
texp.type = t;
return texp;
}
private JCExpression makeTypeTreeInner(DiagnosticPosition diagPos, Type t, boolean makeIntf) {
while (t instanceof CapturedType)
t = ((CapturedType) t).wildcard;
switch (t.tag) {
case TypeTags.CLASS: {
JCExpression texp = null;
boolean isMixin = types.isMixin(t.tsym);
if (makeIntf && isMixin) {
texp = makeAccessExpression(diagPos, t.tsym, true);
} else {
if (t.isCompound()) {
t = types.supertype(t);
}
texp = makeAccessExpression(diagPos, t.tsym, false);
}
// Type outer = t.getEnclosingType();
if (!t.getTypeArguments().isEmpty()) {
List<JCExpression> targs = List.nil();
for (Type ta : t.getTypeArguments()) {
targs = targs.append(makeTypeTreeInner(diagPos, ta, makeIntf));
}
texp = make.at(diagPos).TypeApply(texp, targs);
}
return texp;
}
case TypeTags.BOT: { // it is the null type, punt and make it the Object type
return makeQualifiedTree(diagPos, syms.objectType.tsym.getQualifiedName().toString());
}
case TypeTags.WILDCARD: {
WildcardType wtype = (WildcardType) t;
return make.at(diagPos).Wildcard(make.TypeBoundKind(wtype.kind),
wtype.kind == BoundKind.UNBOUND ? null
: makeTypeTreeInner(diagPos,wtype.type, makeIntf));
}
case TypeTags.ARRAY: {
return make.at(diagPos).TypeArray(makeTypeTreeInner(diagPos,types.elemtype(t), makeIntf));
}
default: {
return make.at(diagPos).Type(t);
}
}
}
/**
* Build a Java AST representing the return type of a function.
* Generate the return type as a Location if "isBound" is set.
* */
public JCExpression makeReturnTypeTree(DiagnosticPosition diagPos, MethodSymbol mth, boolean isBound) {
Type returnType = isBound? syms.visage_PointerType : mth.getReturnType();
return makeType(diagPos, returnType);
}
boolean isValueType(Type type) {
return types.isSequence(type) ||
types.isSameType(type, syms.visage_StringType) ||
types.isSameType(type, syms.visage_DurationType) ||
types.isSameType(type, syms.visage_LengthType) ||
types.isSameType(type, syms.visage_AngleType) ||
types.isSameType(type, syms.visage_ColorType);
}
JCExpression makeDefaultValue(DiagnosticPosition diagPos, Type type) {
return makeDefaultValue(diagPos, types.typeRep(type), type);
}
JCExpression makeDefaultValue(DiagnosticPosition diagPos, VisageVarSymbol vsym) {
return makeDefaultValue(diagPos, vsym.getTypeRepresentation(), vsym.type);
}
JCExpression makeDefaultValue(DiagnosticPosition diagPos, VisageTypeRepresentation typeRep, Type type) {
if (typeRep.isSequence()) {
return accessEmptySequence(diagPos, types.elementType(type));
} else if (typeRep.isObject()) {
if (types.isSameType(type, syms.visage_StringType)) {
return make.Literal("");
}
if (types.isSameType(type, syms.visage_DurationType)) {
return makeQualifiedTree(diagPos, VisageDefs.zero_DurationFieldName);
}
if (types.isSameType(type, syms.visage_LengthType)) {
return makeQualifiedTree(diagPos, VisageDefs.zero_LengthFieldName);
}
if (types.isSameType(type, syms.visage_AngleType)) {
return makeQualifiedTree(diagPos, VisageDefs.zero_AngleFieldName);
}
if (types.isSameType(type, syms.visage_ColorType)) {
return makeQualifiedTree(diagPos, VisageDefs.black_ColorFieldName);
}
// fall through
}
return makeLit(diagPos, type, typeRep.defaultValue());
}
/** Make an attributed tree representing a literal. This will be
* a Literal node.
* @param type The literal's type.
* @param value The literal's value.
*/
JCExpression makeLit(DiagnosticPosition diagPos, Type type, Object value) {
int tag = value==null? TypeTags.BOT : type.tag;
return make.at(diagPos).Literal(tag, value).setType(
tag == TypeTags.BOT? syms.botType : type.constType(value));
}
JCExpression call(DiagnosticPosition diagPos, RuntimeMethod meth, List<JCExpression> typeArgs, List<JCExpression> args) {
JCExpression select = make.at(diagPos).Select(makeQualifiedTree(diagPos, meth.classString), meth.methodName);
return make.at(diagPos).Apply(typeArgs, select, args);
}
JCMethodInvocation call(DiagnosticPosition diagPos, JCExpression receiver, Name methodName, Object args) {
JCExpression expr = null;
if (receiver == null) {
expr = make.at(diagPos).Ident(methodName);
} else {
expr = make.at(diagPos).Select(receiver, methodName);
}
return make.at(diagPos).Apply(List.<JCExpression>nil(), expr, (args == null) ? List.<JCExpression>nil() : (args instanceof List) ? (List<JCExpression>) args : (args instanceof ListBuffer) ? ((ListBuffer<JCExpression>) args).toList() : (args instanceof JCExpression) ? List.<JCExpression>of((JCExpression) args) : null);
}
Name functionInterfaceName(MethodSymbol sym, boolean isBound) {
return functionName(sym, isBound);
}
Name functionName(MethodSymbol sym) {
return functionName(sym, false);
}
Name functionName(MethodSymbol sym, String full, boolean markAsImpl, boolean isBound) {
if (markAsImpl) {
full = full + VisageDefs.implFunctionSuffix;
}
if (isBound) {
full = full + VisageDefs.boundFunctionDollarSuffix + getParameterTypeSuffix(sym);
}
return names.fromString(full);
}
Name functionName(MethodSymbol sym, boolean isBound) {
return functionName(sym, false, isBound);
}
Name functionName(MethodSymbol sym, boolean markAsImpl, boolean isBound) {
if (!markAsImpl && !isBound) {
return sym.name;
}
return functionName(sym, sym.name.toString(), markAsImpl, isBound);
}
Name varMapName(ClassSymbol sym) {
return names.fromString(varMap_VisageObjectFieldPrefix + defs.mangleClassName(sym, true));
}
Name varGetMapName(ClassSymbol sym) {
return names.fromString(varGetMapString + defs.mangleClassName(sym, true));
}
Name attributeOffsetName(Symbol sym) {
return prefixedAttributeName(sym, offset_AttributeFieldPrefix);
}
Name attributeFlagsName(Symbol sym) {
return prefixedAttributeName(sym, flags_AttributeFieldPrefix);
}
Name attributeValueName(Symbol sym) {
return prefixedAttributeName(sym, value_AttributeFieldPrefix);
}
Name attributeGetterName(Symbol sym) {
return prefixedAttributeName(sym, get_AttributeMethodPrefix);
}
Name attributeSetterName(Symbol sym) {
return prefixedAttributeName(sym, set_AttributeMethodPrefix);
}
Name attributeInvalidateName(Symbol sym) {
return prefixedAttributeName(sym, invalidate_AttributeMethodPrefix);
}
Name attributeOnReplaceName(Symbol sym) {
return prefixedAttributeName(sym, onReplace_AttributeMethodPrefix);
}
Name attributeGetMixinName(Symbol sym) {
return prefixedAttributeName(sym, getMixin_AttributeMethodPrefix);
}
Name attributeGetVOFFName(Symbol sym) {
return prefixedAttributeName(sym, getVOFF_AttributeMethodPrefix);
}
Name attributeSetMixinName(Symbol sym) {
return prefixedAttributeName(sym, setMixin_AttributeMethodPrefix);
}
Name attributeGetElementName(Symbol sym) {
return prefixedAttributeName(sym, getElement_AttributeMethodPrefix);
}
Name attributeSizeName(Symbol sym) {
return prefixedAttributeName(sym, size_AttributeMethodPrefix);
}
Name attributeSavedName(Symbol sym) {
return prefixedAttributeName(sym, saved_AttributeFieldPrefix);
}
Name attributeInitVarsName(Symbol sym) {
return prefixedAttributeName(sym, initVars_AttributeMethodPrefix);
}
Name attributeApplyDefaultsName(Symbol sym) {
return prefixedAttributeName(sym, applyDefaults_AttributeMethodPrefix);
}
Name boundFunctionObjectParamName(Name suffix) {
return names.fromString(boundFunctionObjectParamPrefix + suffix);
}
Name boundFunctionVarNumParamName(Name suffix) {
return names.fromString(boundFunctionVarNumParamPrefix + suffix);
}
Name depName(Symbol selector, Symbol sym) {
String selectorString = "";
if (sym.isStatic()) {
selectorString = defs.mangleClassName(sym.owner, false);
} else if (selector != null &&
!(selector instanceof VisageVarSymbol && ((VisageVarSymbol)selector).isSpecial())) {
selectorString = selector.toString();
}
return names.fromString(dep_VisageObjectFieldString + selectorString + "$_$" + sym.toString());
}
Name classDCNT$Name(Symbol classSym) {
return names.fromString(depCount_VisageObjectFieldString + classSym.toString().replace('.', '$'));
}
Name classFCNT$Name(Symbol classSym) {
return names.fromString(funcCount_VisageObjectFieldString + classSym.toString().replace('.', '$'));
}
boolean isBoundFunctionResult(Symbol sym) {
// Is this symbol result var storing bound function's result value?
// Check if the variable is synthetic, type is Pointer and naming convention
// is followed for bound function result value.
return ((sym.flags() & Flags.SYNTHETIC) != 0L) &&
types.isSameType(syms.visage_PointerType, sym.type) &&
sym.name.startsWith(defs.boundFunctionResultName);
}
Name paramOldValueName(VisageOnReplace onReplace) {
return onReplace == null || onReplace.getOldValue() == null ? defs.varOldValue_LocalVarName
: onReplace.getOldValue().getName();
}
Name paramNewValueName(VisageOnReplace onReplace) {
return onReplace == null || onReplace.getNewElements() == null ? defs.varNewValue_ArgName
: onReplace.getNewElements().getName();
}
Name paramStartPosName(VisageOnReplace onReplace) {
return onReplace == null || onReplace.getFirstIndex() == null ? defs.startPos_ArgName
: onReplace.getFirstIndex().getName();
}
Name paramEndPosName(VisageOnReplace onReplace) {
return onReplace == null || onReplace.getLastIndex() == null ||
onReplace.getEndKind() != VisageSequenceSlice.END_EXCLUSIVE ? defs.endPos_ArgName
: onReplace.getLastIndex().getName();
}
Name paramNewElementsLengthName(VisageOnReplace onReplace) {
VisageVar newElements = onReplace == null ? null : onReplace.getNewElements();
if (newElements == null)
return defs.newLength_ArgName;
else
return newElements.sym.name.append(defs.lengthSuffixName);
}
private Name prefixedAttributeName(Symbol sym, String prefix) {
Symbol owner = sym.owner;
if (!types.isVisageClass(owner)) {
return sym.name;
}
VisageVarSymbol vsym = (VisageVarSymbol) sym; //TODO: make parameter a VisageVarSymbol
String sname = sym.name.toString();
// VSGC-2837 - Mixins: script-private vars no longer hidden -- var with same name as
// var in subclass, but with different type fails
if (!vsym.isStatic() && vsym.hasScriptOnlyAccess() && (vsym.isExternallySeen() || types.isMixin(owner))) {
// mangle name to hide it
sname = defs.mangleClassName(owner, false) + '$' + sname;
}
return names.fromString( prefix + sname );
}
private String getParameterTypeSuffix(MethodSymbol sym) {
StringBuilder sb = new StringBuilder();
if (sym != null && sym.type != null) {
Type mtype = sym.type;
if (sym.type.tag == TypeTags.FORALL) {
mtype = ((ForAll) mtype).asMethodType();
}
if (mtype.tag == TypeTags.METHOD) {
List<Type> argtypes = ((MethodType) mtype).getParameterTypes();
int argtypesCount = argtypes.length();
int counter = 0;
for (Type argtype : argtypes) {
sb.append(escapeTypeName(types.erasure(argtype)));
if (counter < argtypesCount - 1) {
// Don't append type separator after the last type in the signature.
sb.append(VisageDefs.escapeTypeChar);
// Double separator between type names.
sb.append(VisageDefs.escapeTypeChar);
}
counter++;
}
}
}
return sb.toString();
}
JCExpression accessEmptySequence(DiagnosticPosition diagPos, Type elemType) {
return make.at(diagPos).Select(TypeInfo(diagPos, elemType), defs.emptySequence_FieldName);
}
private String escapeTypeName(Type type) {
return type.toString().replace(VisageDefs.typeCharToEscape, VisageDefs.escapeTypeChar);
}
private JCExpression primitiveTypeInfo(DiagnosticPosition diagPos, Name typeName) {
return make.at(diagPos).Select(makeQualifiedTree(diagPos, cTypeInfo), typeName);
}
/**
* Given type, return an expression whose value is the corresponding TypeInfo.
* @param diagPos
* @param type
* @return expression representing the TypeInfo of the class
*/
JCExpression TypeInfo(DiagnosticPosition diagPos, Type type) {
Type ubType = types.unboxedType(type);
if (ubType.tag != TypeTags.NONE)
type = ubType;
if (types.isSameType(type, syms.visage_BooleanType)) {
return primitiveTypeInfo(diagPos, syms.booleanTypeName);
} else if (types.isSameType(type, syms.visage_CharacterType)) {
return primitiveTypeInfo(diagPos, syms.charTypeName);
} else if (types.isSameType(type, syms.visage_ByteType)) {
return primitiveTypeInfo(diagPos, syms.byteTypeName);
} else if (types.isSameType(type, syms.visage_ShortType)) {
return primitiveTypeInfo(diagPos, syms.shortTypeName);
} else if (types.isSameType(type, syms.visage_IntegerType)) {
return primitiveTypeInfo(diagPos, syms.integerTypeName);
} else if (types.isSameType(type, syms.visage_LongType)) {
return primitiveTypeInfo(diagPos, syms.longTypeName);
} else if (types.isSameType(type, syms.visage_FloatType)) {
return primitiveTypeInfo(diagPos, syms.floatTypeName);
} else if (types.isSameType(type, syms.visage_DoubleType)) {
return primitiveTypeInfo(diagPos, syms.doubleTypeName);
} else if (types.isSameType(type, syms.visage_StringType)) {
return primitiveTypeInfo(diagPos, syms.stringTypeName);
} else if (types.isSameType(type, syms.visage_DurationType)) {
JCExpression fieldRef = make.at(diagPos).Select(makeType(diagPos, type), defs.defaultingTypeInfo_FieldName);
// If TYPE_INFO becomes a Location again, ad back this line
// fieldRef = getLocationValue(diagPos, fieldRef, TYPE_KIND_OBJECT);
return fieldRef;
} else {
assert !type.isPrimitive();
List<JCExpression> typeArgs = List.of(makeType(diagPos, type, true));
return call(diagPos, defs.TypeInfo_getTypeInfo, typeArgs, List.<JCExpression>nil());
}
}
protected Type operationalType(Type srcType) {
switch (srcType.tag) {
case TypeTags.BYTE:
case TypeTags.SHORT:
return syms.intType;
default:
return srcType;
}
}
protected abstract String getSyntheticPrefix();
Name getSyntheticName(String kind) {
return names.fromString(getSyntheticPrefix() + syntheticNameCounter++ + kind);
}
public Name indexVarName(VisageForExpressionInClause clause) {
return indexVarName(clause.getVar().getName(), names);
}
public Name indexVarName(VisageIdent var) {
return indexVarName(var.getName(), names);
}
public static Name indexVarName(Name name, Name.Table names) {
return names.fromString("$indexof$" + name.toString());
}
JCIdent makeIdentOfPresetKind(DiagnosticPosition diagPos, Name name, int pkind) {
AugmentedJCIdent id = new AugmentedJCIdent(name, pkind);
id.pos = (diagPos == null ? Position.NOPOS : diagPos.getStartPosition());
return id;
}
protected JCModifiers addAccessAnnotationModifiers(DiagnosticPosition diagPos, long flags, JCModifiers mods, List<JCAnnotation> annotations) {
make.at(diagPos);
JCModifiers ret = mods;
if ((flags & Flags.PUBLIC) != 0) {
annotations = annotations.prepend(make.Annotation(makeIdentifier(diagPos, VisageSymtab.publicAnnotationClassNameString), List.<JCExpression>nil()));
}
else if ((flags & Flags.PROTECTED) != 0) {
annotations = annotations.prepend(make.Annotation(makeIdentifier(diagPos, VisageSymtab.protectedAnnotationClassNameString), List.<JCExpression>nil()));
}
else if ((flags & Flags.PRIVATE) != 0) {
annotations = annotations.prepend(make.Annotation(makeIdentifier(diagPos, VisageSymtab.privateAnnotationClassNameString), List.<JCExpression>nil()));
}
else if ((flags & VisageFlags.SCRIPT_PRIVATE) != 0) {
annotations = annotations.prepend(make.Annotation(makeIdentifier(diagPos, VisageSymtab.scriptPrivateAnnotationClassNameString), List.<JCExpression>nil()));
}
else { // otherwise it is package access
annotations = annotations.prepend(make.Annotation(makeIdentifier(diagPos, VisageSymtab.packageAnnotationClassNameString), List.<JCExpression>nil()));
}
if ((flags & VisageFlags.DEFAULT) != 0) {
annotations = annotations.prepend(make.Annotation(makeIdentifier(diagPos, VisageSymtab.defaultAnnotationClassNameString), List.<JCExpression>nil()));
}
if ((flags & VisageFlags.PUBLIC_INIT) != 0) {
annotations = annotations.prepend(make.Annotation(makeIdentifier(diagPos, VisageSymtab.publicInitAnnotationClassNameString), List.<JCExpression>nil()));
}
if ((flags & VisageFlags.PUBLIC_READ) != 0) {
annotations = annotations.prepend(make.Annotation(makeIdentifier(diagPos, VisageSymtab.publicReadAnnotationClassNameString), List.<JCExpression>nil()));
}
if ((flags & VisageFlags.IS_DEF) != 0) {
annotations = annotations.prepend(make.Annotation(makeIdentifier(diagPos, VisageSymtab.defAnnotationClassNameString), List.<JCExpression>nil()));
}
if ((flags & Flags.STATIC) != 0) {
annotations = annotations.prepend(make.Annotation(makeIdentifier(diagPos, VisageSymtab.staticAnnotationClassNameString), List.<JCExpression>nil()));
}
if (annotations.nonEmpty()) {
ret = make.Modifiers(mods.flags, annotations);
}
return ret;
}
protected JCModifiers addAccessAnnotationModifiers(DiagnosticPosition diagPos, long flags, JCModifiers mods) {
return addAccessAnnotationModifiers(diagPos, flags, mods, List.<JCAnnotation>nil());
}
protected JCModifiers addInheritedAnnotationModifiers(DiagnosticPosition diagPos, long flags, JCModifiers mods) {
return make.Modifiers(mods.flags, List.of(make.Annotation(makeIdentifier(diagPos, VisageSymtab.inheritedAnnotationClassNameString), List.<JCExpression>nil())));
}
protected void pretty(JCTree tree) {
OutputStreamWriter osw = new OutputStreamWriter(System.out);
Pretty pretty = new Pretty(osw, false);
try {
pretty.println();
pretty.print("+++++++++++++++++++++++++++++++++");
pretty.println();
pretty.printExpr(tree);
pretty.println();
pretty.print("---------------------------------");
pretty.println();
osw.flush();
}catch(Exception ex) {
System.err.println("Pretty print got: " + ex);
}
}
protected void visagePretty(VisageTree tree) {
OutputStreamWriter osw = new OutputStreamWriter(System.out);
VisagePretty pretty = new VisagePretty(osw, false);
try {
pretty.println();
pretty.print("+++++++++++++++++++++++++++++++++");
pretty.println();
pretty.printExpr(tree);
pretty.println();
pretty.print("---------------------------------");
pretty.println();
osw.flush();
}catch(Exception ex) {
System.err.println("Pretty print got: " + ex);
}
}
protected JCExpression castFromObject (JCExpression arg, Type castType) {
return make.TypeCast(makeType(arg.pos(), types.boxedTypeOrType(castType)), arg);
}
protected class JavaTreeBuilder {
protected DiagnosticPosition diagPos;
private final VisageClassDeclaration enclosingClassDecl;
private boolean isScript;
protected JavaTreeBuilder(DiagnosticPosition diagPos, VisageClassDeclaration enclosingClassDecl, boolean isScript) {
this.diagPos = diagPos;
this.enclosingClassDecl = enclosingClassDecl;
this.isScript = isScript;
}
//
// Returns the current class decl.
//
public VisageClassDeclaration getCurrentClassDecl() { return enclosingClassDecl; }
//
// Returns true if the class (or current class) is a mixin.
//
public boolean isMixinClass() {
return VisageTranslationSupport.this.isMixinClass((ClassSymbol)enclosingClassDecl.sym);
}
public boolean isMixinClass(ClassSymbol sym) {
return VisageTranslationSupport.this.isMixinClass(sym);
}
public boolean isAnonClass() {
return VisageTranslationSupport.this.isAnonClass((ClassSymbol)enclosingClassDecl.sym);
}
public boolean isAnonClass(ClassSymbol sym) {
return VisageTranslationSupport.this.isAnonClass(sym);
}
public boolean isLocalClass() {
return VisageTranslationSupport.this.isLocalClass((ClassSymbol)enclosingClassDecl.sym);
}
public boolean isLocalClass(ClassSymbol sym) {
return VisageTranslationSupport.this.isLocalClass(sym);
}
public boolean isBoundFuncClass() {
return VisageTranslationSupport.this.isBoundFuncClass((ClassSymbol)enclosingClassDecl.sym);
}
public boolean isBoundFuncClass(ClassSymbol sym) {
return VisageTranslationSupport.this.isBoundFuncClass(sym);
}
public boolean isMixinVar(Symbol sym) {
VisageVarSymbol varSym = (VisageVarSymbol)sym;
Symbol owner = varSym.owner;
return owner instanceof ClassSymbol && isMixinClass((ClassSymbol)owner) && !varSym.isStatic();
}
public boolean isLocalClassVar(Symbol sym) {
VisageVarSymbol varSym = (VisageVarSymbol)sym;
Symbol owner = varSym.owner;
return owner instanceof ClassSymbol && isLocalClass((ClassSymbol)owner);
}
public boolean isBoundFuncParameter(Symbol sym) {
VisageVarSymbol varSym = (VisageVarSymbol)sym;
Symbol owner = varSym.owner;
return owner instanceof ClassSymbol && isBoundFuncClass((ClassSymbol)owner);
}
public boolean setIsScript(boolean newState) {
boolean oldState = isScript;
isScript = newState;
return oldState;
}
public boolean isScript() {
return isScript;
}
protected void setDiagPos(DiagnosticPosition diagPos) {
this.diagPos = diagPos;
}
protected void clearDiagPos() {
this.diagPos = null;
}
protected TreeMaker m() {
return make.at(diagPos);
}
/**
* Make an identifier which references the specified variable declaration
*/
protected JCIdent id(JCVariableDecl aVar) {
return id(aVar.name);
}
/**
* Make an identifier of the given name
*/
protected JCIdent id(Name name) {
return m().Ident(name);
}
/**
* Make an identifier of the given symbol
*/
protected JCIdent id(Symbol sym) {
return m().Ident(sym.name);
}
/**
* Make an identifier of the given string
*/
protected JCIdent id(String string) {
return m().Ident(names.fromString(string));
}
/**
* Make a member select or an identifier depending on the selector
*/
protected JCExpression Select(JCExpression selector, Name name) {
return (selector==null)? id(name) : m().Select(selector, name);
}
/**
* An assertion
*/
protected JCAssert Assert(JCExpression cond) {
return m().Assert(cond, null);
}
/**
* Standard method parameters
*/
JCIdent makeMethodArg(Name name, Type type) {
JCIdent id = id(name);
id.type = type;
return id;
}
JCIdent posArg() {
return makeMethodArg(defs.pos_ArgName, syms.intType);
}
JCIdent startPosArg() {
return makeMethodArg(defs.startPos_ArgName, syms.intType);
}
JCIdent endPosArg() {
return makeMethodArg(defs.endPos_ArgName, syms.intType);
}
JCIdent newLengthArg() {
return makeMethodArg(defs.newLength_ArgName, syms.intType);
}
JCIdent phaseArg() {
return makeMethodArg(defs.phase_ArgName, syms.intType);
}
/**
* Set the phase state part of the flag to the next state part of the phase transition
*/
JCStatement SetNextVarFlagsStateFromPhaseTransition(VisageVarSymbol sym) {
return
FlagChangeStmt(sym,
id(defs.varFlagSTATE_MASK),
SHIFTR(
phaseArg(),
id(defs.phaseTransitionNEXT_STATE_SHIFT)
)
);
}
/**
* Clear the BE bits from the phase transition
*/
JCStatement ClearBeFromPhaseTransition() {
return
Stmt(
m().Assignop(JCTree.BITAND_ASG,
phaseArg(),
id(defs.phaseTransitionCLEAR_BE)
));
}
JCStatement PhaseCheckedBlock(VisageVarSymbol sym, JCStatement... stmts) {
return
If (id(defs.wasInvalid_LocalVarName),
Block(
Stmts(
SetNextVarFlagsStateFromPhaseTransition(sym),
ClearBeFromPhaseTransition()
).appendList(List.from(stmts))
)
);
}
JCExpression IsInvalidatePhase() {
return EQ(BITAND(phaseArg(), id(defs.phaseTransitionPHASE)), id(defs.phaseINVALIDATE));
}
JCExpression IsTriggerPhase() {
return EQ(BITAND(phaseArg(), id(defs.phaseTransitionPHASE)), id(defs.phaseTRIGGER));
}
/**
* Convert type to JCExpression
*/
protected JCExpression makeType(Type type, boolean makeIntf) {
return VisageTranslationSupport.this.makeType(diagPos, type, makeIntf);
}
protected JCExpression makeType(Type type) {
return makeType(type, true);
}
protected JCExpression makeType(Symbol sym) {
return makeType(sym.type, true);
}
protected JCExpression makeKeyValueTargetType(Type type) {
Name fieldName;
if (type.isPrimitive()) {
switch (type.getKind()) {
case BYTE:
fieldName = defs.BYTE_KeyValueTargetTypeFieldName;
break;
case SHORT:
fieldName = defs.SHORT_KeyValueTargetTypeFieldName;
break;
case INT:
case CHAR:
fieldName = defs.INTEGER_KeyValueTargetTypeFieldName;
break;
case LONG:
fieldName = defs.LONG_KeyValueTargetTypeFieldName;
break;
case FLOAT:
fieldName = defs.FLOAT_KeyValueTargetTypeFieldName;
break;
case DOUBLE:
fieldName = defs.DOUBLE_KeyValueTargetTypeFieldName;
break;
case BOOLEAN:
fieldName = defs.BOOLEAN_KeyValueTargetTypeFieldName;
break;
default:
fieldName = defs.OBJECT_KeyValueTargetTypeFieldName;
break;
}
} else if (types.isSequence(type)) {
fieldName = defs.SEQUENCE_KeyValueTargetTypeFieldName;
} else {
fieldName = defs.OBJECT_KeyValueTargetTypeFieldName;
}
return Select(makeQualifiedTree(diagPos, VisageDefs.cKeyValueTargetType), fieldName);
}
// Return a receiver$, scriptLevelAccess$() or null depending on the context.
//
protected JCExpression getReceiver() {
return resolveThis(enclosingClassDecl.sym, true);
}
protected JCExpression getReceiverOrThis() {
return resolveThis(enclosingClassDecl.sym, false);
}
protected JCExpression getReceiverOrThis(boolean isStatic) {
Symbol cSym = enclosingClassDecl.sym;
if (isStatic) {
return Select(makeType(cSym.type, false), visagemake.ScriptAccessSymbol(cSym).name);
} else if(isMixinClass()) {
return id(defs.receiverName);
}
return resolveThisInternal(cSym, false);
}
protected JCExpression getReceiver(Symbol sym) {
if (sym.isStatic()) {
return Select(makeType(sym.owner.type, false), visagemake.ScriptAccessSymbol(sym.owner).name);
}
return resolveThis(sym.owner, true);
}
protected JCExpression getReceiverOrThis(Symbol sym) {
if (sym.isStatic()) {
return Select(makeType(sym.owner.type, false), visagemake.ScriptAccessSymbol(sym.owner).name);
}
return resolveThis(sym.owner, false);
}
protected JCExpression resolveThis(Symbol sym, boolean nullForThis) {
return (isMixinClass() && !isScript) ?
id(defs.receiverName) :
resolveThisInternal(sym, nullForThis);
}
//where
private JCExpression resolveThisInternal(Symbol owner, boolean nullForThis) {
JCExpression _this = owner.kind == Kinds.TYP ?
resolveThisInternal(owner, enclosingClassDecl.sym, false) :
id(names._this);
return (nullForThis && _this.getTag() == JCTree.IDENT) ?
null :
_this;
}
//where
private JCExpression resolveThisInternal(Symbol ownerThis, Symbol currentThis, boolean rec) {
JCExpression thisExpr = rec ?
Select(makeType(currentThis.type), names._this) :
id(names._this);
if (!currentThis.isSubClass(ownerThis, types)) {
Type encl = currentThis.type.getEnclosingType();
if (encl == null || encl == Type.noType || types.isMixin(encl.tsym)) {
return resolveThisInternal(ownerThis, currentThis, thisExpr);
}
return resolveThisInternal(ownerThis, currentThis.type.getEnclosingType().tsym, true);
}
else {
return thisExpr;
}
}
//where
private JCExpression resolveThisInternal(Symbol ownerThis, Symbol currentThis, JCExpression receiver) {
if (currentThis == null) {
throw new AssertionError("Cannot find owner");
}
else if (!currentThis.isSubClass(ownerThis, types)) {
return resolveThisInternal(ownerThis, currentThis.owner.enclClass(), Call(receiver, defs.outerAccessor_MethodName));
}
else {
return receiver;
}
}
protected JCExpression resolveSuper(Symbol owner) {
return resolveSuperInternal(owner, enclosingClassDecl.sym, false);
}
private JCExpression resolveSuperInternal(Symbol ownerSym, Symbol currentSym, boolean rec) {
JCExpression superExpr = rec ?
Select(makeType(currentSym.type), names._super) :
id(names._super);
if (!currentSym.isSubClass(ownerSym, types)) {
Type encl = currentSym.type.getEnclosingType();
return resolveSuperInternal(ownerSym, currentSym.type.getEnclosingType().tsym, true);
}
else {
return superExpr;
}
}
//
// Private support methods for testing/setting/clearing a var flag.
//
protected boolean isJCIdentName(JCExpression ident, Name name) {
return ident instanceof JCIdent && ((JCIdent)ident).getName() == name;
}
protected JCExpression GetFlags(VisageVarSymbol varSym) {
if (isMixinClass()) {
return Call(getReceiver(varSym), defs.getFlags_VisageObjectMethodName, Offset(varSym));
} else {
return VarFlags(varSym);
}
}
protected JCExpression flagCast(JCExpression expr) {
return m().TypeCast(makeType(syms.shortType, true), expr);
}
private JCExpression FlagAction(VisageVarSymbol varSym, Name action, Name clearBits, Name setBits, boolean isStmt) {
return FlagAction(varSym, action,
clearBits != null ? id(clearBits) : null,
setBits != null ? id(setBits) : null,
isStmt);
}
private JCExpression FlagAction(VisageVarSymbol varSym, Name action, JCExpression clearBits, JCExpression setBits, boolean isStmt) {
assert clearBits != null || setBits != null : "Need to specify which bits";
boolean clearBitsNull = clearBits == null;
boolean setBitsNull = setBits == null;
if (clearBitsNull) clearBits = Int(0);
if (setBitsNull) setBits = Int(0);
clearDiagPos();
if (action == defs.varFlagActionTest) {
return EQ(BITAND(GetFlags(varSym), clearBits), setBits);
} else if (isMixinClass() && !varSym.isStatic()) {
return Call(getReceiver(varSym), action, Offset(varSym), clearBits, setBits);
} else /* if (action == defs.varFlagActionChange) */ {
JCExpression assignExpr;
if (isStmt) {
if (isJCIdentName(clearBits, defs.varFlagALL_FLAGS)) {
assignExpr = m().Assign(VarFlags(varSym), flagCast(setBits));
} else if (clearBitsNull) {
assignExpr = m().Assignop(JCTree.BITOR_ASG, VarFlags(varSym), flagCast(setBits));
} else if (setBitsNull) {
assignExpr = m().Assignop(JCTree.BITAND_ASG, VarFlags(varSym), flagCast(BITNOT(clearBits)));
} else {
assignExpr = m().Assign(VarFlags(varSym), flagCast(BITOR(BITAND(VarFlags(varSym), BITNOT(clearBits)), setBits)));
}
return assignExpr;
} else {
ListBuffer<JCStatement> stmts = ListBuffer.lb();
JCVariableDecl bitsVar;
if (isJCIdentName(clearBits, defs.varFlagALL_FLAGS)) {
bitsVar = TmpVar(syms.intType, setBits);
assignExpr = m().Assign(VarFlags(varSym), flagCast(id(bitsVar.name)));
} else if (clearBitsNull) {
bitsVar = TmpVar(syms.intType, setBits);
assignExpr = m().Assignop(JCTree.BITOR_ASG, VarFlags(varSym), flagCast(id(bitsVar.name)));
} else if (setBitsNull) {
bitsVar = TmpVar(syms.intType, clearBits);
assignExpr = m().Assignop(JCTree.BITAND_ASG, VarFlags(varSym), flagCast(BITNOT(id(bitsVar.name))));
} else {
JCVariableDecl clearBitsVar = TmpVar(syms.intType, clearBits);
JCVariableDecl setBitsVar = TmpVar(syms.intType, setBits);
stmts.append(clearBitsVar);
stmts.append(setBitsVar);
bitsVar = TmpVar(syms.intType, BITOR(id(clearBitsVar.name), id(setBitsVar.name)));
assignExpr = m().Assign(VarFlags(varSym), flagCast(BITOR(BITAND(VarFlags(varSym), BITNOT(id(clearBitsVar.name))), id(bitsVar.name))));
}
stmts.append(bitsVar);
JCVariableDecl testVar = TmpVar(syms.booleanType, EQ(BITAND(VarFlags(varSym), id(bitsVar.name)), id(bitsVar.name)));
stmts.append(testVar);
stmts.append(Stmt(assignExpr));
return BlockExpression(stmts, id(testVar.name));
}
}
}
private JCExpression FlagAction(JCExpression offset, Name action, Name clearBits, Name setBits, boolean isStmt) {
return Call(action, offset,
clearBits != null ? id(clearBits) : Int(0),
setBits != null ? id(setBits) : Int(0));
}
//
// These methods return an expression for testing a var flag.
//
protected JCExpression FlagTest(Name flagsVar, Name clearBits, Name setBits) {
return EQ(BITAND(id(flagsVar), clearBits == null ? Int(0) : id(clearBits)), setBits == null ? Int(0) : id(setBits));
}
protected JCExpression FlagTest(VisageVarSymbol varSym, Name clearBits, Name setBits) {
return FlagAction(varSym, defs.varFlagActionTest, clearBits, setBits, false);
}
protected JCExpression FlagTest(VisageVarSymbol varSym, JCExpression clearBits, JCExpression setBits) {
return FlagAction(varSym, defs.varFlagActionTest, clearBits, setBits, false);
}
protected JCExpression FlagTest(JCExpression offset, Name clearBits, Name setBits) {
return FlagAction(offset, defs.varFlagActionTest, clearBits, setBits, false);
}
//
// These methods returns a statement for setting/clearing a var flag.
//
protected JCStatement FlagChangeStmt(VisageVarSymbol varSym, Name clearBits, Name setBits) {
return Stmt(FlagAction(varSym, defs.varFlagActionChange, clearBits, setBits, true));
}
protected JCStatement FlagChangeStmt(VisageVarSymbol varSym, JCExpression clearBits, JCExpression setBits) {
return Stmt(FlagAction(varSym, defs.varFlagActionChange, clearBits, setBits, true));
}
protected JCStatement FlagChangeStmt(JCExpression offset, Name clearBits, Name setBits) {
return Stmt(FlagAction(offset, defs.varFlagActionChange, clearBits, setBits, true));
}
// Specialized test for checking to see if a var is init ready in a bind expression.
// The var flags have been copied to a local varFlags$.
protected JCExpression bindNeedsDefault(VisageVarSymbol varSym) {
return EQ(BITAND(id(defs.varFlags_LocalVarName),
id(defs.varFlagINITIALIZED_STATE_BIT)),
Int(0));
}
//
// Methods to generate simple constants.
//
protected JCExpression Int(int value) { return m().Literal(TypeTags.INT, value); }
protected JCExpression Byte(int value) { return m().Literal(TypeTags.BYTE, value); }
protected JCExpression Null() { return m().Literal(TypeTags.BOT, null); }
protected JCExpression String(String str) { return m().Literal(TypeTags.CLASS, str); }
protected JCExpression Boolean(boolean value) { return m().Literal(TypeTags.BOOLEAN, value ? 1 : 0); }
protected JCExpression True() { return Boolean(true); }
protected JCExpression False() { return Boolean(false); }
protected JCStatement Stmt(JCExpression expr) {
return m().Exec(expr);
}
protected JCStatement Return(JCExpression expr) {
return m().Return(expr);
}
protected JCStatement Stmt(JCExpression expr, Type returnType) {
return (returnType==null || returnType==syms.voidType)?
Stmt(expr)
: Return(expr);
}
//
// Binary and Unary operators
//
JCExpression LT(JCExpression v1, JCExpression v2) {
return m().Binary(JCTree.LT, v1, v2);
}
JCExpression LE(JCExpression v1, JCExpression v2) {
return m().Binary(JCTree.LE, v1, v2);
}
JCExpression GT(JCExpression v1, JCExpression v2) {
return m().Binary(JCTree.GT, v1, v2);
}
JCExpression GE(JCExpression v1, JCExpression v2) {
return m().Binary(JCTree.GE, v1, v2);
}
JCExpression EQ(JCExpression v1, JCExpression v2) {
return m().Binary(JCTree.EQ, v1, v2);
}
JCExpression NE(JCExpression v1, JCExpression v2) {
return m().Binary(JCTree.NE, v1, v2);
}
JCExpression AND(JCExpression v1, JCExpression v2) {
return m().Binary(JCTree.AND, v1, v2);
}
JCExpression OR(JCExpression v1, JCExpression v2) {
return m().Binary(JCTree.OR, v1, v2);
}
JCExpression PLUS(JCExpression v1, JCExpression v2) {
return m().Binary(JCTree.PLUS, v1, v2);
}
JCExpression MINUS(JCExpression v1, JCExpression v2) {
return m().Binary(JCTree.MINUS, v1, v2);
}
JCExpression MUL(JCExpression v1, JCExpression v2) {
return m().Binary(JCTree.MUL, v1, v2);
}
JCExpression MOD(JCExpression v1, JCExpression v2) {
return m().Binary(JCTree.MOD, v1, v2);
}
JCExpression DIV(JCExpression v1, JCExpression v2) {
return m().Binary(JCTree.DIV, v1, v2);
}
JCExpression NEG(JCExpression v1) {
return m().Unary(JCTree.NEG, v1);
}
JCExpression NOT(JCExpression v1) {
return m().Unary(JCTree.NOT, v1);
}
JCExpression BITAND(JCExpression v1, JCExpression v2) {
return m().Binary(JCTree.BITAND, v1, v2);
}
JCExpression BITOR(JCExpression v1, JCExpression v2) {
return m().Binary(JCTree.BITOR, v1, v2);
}
JCExpression BITXOR(JCExpression v1, JCExpression v2) {
return m().Binary(JCTree.BITXOR, v1, v2);
}
JCExpression BITNOT(JCExpression v1) {
return m().Binary(JCTree.BITXOR, v1, Int(-1));
}
JCExpression SHIFTL(JCExpression v1, JCExpression v2) {
return m().Binary(JCTree.SL, v1, v2);
}
JCExpression SHIFTR(JCExpression v1, JCExpression v2) {
return m().Binary(JCTree.SR, v1, v2);
}
/**
* Compare against null
*/
protected JCExpression EQnull(JCExpression targ) {
return EQ(targ, Null());
}
protected JCExpression NEnull(JCExpression targ) {
return NE(targ, Null());
}
/**
* Make a variable -- final by default
*/
protected JCVariableDecl Var(JCModifiers modifiers, JCExpression varType, Name varName, JCExpression initialValue, VisageVarSymbol varSym) {
JCVariableDecl varDecl = m().VarDef(
modifiers,
varName,
varType,
initialValue);
varDecl.sym = varSym;
return varDecl;
}
protected JCVariableDecl Var(long flags, Type varType, Name varName, JCExpression initialValue, VisageVarSymbol varSym) {
return Var(m().Modifiers(flags), makeType(varType), varName, initialValue, varSym);
}
protected JCVariableDecl Var(long flags, JCExpression varType, Name varName, JCExpression initialValue) {
return Var(m().Modifiers(flags), varType, varName, initialValue, null);
}
protected JCVariableDecl Var(long flags, Type varType, Name varName, JCExpression initialValue) {
return Var(flags, varType, varName, initialValue, null);
}
protected JCVariableDecl Var(Type varType, Name varName, JCExpression value) {
return Var(Flags.FINAL, varType, varName, value);
}
protected JCVariableDecl Var(long flags, Type varType, String varName, JCExpression initialValue) {
return Var(flags, varType, names.fromString(varName), initialValue);
}
/**
* Make a method paramter
*/
protected JCVariableDecl Param(Type varType, Name varName) {
return Var(Flags.PARAMETER | Flags.FINAL, varType, varName, null);
}
/**
* Make a receiver parameter.
* Its type is that of the corresponding interface and it is a final parameter.
* */
JCVariableDecl ReceiverParam(VisageClassDeclaration cDecl) {
return m().VarDef(
m().Modifiers(Flags.PARAMETER | Flags.FINAL),
defs.receiverName,
id(interfaceName(cDecl)),
null);
}
/**
* Make a variable (synthethic name) -- final by default
*/
protected JCVariableDecl MutableTmpVar(String root, Type varType, JCExpression initialValue) {
return TmpVar(0L, root, varType, initialValue);
}
protected JCVariableDecl TmpVar(Type type, JCExpression value) {
return TmpVar("tmp", type, value);
}
protected JCVariableDecl TmpVar(String root, Type varType, JCExpression value) {
return TmpVar(Flags.FINAL, root, varType, value);
}
protected JCVariableDecl TmpVar(long flags, String root, Type varType, JCExpression initialValue) {
return Var(flags, varType, getSyntheticName(root), initialValue);
}
/**
* Block Expressions
*/
BlockExprJCBlockExpression BlockExpression(List<JCStatement> stmts, JCExpression value) {
BlockExprJCBlockExpression bexpr = new BlockExprJCBlockExpression(0L, stmts, value);
bexpr.pos = (diagPos == null ? Position.NOPOS : diagPos.getStartPosition());
return bexpr;
}
BlockExprJCBlockExpression BlockExpression(ListBuffer<JCStatement> stmts, JCExpression value) {
return BlockExpression(stmts.toList(), value);
}
BlockExprJCBlockExpression BlockExpression(JCStatement stmt1, JCExpression value) {
return BlockExpression(List.of(stmt1), value);
}
BlockExprJCBlockExpression BlockExpression(JCStatement stmt1, JCStatement stmt2, JCExpression value) {
return BlockExpression(List.of(stmt1, stmt2), value);
}
/**
* Block
*/
JCBlock Block(List<JCStatement> prolog, JCStatement... epilog) {
ListBuffer<JCStatement> stmts = ListBuffer.lb();
for (JCStatement p : prolog) stmts.append(p);
for (JCStatement e : epilog) stmts.append(e);
return Block(stmts);
}
JCBlock Block(ListBuffer<JCStatement> prolog, JCStatement... epilog) {
ListBuffer<JCStatement> stmts = ListBuffer.lb();
for (JCStatement p : prolog) stmts.append(p);
for (JCStatement e : epilog) stmts.append(e);
return Block(stmts);
}
JCBlock Block(List<JCStatement> stmts) {
ListBuffer<JCStatement> nonNull = ListBuffer.lb();
for (JCStatement stmt : stmts) {
if (stmt != null) {
nonNull.append(stmt);
}
}
return m().Block(0L, nonNull.toList());
}
JCBlock Block(ListBuffer<JCStatement> stmts) {
return Block(stmts.toList());
}
JCBlock Block(JCStatement... stmts) {
return Block(List.from(stmts));
}
boolean isBlockEmpty(JCBlock block) {
return block == null || block.getStatements().isEmpty();
}
List<JCStatement> Stmts(JCStatement... stmts) {
return List.from(stmts);
}
/**
* If / Condition
*/
JCStatement If(JCExpression cond, JCStatement thenStmt, JCStatement elseStmt) {
return m().If(cond, thenStmt, elseStmt);
}
JCStatement If(JCExpression cond, JCStatement thenStmt) {
return m().If(cond, thenStmt, null);
}
JCExpression If(JCExpression cond, JCExpression thenExpr, JCExpression elseExpr) {
return m().Conditional(cond, thenExpr, elseExpr);
}
/**
* Optimal If
*/
JCStatement OptIf(JCExpression cond, JCStatement thenStmt) {
return OptIf(cond, thenStmt, null);
}
JCStatement OptIf(JCExpression cond, JCStatement thenStmt, JCStatement elseStmt) {
boolean noThen = thenStmt == null || (thenStmt instanceof JCBlock && isBlockEmpty((JCBlock)thenStmt));
boolean noElse = elseStmt == null || (elseStmt instanceof JCBlock && isBlockEmpty((JCBlock)elseStmt));
if (!noThen) {
return If(cond, thenStmt, noElse ? null : elseStmt);
} if (!noElse) {
return If(NOT(cond), elseStmt, null);
}
return null;
}
/**
* Try
*/
JCStatement Try(JCBlock body, JCCatch cat, JCBlock finalizer) {
ListBuffer<JCCatch> catches = ListBuffer.lb();
catches.append(cat);
return m().Try(body, catches.toList(), finalizer);
}
JCStatement Try(JCBlock body, JCCatch cat) {
return Try(body, cat, null);
}
/**
* Make methods
*/
protected JCMethodDecl Method(long flags, Type returnType, Name methodName, List<JCVariableDecl> params, List<JCStatement> stmts, MethodSymbol methSym) {
return Method(m().Modifiers(flags), returnType, methodName, params, stmts, methSym);
}
protected JCMethodDecl Method(long flags, Type returnType, Name methodName, List<Type> paramTypes, List<JCVariableDecl> params, Symbol owner, List<JCStatement> stmts) {
MethodSymbol methSym = makeMethodSymbol(flags, returnType, methodName, owner, paramTypes);
return Method(m().Modifiers(flags), returnType, methodName, params, stmts, methSym);
}
protected JCMethodDecl Method(JCModifiers modifiers, Type returnType, Name methodName, List<JCVariableDecl> params, List<JCStatement> stmts, MethodSymbol methSym) {
JCMethodDecl methDecl = m().MethodDef(
modifiers,
methodName,
makeType(returnType),
List.<JCTypeParameter>nil(),
params != null ? params : List.<JCVariableDecl>nil(),
List.<JCExpression>nil(),
stmts == null ? null : Block(stmts),
null);
methDecl.sym = methSym;
return methDecl;
}
protected JCExpression QualifiedTree(String str) {
return VisageTranslationSupport.this.makeQualifiedTree(diagPos, str);
}
/**
* Var accessors -- returning a JCExpression
*/
public JCExpression Get(Symbol sym) {
assert sym instanceof VisageVarSymbol : "Expect a var symbol, got " + sym;
VisageVarSymbol varSym = (VisageVarSymbol)sym;
if (varSym.isSpecial()) {
JCExpression receiver = getReceiver(varSym);
return receiver == null ? id(varSym.name) : receiver;
} else if (isMixinVar(varSym)) {
return Call(attributeGetMixinName(varSym));
} else if (varSym.isStatic()) {
return id(attributeValueName(varSym));
} else {
return Select(getReceiver(varSym), attributeValueName(varSym));
}
}
public JCExpression Get(JCExpression selector, Symbol sym) {
assert sym instanceof VisageVarSymbol : "Expect a var symbol, got " + sym;
VisageVarSymbol varSym = (VisageVarSymbol)sym;
if (isMixinVar(varSym)) {
return Call(selector, attributeGetMixinName(varSym));
} else {
return Select(selector, attributeValueName(varSym));
}
}
public JCExpression Offset(Symbol sym) {
assert sym instanceof VisageVarSymbol : "Expect a var symbol, got " + sym;
VisageVarSymbol varSym = (VisageVarSymbol)sym;
if (isMixinVar(varSym)) {
return Call(getReceiver(), attributeGetVOFFName(varSym));
} else {
JCExpression klass = makeType(varSym.owner.type, false);
if (varSym.isStatic()) {
klass = Select(klass, visagemake.ScriptSymbol(varSym.owner).name);
}
return Select(klass, attributeOffsetName(varSym));
}
}
public JCExpression Offset(JCExpression selector, Symbol sym) {
assert sym instanceof VisageVarSymbol : "Expect a var symbol, got " + sym;
VisageVarSymbol varSym = (VisageVarSymbol)sym;
if (selector != null && isMixinVar(varSym)) {
return Call(selector, attributeGetVOFFName(varSym));
}
return Offset(varSym);
}
public JCExpression DepNum(JCExpression selector, Symbol selectorSym, Symbol sym) {
assert sym instanceof VisageVarSymbol : "Expect a var symbol, got " + sym;
VisageVarSymbol varSym = (VisageVarSymbol)sym;
Name depName = depName(selectorSym, varSym);
if (isMixinClass()) {
return PLUS(Call(classDCNT$Name(enclosingClassDecl.sym)), id(depName));
}
return Select(selector, depName);
}
public JCExpression FuncNum(int number) {
JCExpression baseExpr;
if (isMixinClass() && !isScript()) {
baseExpr = Call(classFCNT$Name(enclosingClassDecl.sym));
} else if (isScript()) {
baseExpr = Select(id(visagemake.ScriptAccessSymbol(enclosingClassDecl.sym).name), defs.funcCount_VisageObjectFieldName);
} else {
baseExpr = id(defs.funcCount_VisageObjectFieldName);
}
return PLUS(baseExpr, Int(number));
}
public JCExpression VarFlags(Symbol sym) {
assert sym instanceof VisageVarSymbol : "Expect a var symbol, got " + sym;
VisageVarSymbol varSym = (VisageVarSymbol)sym;
return Select(getReceiver(varSym), attributeFlagsName(varSym));
}
public JCExpression VarFlags(JCExpression selector, Symbol sym) {
assert sym instanceof VisageVarSymbol : "Expect a var symbol, got " + sym;
VisageVarSymbol varSym = (VisageVarSymbol)sym;
return Select(selector, attributeFlagsName(varSym));
}
public JCExpression Set(Symbol sym, JCExpression value) {
assert sym instanceof VisageVarSymbol : "Expect a var symbol, got " + sym;
VisageVarSymbol varSym = (VisageVarSymbol)sym;
if (isMixinVar(varSym)) {
return Call(attributeSetMixinName(varSym), value);
} else if (varSym.isStatic()) {
return m().Assign(id(attributeValueName(varSym)), value);
} else {
return m().Assign(Select(getReceiver(varSym), attributeValueName(varSym)), value);
}
}
public JCExpression Set(JCExpression selector, Symbol sym, JCExpression value) {
assert sym instanceof VisageVarSymbol : "Expect a var symbol, got " + sym;
VisageVarSymbol varSym = (VisageVarSymbol)sym;
if (isMixinVar(varSym)) {
return Call(selector, attributeSetMixinName(varSym), value);
} else {
return m().Assign(Select(selector, attributeValueName(varSym)), value);
}
}
public JCStatement SetStmt(Symbol sym, JCExpression value) {
return Stmt(Set(sym, value));
}
public JCStatement SetStmt(JCExpression selector, Symbol sym, JCExpression value) {
return Stmt(Set(selector, sym, value));
}
public JCExpression Getter(Symbol sym) {
return Getter(sym.isStatic() ?
makeType(sym.owner.type, false) :
getReceiver(sym), sym);
}
public JCExpression Getter(JCExpression selector, Symbol sym) {
VisageVarSymbol vsym = (VisageVarSymbol) sym;
if (vsym.isSpecial()) {
return Get(vsym);
} else if (vsym.isMember()) {
if (vsym.useGetters()) {
return Call(selector, attributeGetterName(vsym));
} else {
return Get(selector, vsym);
}
} else {
// Local variable
return id(vsym.name);
}
}
public JCExpression Setter(Symbol sym, JCExpression value) {
return Setter(sym.isStatic() ?
makeType(sym.owner.type, false) :
getReceiver(sym), sym, value);
}
public JCExpression Setter(JCExpression selector, Symbol sym, JCExpression value) {
VisageVarSymbol vsym = (VisageVarSymbol) sym;
if (vsym.isSpecial()) {
return Set(selector, sym, value);
} else if (vsym.isMember()) {
if (vsym.useSetters()) {
return Call(selector, attributeSetterName(sym), value);
} else {
return Set(selector, sym, value);
}
} else {
// Local variable
return m().Assign(id(sym.name), value);
}
}
public JCStatement SetterStmt(Symbol sym, JCExpression value) {
return Stmt(Setter(sym, value));
}
public JCStatement SetterStmt(JCExpression selector, Symbol sym, JCExpression value) {
return Stmt(Setter(selector, sym, value));
}
/**
* Method call support
*/
private List<JCExpression> callArgs(JCExpression[] args) {
// Convert args to list.
ListBuffer<JCExpression> argBuffer = ListBuffer.lb();
for (JCExpression arg : args) {
argBuffer.append(arg);
}
return argBuffer.toList();
}
/**
* Method calls -- returning a JCExpression
*/
JCExpression Call(JCExpression receiver, Name methodName, List<JCExpression> typeArgs, List<JCExpression> args) {
JCExpression expr = Select(receiver, methodName);
return m().Apply(typeArgs, expr, args);
}
JCExpression Call(JCExpression receiver, Name methodName, List<JCExpression> args) {
return Call(receiver, methodName, List.<JCExpression>nil(), args);
}
JCExpression Call(JCExpression receiver, Name methodName, ListBuffer<JCExpression> args) {
return Call(receiver, methodName, args.toList());
}
JCExpression Call(JCExpression receiver, Name methodName, JCExpression... args) {
return Call(receiver, methodName, callArgs(args));
}
JCExpression Call(Name methodName, List<JCExpression> args) {
return Call(getReceiver(), methodName, args);
}
JCExpression Call(Name methodName, ListBuffer<JCExpression> args) {
return Call(getReceiver(), methodName, args.toList());
}
JCExpression Call(Name methodName, JCExpression... args) {
return Call(getReceiver(), methodName, callArgs(args));
}
JCExpression Call(RuntimeMethod meth, List<JCExpression> typeArgs, List<JCExpression> args) {
return Call(QualifiedTree(meth.classString), meth.methodName, typeArgs, args);
}
JCExpression Call(RuntimeMethod meth, ListBuffer<JCExpression> typeArgs, ListBuffer<JCExpression> args) {
return Call(meth, typeArgs.toList(), args.toList());
}
JCExpression Call(RuntimeMethod meth, List<JCExpression> args) {
return Call(meth, List.<JCExpression>nil(), args);
}
JCExpression Call(RuntimeMethod meth, ListBuffer<JCExpression> args) {
return Call(meth, args.toList());
}
JCExpression Call(RuntimeMethod meth, JCExpression... args) {
return Call(meth, callArgs(args));
}
/**
* Method calls -- returning a JCStatement
*/
JCStatement CallStmt(JCExpression receiver, Name methodName, List<JCExpression> args) {
return Stmt(Call(receiver, methodName, args));
}
JCStatement CallStmt(JCExpression receiver, Name methodName, ListBuffer<JCExpression> args) {
return Stmt(Call(receiver, methodName, args.toList()));
}
JCStatement CallStmt(JCExpression receiver, Name methodName, JCExpression... args) {
return Stmt(Call(receiver, methodName, callArgs(args)));
}
JCStatement CallStmt(Name methodName, List<JCExpression> args) {
return Stmt(Call(getReceiver(), methodName, args));
}
JCStatement CallStmt(Name methodName, ListBuffer<JCExpression> args) {
return Stmt(Call(getReceiver(), methodName, args.toList()));
}
JCStatement CallStmt(Name methodName, JCExpression... args) {
return Stmt(Call(getReceiver(), methodName, callArgs(args)));
}
JCStatement CallStmt(RuntimeMethod meth, List<JCExpression> args) {
return Stmt(Call(meth, args));
}
JCStatement CallStmt(RuntimeMethod meth, ListBuffer<JCExpression> args) {
return Stmt(Call(meth, args));
}
JCStatement CallStmt(RuntimeMethod meth, JCExpression... args) {
return Stmt(Call(meth, args));
}
/**
* Invalidation support
*/
private JCStatement CallInvalidate(Symbol sym, Name flag) {
clearDiagPos();
return CallStmt(attributeInvalidateName(sym), id(flag));
}
JCStatement CallInvalidate(Symbol sym) {
return CallInvalidate(sym, defs.phaseTransitionCASCADE_INVALIDATE);
}
JCStatement CallTrigger(Symbol sym) {
return CallInvalidate(sym, defs.phaseTransitionCASCADE_TRIGGER);
}
JCStatement CallBeInvalidate(Symbol sym) {
return CallInvalidate(sym, defs.phaseTransitionBE_INVALIDATE);
}
JCStatement CallBeTrigger(Symbol sym) {
return CallInvalidate(sym, defs.phaseTransitionBE_TRIGGER);
}
/**
* Sequence invalidation support
*/
JCExpression Undefined() {
return Int(VisageDefs.UNDEFINED_MARKER_INT);
}
JCStatement CallSeqInvalidate(Symbol sym, JCExpression begin, JCExpression end, JCExpression newLen) {
clearDiagPos();
return CallStmt(attributeInvalidateName(sym), begin, end, newLen, id(defs.phaseTransitionCASCADE_INVALIDATE));
}
JCStatement CallSeqTrigger(Symbol sym, JCExpression begin, JCExpression end, JCExpression newLen) {
clearDiagPos();
return CallStmt(attributeInvalidateName(sym), begin, end, newLen, id(defs.phaseTransitionCASCADE_TRIGGER));
}
JCStatement CallSeqInvalidateUndefined(Symbol sym) {
return CallSeqInvalidate(sym, Int(0), Undefined(), Undefined());
}
JCStatement CallSeqTriggerInitial(Symbol sym, JCExpression initialSize) {
return CallSeqTrigger(sym, Int(0), Int(0), initialSize);
}
JCStatement CallSeqTriggerUnchanged(Symbol sym) {
return CallSeqTrigger(sym, Undefined(), Undefined(), Int(0));
}
JCExpression IsUnchangedTrigger() {
return LT(startPosArg(), Int(0));
}
/**
* These methods simplify throw statements.
*/
JCStatement Throw(Type type, String message) {
if (message != null) {
return m().Throw(m().NewClass(null, null, makeType(type), List.<JCExpression>of(String(message)), null));
} else {
return m().Throw(m().NewClass(null, null, makeType(type), List.<JCExpression>nil(), null));
}
}
JCStatement Throw(Type type) {
return Throw(type, null);
}
JCExpression typeCast(final Type targetType, final Type inType, final JCExpression expr) {
if (types.typeRep(inType).isObject()) {
// We can't just cast the Object to Float (for example)
// because if the Object is not Float, we will get a ClassCastException at runtime.
// And we can't just call java.lang.Number.floatValue() because java.lang.Number
// doesn't exist on mobile, at least not as of Jan 2009.
VisageTypeRepresentation targetKind = types.typeRep(targetType);
if (targetKind.isPrimitive()) {
return Call(defs.Util_objectTo[targetKind.ordinal()], expr);
}
}
// The makeTypeCast below is usually redundant, since translateAsValue
// takes care of most conversions - except in the case of a plain object cast.
// It would be cleaner to move the makeTypeCast to translateAsValue,
// but it's painful to get it right. FIXME.
return TypeCast(targetType, inType, expr);
}
JCExpression TypeCast(Type clazztype, Type exprtype, JCExpression translatedExpr) {
if (types.isSameType(clazztype, exprtype)) {
return translatedExpr;
} else {
Type castType = clazztype;
if (exprtype != Type.noType && !exprtype.isPrimitive()) {
castType = types.boxedTypeOrType(castType);
}
JCTree clazz = makeType(castType, true);
return m().TypeCast(clazz, translatedExpr);
}
}
/* Default value per type */
JCExpression DefaultValue(Type type) {
return VisageTranslationSupport.this.makeDefaultValue(diagPos, type);
}
/*
* Construct a symbol and type for a new class.
*/
protected ClassSymbol makeClassSymbol(long flags, Name name, Symbol owner) {
ClassSymbol classSym = new ClassSymbol(flags, name, owner);
ClassType type = new ClassType(Type.noType, List.<Type>nil(), classSym);
classSym.type = type;
return classSym;
}
/**
* Create a method symbol.
*/
public MethodSymbol makeMethodSymbol(long flags, Type returnType, Name methodName, Symbol owner, List<Type> argTypes) {
MethodType methodType = new MethodType(argTypes, returnType, List.<Type>nil(), syms.methodClass);
return new MethodSymbol(flags, methodName, methodType, owner);
}
/*
* Copy the members of a newly created JCClassDecl to it's symbol.
*/
protected void membersToSymbol(JCClassDecl cls) {
ClassSymbol cSym = cls.sym;
Scope members = new Scope(cSym);
for (JCTree tree : cls.getMembers()) {
if (tree instanceof JCVariableDecl) {
JCVariableDecl varDecl = (JCVariableDecl)tree;
if (varDecl.sym != null) {
members.enter(varDecl.sym);
}
} else if (tree instanceof JCMethodDecl) {
JCMethodDecl methDecl = (JCMethodDecl)tree;
if (methDecl.sym != null) {
members.enter(methDecl.sym);
}
} else if (tree instanceof JCClassDecl) {
JCClassDecl classDecl = (JCClassDecl)tree;
if (classDecl.sym != null) {
members.enter(classDecl.sym);
}
}
}
cSym.members_field = members;
}
protected void membersToSymbol(ClassSymbol cSym, List<JCTree> adding) {
HashSet<Symbol> symbols = new HashSet<Symbol>();
Scope members = cSym.members();
for (Scope.Entry e = members.elems; e != null && e.sym != null; e = e.sibling) {
symbols.add(e.sym);
}
for (JCTree tree : adding) {
if (tree instanceof JCVariableDecl) {
JCVariableDecl varDecl = (JCVariableDecl)tree;
if (varDecl.sym != null && symbols.add(varDecl.sym)) {
members.enter(varDecl.sym);
}
} else if (tree instanceof JCMethodDecl) {
JCMethodDecl methDecl = (JCMethodDecl)tree;
if (methDecl.sym != null && symbols.add(methDecl.sym)) {
members.enter(methDecl.sym);
}
} else if (tree instanceof JCClassDecl) {
JCClassDecl classDecl = (JCClassDecl)tree;
if (classDecl.sym != null && symbols.add(classDecl.sym)) {
members.enter(classDecl.sym);
}
}
}
}
/* Debugging support */
JCStatement Println(String msg) {
return
CallStmt(
QualifiedTree("java.lang.System.out"),
names.fromString("println"),
String(msg));
}
JCStatement Debug(String msg) {
return Debug(msg, null);
}
JCStatement Debug(String msg, JCExpression obj) {
return CallStmt(QualifiedTree("java.lang.System.err"), names.fromString("println"),
obj==null?
String(msg)
: PLUS(String(msg + " "), obj));
}
List<JCStatement> makeDebugTrace(String msg) {
return makeDebugTrace(msg, String(""));
}
List<JCStatement> makeDebugTrace(String msg, JCExpression obj) {
String trace = options.get("debugTrace");
return trace != null ?
List.<JCStatement>of(Debug(msg, obj))
: List.<JCStatement>nil();
}
}
}