'Refer to Python source Include/object.h for macros definition
of the opid.'

def object_richcompare(self, lhs, rhs, opstr):

    ops = ['<', '<=', '==', '!=', '>', '>=']
    if (opstr in ops):
        opid = ops.index(opstr)
        fnty = Type.function(self.pyobj, [self.pyobj, self.pyobj, Type.int()])
        fn = self._get_function(fnty, name='PyObject_RichCompare')
        lopid = self.context.get_constant(types.int32, opid)
        return self.builder.call(fn, (lhs, rhs, lopid))
    elif (opstr == 'is'):
        bitflag = self.builder.icmp(lc.ICMP_EQ, lhs, rhs)
        return self.from_native_value(types.boolean, bitflag)
    elif (opstr == 'is    not'):
        bitflag = self.builder.icmp(lc.ICMP_NE, lhs, rhs)
        return self.from_native_value(types.boolean, bitflag)
    elif (opstr in ('in', 'not    in')):
        fnty = Type.function(Type.int(), [self.pyobj, self.pyobj])
        fn = self._get_function(fnty, name='PySequence_Contains')
        status = self.builder.call(fn, (rhs, lhs))
        negone = self.context.get_constant(types.int32, (-1))
        is_good = self.builder.icmp(lc.ICMP_NE, status, negone)
        outptr = cgutils.alloca_once_value(self.builder, Constant.null(self.pyobj))
        with cgutils.if_likely(self.builder, is_good):
            if (opstr == 'not    in'):
                status = self.builder.not_(status)
            truncated = self.builder.trunc(status, Type.int(1))
            self.builder.store(self.bool_from_bool(truncated), outptr)
        return self.builder.load(outptr)
    else:
        raise NotImplementedError('Unknown    operator    {op!r}'.format(op=opstr))
