package polyglot.ext.jl.ast;
import polyglot.ast.*;
import polyglot.util.*;
import polyglot.visit.*;
import polyglot.types.*;
import polyglot.main.Options;
import java.util.*;
/**
* A <code>Cast</code> is an immutable representation of a casting
* operation. It consists of an <code>Expr</code> being cast and a
* <code>TypeNode</code> being cast to.
*/
public class Cast_c extends Expr_c implements Cast
{
protected TypeNode castType;
protected Expr expr;
public Cast_c(Position pos, TypeNode castType, Expr expr) {
super(pos);
this.castType = castType;
this.expr = expr;
}
/** Get the precedence of the expression. */
public Precedence precedence() {
return Precedence.CAST;
}
/** Get the cast type of the expression. */
public TypeNode castType() {
return this.castType;
}
/** Set the cast type of the expression. */
public Cast castType(TypeNode castType) {
Cast_c n = (Cast_c) copy();
n.castType = castType;
return n;
}
/** Get the expression being cast. */
public Expr expr() {
return this.expr;
}
/** Set the expression being cast. */
public Cast expr(Expr expr) {
Cast_c n = (Cast_c) copy();
n.expr = expr;
return n;
}
/** Reconstruct the expression. */
protected Cast_c reconstruct(TypeNode castType, Expr expr) {
if (castType != this.castType || expr != this.expr) {
Cast_c n = (Cast_c) copy();
n.castType = castType;
n.expr = expr;
return n;
}
return this;
}
/** Visit the children of the expression. */
public Node visitChildren(NodeVisitor v) {
TypeNode castType = (TypeNode) visitChild(this.castType, v);
Expr expr = (Expr) visitChild(this.expr, v);
return reconstruct(castType, expr);
}
/** Type check the expression. */
public Node typeCheck(TypeChecker tc) throws SemanticException
{
TypeSystem ts = tc.typeSystem();
if (! ts.isCastValid(expr.type(), castType.type())) {
throw new SemanticException("Cannot cast the expression of type \""
+ expr.type() + "\" to type \""
+ castType.type() + "\".",
position());
}
return type(castType.type());
}
public Type childExpectedType(Expr child, AscriptionVisitor av) {
TypeSystem ts = av.typeSystem();
if (child == expr) {
if (castType.type().isReference()) {
return ts.Object();
}
else if (castType.type().isNumeric()) {
return ts.Double();
}
else if (castType.type().isBoolean()) {
return ts.Boolean();
}
}
return child.type();
}
public String toString() {
return "(" + castType + ") " + expr;
}
/** Write the expression to an output file. */
public void prettyPrint(CodeWriter w, PrettyPrinter tr)
{
w.begin(0);
w.write("(");
print(castType, w, tr);
w.write(")");
w.allowBreak(2, " ");
printSubExpr(expr, w, tr);
w.end();
}
public Term entry() {
return expr.entry();
}
public List acceptCFG(CFGBuilder v, List succs) {
v.visitCFG(expr, this);
return succs;
}
public List throwTypes(TypeSystem ts) {
if (expr.type().isReference()) {
return Collections.singletonList(ts.ClassCastException());
}
return Collections.EMPTY_LIST;
}
public boolean isConstant() {
return expr.isConstant() && castType.type().isPrimitive();
}
public Object constantValue() {
Object v = expr.constantValue();
if (v == null) {
return null;
}
if (v instanceof Boolean) {
if (castType.type().isBoolean()) return v;
}
if (v instanceof String) {
TypeSystem ts = castType.type().typeSystem();
if (castType.type().equals(ts.String())) return v;
}
if (v instanceof Double) {
double vv = ((Double) v).doubleValue();
if (castType.type().isDouble()) return new Double((double) vv);
if (castType.type().isFloat()) return new Float((float) vv);
if (castType.type().isLong()) return new Long((long) vv);
if (castType.type().isInt()) return new Integer((int) vv);
if (castType.type().isChar()) return new Character((char) vv);
if (castType.type().isShort()) return new Short((short) vv);
if (castType.type().isByte()) return new Byte((byte) vv);
}
if (v instanceof Float) {
float vv = ((Float) v).floatValue();
if (castType.type().isDouble()) return new Double((double) vv);
if (castType.type().isFloat()) return new Float((float) vv);
if (castType.type().isLong()) return new Long((long) vv);
if (castType.type().isInt()) return new Integer((int) vv);
if (castType.type().isChar()) return new Character((char) vv);
if (castType.type().isShort()) return new Short((short) vv);
if (castType.type().isByte()) return new Byte((byte) vv);
}
if (v instanceof Number) {
long vv = ((Number) v).longValue();
if (castType.type().isDouble()) return new Double((double) vv);
if (castType.type().isFloat()) return new Float((float) vv);
if (castType.type().isLong()) return new Long((long) vv);
if (castType.type().isInt()) return new Integer((int) vv);
if (castType.type().isChar()) return new Character((char) vv);
if (castType.type().isShort()) return new Short((short) vv);
if (castType.type().isByte()) return new Byte((byte) vv);
}
if (v instanceof Character) {
char vv = ((Character) v).charValue();
if (castType.type().isDouble()) return new Double((double) vv);
if (castType.type().isFloat()) return new Float((float) vv);
if (castType.type().isLong()) return new Long((long) vv);
if (castType.type().isInt()) return new Integer((int) vv);
if (castType.type().isChar()) return new Character((char) vv);
if (castType.type().isShort()) return new Short((short) vv);
if (castType.type().isByte()) return new Byte((byte) vv);
}
// not a constant
return null;
}
}