package x10.types.constraints; import polyglot.ast.Expr; import polyglot.types.Context; import polyglot.types.Type; import polyglot.types.TypeSystem; import polyglot.types.Types; import x10.constraint.XFailure; import x10.constraint.XLit; import x10.constraint.XTerm; import x10.constraint.XVar; import x10.types.ConstrainedType; /** * Because the constraint system cannot handle conditional constraints, we build in a few special constraint propagation rules for operators. Our goal is to enrich the constraint system so that these rules can be expressed within usual operator definitions in X10. * @author vj * */ public class BuiltInTypeRules { /** * Because the constraint system cannot handle conditional constraints, we build in a few special * constraint propagation rules for operators. * * For an IntRange left..right, if we can staticaly establish that left is zero, then we assert * self.isZeroBased in the return type. * * class IntRange { * public static (left:Int) .. (right:Int) : IntRange{self.zeroBased==(left == 0)} {...} * } * @param left * @param right * @param type * @param context * @return */ public static Type adjustReturnTypeForIntRange(Expr left, Expr right, Type type, Context context) { TypeSystem ts = (TypeSystem) context.typeSystem(); Type ltype = left.type(); XTerm selfTerm = Types.selfBinding(ltype); if (selfTerm != null && selfTerm.equals(ts.ZERO())) { if (!ts.isUnknown(type)) { ConstrainedType result = Types.toConstrainedType(type); XTerm zb = result.makeZeroBased(); if (zb != null) result = (ConstrainedType) Types.addTerm(result, zb); result=result.addNonNull(); return result; } } return type; } /** * * * For a region mult left*right, we build in that the rank of the result is l+r if we can statically * establish that the rank of left is an value l, and the rank of right is a value r. * * If both left and right are rect, then we establish that the result is rect. * * If both left and right are zeroBased, then we establish that the result is zeroBased. * @param left * @param right * @param type * @param context * @return */ public static ConstrainedType adjustReturnTypeForRegionMult(Expr left, Expr right, Type type, Context context) { TypeSystem ts = context.typeSystem(); ConstrainedType ltype = Types.toConstrainedType(left.type()); ConstrainedType rtype = Types.toConstrainedType(right.type()); XTerm lrank = ltype.rank(context); XTerm rrank = rtype.rank(context); ConstrainedType ct = Types.toConstrainedType(type); XVar selfVar = ct.selfVar(); if (lrank instanceof XLit && rrank instanceof XLit) { int xr = (Integer) ((XLit) lrank).val(); int yr = (Integer) ((XLit) rrank).val(); ct = ct.addRank(xr+yr); } if (ltype.isRect(context) && rtype.isRect(context)) ct = ct.addRect(); if (ltype.isZeroBased(context) && rtype.isZeroBased(context)) ct = ct.addZeroBased(); assert selfVar == ct.selfVar(); ct=ct.addNonNull(); return ct; } /** * * * For a region mult left*right, we build in that the rank of the result is l+r if we can statically * establish that the rank of left is an value l, and the rank of right is a value r. * * If both left and right are rect, then we establish that the result is rect. * * If both left and right are zeroBased, then we establish that the result is zeroBased. * @param left * @param right * @param type * @param context * @return */ public static ConstrainedType adjustReturnTypeForRangeRangeMult(Expr left, Expr right, Type type, Context context) { TypeSystem ts = context.typeSystem(); ConstrainedType ltype = Types.toConstrainedType(left.type()); ConstrainedType rtype = Types.toConstrainedType(right.type()); ConstrainedType ct = Types.toConstrainedType(type); XVar selfVar = ct.selfVar(); ct = ct.addRank(2); ct = ct.addRect(); if (ltype.isZeroBased(context) && rtype.isZeroBased(context)) ct = ct.addZeroBased(); assert selfVar == ct.selfVar(); ct=ct.addNonNull(); return ct; } /** * * @param l * @param r * @param context * @return */ public static Type adjustReturnTypeForConjunction(Type l, Type r, Context context) { TypeSystem xts = (TypeSystem) l.typeSystem(); Type result = xts.Boolean(); // Support conjunction of boolean terms. // Once we shift to Shostak we will have more comprehensive // support for all operators. /*if (l.isBoolean() && r.isBoolean()) { XTerm xt = Types.selfBinding(l); if (xt != null) { XTerm yt = Types.selfBinding(r); if (yt != null) { result = Types.addSelfBinding(result, XTerms.makeAnd(xt, yt)); } } }*/ return result; } }