/* * 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 * * This file was originally derived from the Polyglot extensible compiler framework. * * (C) Copyright 2000-2007 Polyglot project group, Cornell University * (C) Copyright IBM Corporation 2007-2012. */ package polyglot.ast; import java.math.BigInteger; import polyglot.types.SemanticException; import polyglot.types.TypeSystem; import polyglot.types.Type; import polyglot.types.Context; import polyglot.types.Types; import polyglot.util.*; import polyglot.visit.ContextVisitor; import polyglot.visit.PrettyPrinter; import x10.errors.Errors; import x10.errors.Errors.IllegalConstraint; import x10.types.constants.ConstantValue; import x10.types.constraints.CConstraint; import x10.types.constraints.ConstraintManager; import x10.constraint.XTerm; import x10.constraint.XFailure; /** * An immutable representation of an int lit, modified from JL to support a * self-clause in the dep type. */ public class IntLit_c extends NumLit_c implements IntLit { /** The kind of literal: INT or LONG. */ protected Kind kind; public IntLit_c(Position pos, Kind kind, long value) { super(pos, value); assert(kind != null); this.kind = kind; } /** * @return True if this is a boundary case: the literal can only appear * as the operand of a unary minus. */ public boolean boundary() { return (kind == INT && (int) value == Integer.MIN_VALUE) || (kind == LONG && value == Long.MIN_VALUE) || (kind == BYTE && value == Byte.MIN_VALUE) || (kind == SHORT && value == Short.MIN_VALUE); } /** Get the value of the expression. */ public long value() { return longValue(); } /** Set the value of the expression. */ public IntLit value(long value) { IntLit_c n = (IntLit_c) copy(); n.value = value; return n; } /** Get the kind of the expression. */ public IntLit.Kind kind() { return kind; } /** Set the kind of the expression. */ public IntLit kind(IntLit.Kind kind) { IntLit_c n = (IntLit_c) copy(); n.kind = kind; return n; } /** Type check the expression. */ private void rangeCheck(ContextVisitor tc, Kind signed, Kind unsigned, long max, long min, long boundary) { if (kind == signed) { if ((value > max || value < min)) { Errors.issue(tc.job(), new Errors.LiteralOutOfRange(signed.toString(), value, position())); } } if (kind == unsigned) { if (value < 0 || value > boundary) { Errors.issue(tc.job(), new Errors.LiteralOutOfRange(unsigned.toString(), value, position())); } } } public Node typeCheck(ContextVisitor tc) { // todo: handle LONG and ULONG rangeCheck(tc, Kind.INT, Kind.UINT, 1l+Integer.MAX_VALUE, Integer.MIN_VALUE, 0xffffffffl); rangeCheck(tc, Kind.SHORT, Kind.USHORT, 1l+Short.MAX_VALUE, Short.MIN_VALUE, 0xffffl); rangeCheck(tc, Kind.BYTE, Kind.UBYTE, 1l+Byte.MAX_VALUE, Byte.MIN_VALUE, 0xffl); TypeSystem xts = (TypeSystem) tc.typeSystem(); Type Type; switch (kind) { case BYTE: Type = xts.Byte(); break; case SHORT: Type = xts.Short(); break; case INT: Type = xts.Int(); break; case LONG: Type = xts.Long(); break; case UBYTE: Type = xts.UByte(); break; case USHORT: Type = xts.UShort(); break; case UINT: Type = xts.UInt(); break; case ULONG: Type = xts.ULong(); break; default: throw new InternalCompilerError("bad integer literal kind", position()); } CConstraint c = ConstraintManager.getConstraintSystem().makeCConstraint(); try { XTerm term = xts.xtypeTranslator().translate(c, this.type(Type), (Context) tc.context()); c.addSelfBinding(term); } catch (IllegalConstraint z) { Errors.issue(tc.job(), z); } Type newType = Types.xclause(Type, c); return type(newType); } public String positiveToString() { assert boundary(); return kind == LONG ? "9223372036854775808L" : kind == INT ? "2147483648" : ""+Math.abs(value); } public String toString() { if (kind() == UINT) { return Long.toString(value & 0xffffffffL) + "U"; } else if (kind() == LONG) { return Long.toString(value) + "L"; } else if (kind() == ULONG) { StringBuilder sb = new StringBuilder(); long a = value; if (a >= 0) return Long.toString(a); byte[] bytes = new byte[9]; for (int i = 0; i < 8; i++) { bytes[8-i] = (byte) (a & 0xff); a >>>= 8; } return new BigInteger(bytes).toString() + "UL"; } else { String s = Long.toString((int) value); if (kind() == BYTE) { s += "Y"; } else if (kind() == UBYTE) { s += "UY"; } else if (kind() == SHORT) { s += "S"; } else if (kind() == USHORT) { s += "US"; } return s; } } public void prettyPrint(CodeWriter w, PrettyPrinter tr) { w.write(toString()); } public ConstantValue constantValue() { return ConstantValue.makeIntegral(value, kind()); } public Precedence precedence() { if (value < 0L && ! boundary()) { return Precedence.UNARY; } else { return Precedence.LITERAL; } } }