/* * This file is part of the X10 project (http://x10-lang.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.opensource.org/licenses/eclipse-1.0.php * * (C) Copyright IBM Corporation 2006-2010. */ package x10.emitter; import polyglot.ast.Node; import polyglot.types.Type; import polyglot.util.CodeWriter; import polyglot.visit.Translator; import x10.X10CompilerOptions; import x10.visit.X10PrettyPrinterVisitor; // constants import static x10.visit.X10PrettyPrinterVisitor.BOX_PRIMITIVES; public class CastExpander extends Expander { private final CodeWriter w; private final TypeExpander typeExpander; private final Expander child; private final Node node; private boolean boxConversion; // flag requesting explicit boxing conversion private boolean unboxConversion; // flag requesting explicit unboxing conversion private String location; private boolean debug = false; private void setLocation(Emitter er) { debug = ((X10CompilerOptions)er.tr.job().extensionInfo().getOptions()).x10_config.DEBUG_CODEGEN; if (!debug) return; StackTraceElement[] stackTrace = new Exception().getStackTrace(); StringBuffer sb = new StringBuffer(); for (int i = Math.min(3, stackTrace.length); i >= 3; i--) { sb.append(" "); sb.append(stackTrace[i].toString()); } location = sb.toString(); } public CastExpander(CodeWriter w, Emitter er, TypeExpander typeExpander, Expander child) { super(er); this.w = w; this.typeExpander = typeExpander; this.child = child; this.node = null; setLocation(er); } public CastExpander(CodeWriter w, Emitter er, Node node) { super(er); this.w = w; this.typeExpander = null; this.child = null; this.node = node; setLocation(er); } private CastExpander setBoxConversion(boolean b) { boxConversion = b; return this; } private CastExpander setUnboxConversion(boolean b) { unboxConversion = b; return this; } // not used // public CastExpander(CodeWriter w, Emitter er, Expander child) { // super(er); // this.w = w; // this.typeExpander = null; // this.child = child; // this.node = null; // } public CastExpander castTo(Type castType) { return new CastExpander(w, er, new TypeExpander(er, castType, 0), this); } public CastExpander castTo(Type castType, int flags) { return new CastExpander(w, er, new TypeExpander(er, castType, flags), this); } public CastExpander boxTo(Type castType) { return new CastExpander(w, er, new TypeExpander(er, castType, BOX_PRIMITIVES), this) .setBoxConversion(true); } public CastExpander unboxTo(Type castType) { return new CastExpander(w, er, new TypeExpander(er, castType, 0), this) .setUnboxConversion(true); } @Override public String toString() { StringBuffer buf = new StringBuffer(); if (typeExpander == null) { buf.append("("); toStringChild(buf); buf.append(")"); } else { buf.append("(("); buf.append(typeExpander); buf.append(")"); toStringChild(buf); w.write(")"); } return "((" + typeExpander + ")" + node + ")"; } private void toStringChild(StringBuffer buf) { if (node != null) { buf.append(node); } else { buf.append(child); } } @Override public void expand(Translator tr) { if (typeExpander == null) { expandChild(tr); } else { Type type = typeExpander.type(); if (type.isAny() || type.isParameterType() || boxConversion) { if (debug) w.write("/*location:" + location + "*/("); else w.write("("); er.printBoxConversion(type); w.write("("); // required by printBoxConversion expandChild(tr); w.write("))"); } else if (unboxConversion) { w.write("("); boolean closeParen = er.printUnboxConversion(type); expandChild(tr); if (closeParen) w.write(")"); w.write(")"); } else { if (debug) w.write("/*location:" + location + "*/(("); else w.write("(("); typeExpander.expand(tr); w.write(")("); expandChild(tr); w.write("))"); } } } private void expandChild(Translator tr) { Node printExpr = node; Expander printExpander = child; while (true) { if (printExpr != null) { er.prettyPrint(printExpr, tr); } else { if (printExpander instanceof CastExpander) { CastExpander castChild = (CastExpander) printExpander; if (sameCast(castChild)) { printExpr = castChild.node; printExpander = castChild.child; continue; } } printExpander.expand(tr); } return; } } private boolean sameCast(CastExpander expander) { if (typeExpander == null || expander.typeExpander == null) { return typeExpander == null && expander.typeExpander == null; } return typeExpander.toString().equals( expander.typeExpander.toString()); } }