001package org.clafer.ir; 002 003import org.clafer.common.Check; 004 005/** 006 * left `op` right + offset 007 * 008 * @author jimmy 009 */ 010public class IrCompare extends IrAbstractBool implements IrBoolExpr { 011 012 private final IrIntExpr left; 013 private final Op op; 014 private final IrIntExpr right; 015 016 IrCompare(IrIntExpr left, Op op, IrIntExpr right, IrBoolDomain domain) { 017 super(domain); 018 this.left = Check.notNull(left); 019 this.op = Check.notNull(op); 020 this.right = Check.notNull(right); 021 } 022 023 public IrIntExpr getLeft() { 024 return left; 025 } 026 027 public Op getOp() { 028 return op; 029 } 030 031 public IrIntExpr getRight() { 032 return right; 033 } 034 035 @Override 036 public IrBoolExpr negate() { 037 switch (op) { 038 case Equal: 039 return new IrCompare(left, Op.NotEqual, right, getDomain().invert()); 040 case NotEqual: 041 return new IrCompare(left, Op.Equal, right, getDomain().invert()); 042 case LessThan: 043 return new IrCompare(right, Op.LessThanEqual, left, getDomain().invert()); 044 case LessThanEqual: 045 return new IrCompare(right, Op.LessThan, left, getDomain().invert()); 046 default: 047 throw new IllegalStateException(); 048 } 049 } 050 051 @Override 052 public boolean isNegative() { 053 return false; 054 } 055 056 @Override 057 public <A, B> B accept(IrBoolExprVisitor<A, B> visitor, A a) { 058 return visitor.visit(this, a); 059 } 060 061 @Override 062 public <A, B> B accept(IrIntExprVisitor<A, B> visitor, A a) { 063 return visitor.visit(this, a); 064 } 065 066 @Override 067 public boolean equals(Object obj) { 068 if (obj instanceof IrCompare) { 069 IrCompare other = (IrCompare) obj; 070 return left.equals(other.left) && op.equals(other.op) && right.equals(other.right) && super.equals(other); 071 } 072 return false; 073 } 074 075 @Override 076 public int hashCode() { 077 // op.hashCode() can change between runs which makes the output change 078 // every time. 079 return left.hashCode() ^ op.ordinal() ^ right.hashCode(); 080 } 081 082 @Override 083 public String toString() { 084 return left + " " + op.getSyntax() + " " + right; 085 } 086 087 public static enum Op { 088 089 Equal("="), 090 NotEqual("!="), 091 LessThan("<"), 092 LessThanEqual("<="); 093 private final String syntax; 094 095 Op(String syntax) { 096 this.syntax = syntax; 097 } 098 099 public String getSyntax() { 100 return syntax; 101 } 102 103 public boolean isEquality() { 104 switch (this) { 105 case Equal: 106 case NotEqual: 107 return true; 108 default: 109 return false; 110 } 111 } 112 113 public boolean isInequality() { 114 return !isEquality(); 115 } 116 } 117}