diff --git a/python/common/org/Python.java b/python/common/org/Python.java index 472178dc20..500976c880 100644 --- a/python/common/org/Python.java +++ b/python/common/org/Python.java @@ -1066,11 +1066,7 @@ public static org.python.Object max(org.python.types.Tuple args, org.python.Obje } private static boolean compareKeys(org.python.Object first, org.python.Object second) { - return org.python.types.Object.__cmp__( - first, - second, - org.python.types.Object.CMP_OP.GT - ).toBoolean(); + return org.python.types.Object.__gt__(first, second).toBoolean(); } @org.python.Method( @@ -1584,11 +1580,11 @@ public __SortedObjectComparator(boolean reverse) { public int compare(org.python.Object o1, org.python.Object o2) { o1 = applyKey(o1, key); o2 = applyKey(o2, key); - org.python.Object result = org.python.types.Object.__cmp_bool__(o1, o2, org.python.types.Object.CMP_OP.LT); + org.python.Object result = org.python.types.Object.__lt__(o1, o2); if (result.toBoolean()) { return reverse ? 1 : -1; } - result = org.python.types.Object.__cmp_bool__(o2, o1, org.python.types.Object.CMP_OP.LT); + result = org.python.types.Object.__lt__(o2, o1); if (result.toBoolean()) { return reverse ? -1 : 1; } diff --git a/python/common/org/python/types/List.java b/python/common/org/python/types/List.java index 094fdd83bb..8d854ff6f7 100644 --- a/python/common/org/python/types/List.java +++ b/python/common/org/python/types/List.java @@ -198,8 +198,8 @@ public org.python.Object __lt__(org.python.Object other) { // check how many items are identical on the lists int i = 0; for (i = 0; i < count; i++) { - org.python.types.Bool result = (org.python.types.Bool) org.python.types.Object.__cmp_bool__( - this.value.get(i), otherList.value.get(i), org.python.types.Object.CMP_OP.EQ); + org.python.types.Bool result = (org.python.types.Bool) org.python.types.Object.__cmp_eq__( + this.value.get(i), otherList.value.get(i)); if (!result.value) { break; } @@ -207,8 +207,7 @@ public org.python.Object __lt__(org.python.Object other) { // not all items were identical, result is that of the first non-identical item if (i < count) { - return org.python.types.Object.__cmp_bool__(this.value.get(i), otherList.value.get(i), - org.python.types.Object.CMP_OP.LT); + return org.python.types.Object.__lt__(this.value.get(i), otherList.value.get(i)); } // all items were identical, break tie by size @@ -232,8 +231,8 @@ public org.python.Object __le__(org.python.Object other) { // check how many items are identical on the lists int i = 0; for (i = 0; i < count; i++) { - org.python.types.Bool result = (org.python.types.Bool) org.python.types.Object.__cmp_bool__( - this.value.get(i), otherList.value.get(i), org.python.types.Object.CMP_OP.EQ); + org.python.types.Bool result = (org.python.types.Bool) org.python.types.Object.__cmp_eq__( + this.value.get(i), otherList.value.get(i)); if (!result.value) { break; } @@ -241,8 +240,7 @@ public org.python.Object __le__(org.python.Object other) { // not all items were identical, result is that of the first non-identical item if (i < count) { - return org.python.types.Object.__cmp_bool__(this.value.get(i), otherList.value.get(i), - org.python.types.Object.CMP_OP.LE); + return org.python.types.Object.__le__(this.value.get(i), otherList.value.get(i)); } // all items were identical, break tie by size @@ -278,8 +276,8 @@ public org.python.Object __gt__(org.python.Object other) { // check how many items are identical on the lists int i = 0; for (i = 0; i < count; i++) { - org.python.types.Bool result = (org.python.types.Bool) org.python.types.Object.__cmp_bool__( - this.value.get(i), otherList.value.get(i), org.python.types.Object.CMP_OP.EQ); + org.python.types.Bool result = (org.python.types.Bool) org.python.types.Object.__cmp_eq__( + this.value.get(i), otherList.value.get(i)); if (!result.value) { break; } @@ -287,8 +285,7 @@ public org.python.Object __gt__(org.python.Object other) { // not all items were identical, result is that of the first non-identical item if (i < count) { - return org.python.types.Object.__cmp_bool__(this.value.get(i), otherList.value.get(i), - org.python.types.Object.CMP_OP.GT); + return org.python.types.Object.__gt__(this.value.get(i), otherList.value.get(i)); } // all items were identical, break tie by size @@ -312,8 +309,8 @@ public org.python.Object __ge__(org.python.Object other) { // check how many items are identical on the lists int i = 0; for (i = 0; i < count; i++) { - org.python.types.Bool result = (org.python.types.Bool) org.python.types.Object.__cmp_bool__( - this.value.get(i), otherList.value.get(i), org.python.types.Object.CMP_OP.EQ); + org.python.types.Bool result = (org.python.types.Bool) org.python.types.Object.__cmp_eq__( + this.value.get(i), otherList.value.get(i)); if (!result.value) { break; } @@ -321,8 +318,7 @@ public org.python.Object __ge__(org.python.Object other) { // not all items were identical, result is that of the first non-identical item if (i < count) { - return org.python.types.Object.__cmp_bool__(this.value.get(i), otherList.value.get(i), - org.python.types.Object.CMP_OP.GE); + return org.python.types.Object.__ge__(this.value.get(i), otherList.value.get(i)); } // all items were identical, break tie by size @@ -553,8 +549,8 @@ public org.python.Object __reversed__() { public org.python.Object __contains__(org.python.Object item) { boolean found = false; for (int i = 0; i < this.value.size(); i++) { - if (((org.python.types.Bool) org.python.types.Object.__cmp_bool__( - item, this.value.get(i), org.python.types.Object.CMP_OP.EQ)).value) { + if (((org.python.types.Bool) org.python.types.Object.__cmp_eq__( + item, this.value.get(i))).value) { found = true; break; } @@ -664,8 +660,8 @@ public org.python.Object copy() { public org.python.Object count(org.python.Object other) { int count = 0; for (int i = 0; i < this.value.size(); i++) { - if (((org.python.types.Bool) org.python.types.Object.__cmp_bool__( - other, this.value.get(i), org.python.types.Object.CMP_OP.EQ)).value) { + if (((org.python.types.Bool) org.python.types.Object.__cmp_eq__( + other, this.value.get(i))).value) { count++; } } @@ -763,8 +759,8 @@ public org.python.Object index(org.python.Object item, org.python.Object start, } for (int i = iStart; i < Math.min(iEnd, this.value.size()); i++) { - if (((org.python.types.Bool) org.python.types.Object.__cmp_bool__( - item, this.value.get(i), org.python.types.Object.CMP_OP.EQ)).value) { + if (((org.python.types.Bool) org.python.types.Object.__cmp_eq__( + item, this.value.get(i))).value) { return org.python.types.Int.getInt(i); } } @@ -818,8 +814,8 @@ public org.python.Object pop(org.python.Object item) { ) public org.python.Object remove(org.python.Object item) { for (int i = 0; i < this.value.size(); i++) { - if (((org.python.types.Bool) org.python.types.Object.__cmp_bool__( - item, this.value.get(i), org.python.types.Object.CMP_OP.EQ)).value) { + if (((org.python.types.Bool) org.python.types.Object.__cmp_eq__( + item, this.value.get(i))).value) { this.value.remove(i); return org.python.types.NoneType.NONE; } diff --git a/python/common/org/python/types/Object.java b/python/common/org/python/types/Object.java index ff7f82260d..33eaf3477d 100644 --- a/python/common/org/python/types/Object.java +++ b/python/common/org/python/types/Object.java @@ -105,7 +105,7 @@ public Object(org.python.Object[] args, java.util.Map=", "__ge__", "__le__"), - GT(">", "__gt__", "__lt__"), - EQ("==", "__eq__", "__eq__"), - NE("!=", "__ne__", "__ne__"), - LE("<=", "__le__", "__ge__"), - LT("<", "__lt__", "__gt__"); + /* This method is used from standard library container datatypes */ // FIXME provide more useful comment? + public static org.python.Object __cmp_eq__(org.python.Object v, org.python.Object w) { + // identity implies equality + if (v == w) { + return org.python.types.Bool.TRUE; + } + org.python.Object result = __eq__(v, w); + return (result instanceof org.python.types.Bool) ? result : result.__bool__(); + } - public final String oper; - public final String operMethod; - public final String reflOperMethod; - CMP_OP(java.lang.String oper, java.lang.String operMethod, java.lang.String reflOperMethod) { - this.oper = oper; - this.operMethod = operMethod; - this.reflOperMethod = reflOperMethod; + /* This method is used from standard library container datatypes */ + public static org.python.Object __cmp_ne__(org.python.Object v, org.python.Object w) { + // identity implies equality + if (v != w) { + return org.python.types.Bool.TRUE; } + org.python.Object result = __ne__(v, w); + return (result instanceof org.python.types.Bool) ? result : result.__bool__(); } - /* This method is used from standard library datatypes, etc */ - public static org.python.Object __cmp__(org.python.Object v, org.python.Object w, - org.python.types.Object.CMP_OP op) { - return __cmp__(v, w, op.oper, op.operMethod, op.reflOperMethod); + private static boolean isBuiltin(org.python.Object obj) { + return obj instanceof org.python.types.Int || obj instanceof org.python.types.Str || + obj instanceof org.python.types.Bool || obj instanceof org.python.types.Float || + obj instanceof org.python.types.List || obj instanceof org.python.types.Dict || + obj instanceof org.python.types.Tuple || obj instanceof org.python.types.Set || + obj instanceof org.python.types.Range || obj instanceof org.python.types.Slice || + obj instanceof org.python.types.Bytes || obj instanceof org.python.types.Complex || + obj instanceof org.python.types.ByteArray || obj instanceof org.python.types.FrozenSet || + obj instanceof org.python.types.MemoryView; } - /* This method is used from standard library container datatypes */ - public static org.python.Object __cmp_bool__(org.python.Object v, org.python.Object w, - org.python.types.Object.CMP_OP op) { - // identity implies equality - if (v == w) { - if (op == org.python.types.Object.CMP_OP.EQ) { - return org.python.types.Bool.TRUE; - } else if (op == org.python.types.Object.CMP_OP.NE) { - return org.python.types.Bool.FALSE; + public static org.python.Object __lt__(org.python.Object v, org.python.Object w) { + org.python.Object result = org.python.types.NotImplementedType.NOT_IMPLEMENTED; + boolean reflectedChecked = v.type() != w.type() + && ((org.python.types.Bool) org.Python.isinstance(w, v.type())).value; + boolean v_builtin = isBuiltin(v); + boolean w_builtin = isBuiltin(w); + + // Reflective case + if (reflectedChecked) { + if (w_builtin) { + result = w.__gt__(v); + } else { + result = invokeComparison(w, v, "__gt__"); + } + + if (result != org.python.types.NotImplementedType.NOT_IMPLEMENTED) { + return result; + } + } + + // Normal case + if (v_builtin) { + result = v.__lt__(w); + } else { + result = invokeComparison(v, w, "__lt__"); + } + if (result != org.python.types.NotImplementedType.NOT_IMPLEMENTED) { + return result; + } + + // Now check reflection + if (!reflectedChecked) { + if (w_builtin) { + result = w.__gt__(v); + } else { + result = invokeComparison(w, v, "__gt__"); + } + + if (result != org.python.types.NotImplementedType.NOT_IMPLEMENTED) { + return result; + } + } + + // Error case + if (org.Python.VERSION < 0x03060000) { + throw new org.python.exceptions.TypeError(String.format( + "unorderable types: %s() %s %s()", v.typeName(), "<", w.typeName())); + } else { + throw new org.python.exceptions.TypeError(String.format( + "'%s' not supported between instances of '%s' and '%s'", "<", v.typeName(), w.typeName())); + } + } + + public static org.python.Object __le__(org.python.Object v, org.python.Object w) { + org.python.Object result = org.python.types.NotImplementedType.NOT_IMPLEMENTED; + boolean reflectedChecked = v.type() != w.type() + && ((org.python.types.Bool) org.Python.isinstance(w, v.type())).value; + + boolean v_builtin = isBuiltin(v); + boolean w_builtin = isBuiltin(w); + + + // Reflective case + if (reflectedChecked) { + if (w_builtin) { + result = w.__ge__(v); + } else { + result = invokeComparison(w, v, "__ge__"); + } + + if (result != org.python.types.NotImplementedType.NOT_IMPLEMENTED) { + return result; + } + } + + // Normal case + if (v_builtin) { + result = v.__le__(w); + } else { + result = invokeComparison(v, w, "__le__"); + } + if (result != org.python.types.NotImplementedType.NOT_IMPLEMENTED) { + return result; + } + + // Now check reflection + if (!reflectedChecked) { + if (w_builtin) { + result = w.__ge__(v); + } else { + result = invokeComparison(w, v, "__ge__"); + } + + if (result != org.python.types.NotImplementedType.NOT_IMPLEMENTED) { + return result; + } + } + + // Error case + if (org.Python.VERSION < 0x03060000) { + throw new org.python.exceptions.TypeError(String.format( + "unorderable types: %s() %s %s()", v.typeName(), "<=", w.typeName())); + } else { + throw new org.python.exceptions.TypeError(String.format( + "'%s' not supported between instances of '%s' and '%s'", "<=", v.typeName(), w.typeName())); + } + } + + public static org.python.Object __eq__(org.python.Object v, org.python.Object w) { + org.python.Object result = org.python.types.NotImplementedType.NOT_IMPLEMENTED; + boolean reflectedChecked = v.type() != w.type() + && ((org.python.types.Bool) org.Python.isinstance(w, v.type())).value; + + boolean v_builtin = isBuiltin(v); + boolean w_builtin = isBuiltin(w); + + // Reflective case + if (reflectedChecked) { + if (w_builtin) { + result = w.__eq__(v); + } else { + result = invokeComparison(w, v, "__eq__"); + } + + if (result != org.python.types.NotImplementedType.NOT_IMPLEMENTED) { + return result; + } + } + + // Normal case + if (v_builtin) { + result = v.__eq__(w); + } else { + result = invokeComparison(v, w, "__eq__"); + } + if (result != org.python.types.NotImplementedType.NOT_IMPLEMENTED) { + return result; + } + + // Now check reflection + if (!reflectedChecked) { + if (w_builtin) { + result = w.__eq__(v); + } else { + result = invokeComparison(w, v, "__eq__"); + } + + if (result != org.python.types.NotImplementedType.NOT_IMPLEMENTED) { + return result; } } - org.python.Object result = __cmp__(v, w, op.oper, op.operMethod, op.reflOperMethod); - if (result instanceof org.python.types.Bool) { + + return org.python.types.Bool.getBool(v == w); + } + + public static org.python.Object __ne__(org.python.Object v, org.python.Object w) { + org.python.Object result = org.python.types.NotImplementedType.NOT_IMPLEMENTED; + boolean reflectedChecked = v.type() != w.type() + && ((org.python.types.Bool) org.Python.isinstance(w, v.type())).value; + boolean v_builtin = isBuiltin(v); + boolean w_builtin = isBuiltin(w); + + // Reflective case + if (reflectedChecked) { + if (w_builtin) { + result = w.__ne__(v); + } else { + result = invokeComparison(w, v, "__ne__"); + } + + if (result != org.python.types.NotImplementedType.NOT_IMPLEMENTED) { + return result; + } + } + + // Normal case + if (v_builtin) { + result = v.__ne__(w); + } else { + result = invokeComparison(v, w, "__ne__"); + } + + if (result != org.python.types.NotImplementedType.NOT_IMPLEMENTED) { return result; + } + + // Now check reflection + if (!reflectedChecked) { + if (w_builtin) { + result = w.__ne__(v); + } else { + result = invokeComparison(w, v, "__ne__"); + } + + if (result != org.python.types.NotImplementedType.NOT_IMPLEMENTED) { + return result; + } + } + + return org.python.types.Bool.getBool(v != w); + } + + public static org.python.Object __gt__(org.python.Object v, org.python.Object w) { + org.python.Object result = org.python.types.NotImplementedType.NOT_IMPLEMENTED; + boolean reflectedChecked = v.type() != w.type() + && ((org.python.types.Bool) org.Python.isinstance(w, v.type())).value; + boolean v_builtin = isBuiltin(v); + boolean w_builtin = isBuiltin(w); + + // Reflective case + if (reflectedChecked) { + if (w_builtin) { + result = w.__lt__(v); + } else { + result = invokeComparison(w, v, "__lt__"); + } + + if (result != org.python.types.NotImplementedType.NOT_IMPLEMENTED) { + return result; + } + } + + // Normal case + if (v_builtin) { + result = v.__gt__(w); } else { - return result.__bool__(); + result = invokeComparison(v, w, "__gt__"); + } + + if (result != org.python.types.NotImplementedType.NOT_IMPLEMENTED) { + return result; + } + + // Now check reflection + if (!reflectedChecked) { + if (w_builtin) { + result = w.__lt__(v); + } else { + result = invokeComparison(w, v, "__lt__"); + } + + if (result != org.python.types.NotImplementedType.NOT_IMPLEMENTED) { + return result; + } + } + + // Error case + if (org.Python.VERSION < 0x03060000) { + throw new org.python.exceptions.TypeError(String.format( + "unorderable types: %s() %s %s()", v.typeName(), ">", w.typeName())); + } else { + throw new org.python.exceptions.TypeError(String.format( + "'%s' not supported between instances of '%s' and '%s'", ">", v.typeName(), w.typeName())); } } - /* This method is invoked from the AST for Compare nodes */ - public static org.python.Object __cmp__(org.python.Object v, org.python.Object w, java.lang.String oper, - java.lang.String operMethod, java.lang.String reflOperMethod) { + public static org.python.Object __ge__(org.python.Object v, org.python.Object w) { org.python.Object result = org.python.types.NotImplementedType.NOT_IMPLEMENTED; boolean reflectedChecked = v.type() != w.type() && ((org.python.types.Bool) org.Python.isinstance(w, v.type())).value; + boolean v_builtin = isBuiltin(v); + boolean w_builtin = isBuiltin(w); + // Reflective case if (reflectedChecked) { - result = invokeComparison(w, v, reflOperMethod); + if (w_builtin) { + result = w.__le__(v); + } else { + result = invokeComparison(w, v, "__le__"); + } + if (result != org.python.types.NotImplementedType.NOT_IMPLEMENTED) { return result; } } - result = invokeComparison(v, w, operMethod); + // Normal case + if (v_builtin) { + result = v.__ge__(w); + } else { + result = invokeComparison(v, w, "__ge__"); + } + if (result != org.python.types.NotImplementedType.NOT_IMPLEMENTED) { return result; } + // Now check reflection if (!reflectedChecked) { - result = invokeComparison(w, v, reflOperMethod); + if (w_builtin) { + result = w.__le__(v); + } else { + result = invokeComparison(w, v, "__le__"); + } + if (result != org.python.types.NotImplementedType.NOT_IMPLEMENTED) { return result; } } - if (oper.equals("==")) { - return org.python.types.Bool.getBool(v == w); - } else if (oper.equals("!=")) { - return org.python.types.Bool.getBool(v != w); + // Error case + if (org.Python.VERSION < 0x03060000) { + throw new org.python.exceptions.TypeError(String.format( + "unorderable types: %s() %s %s()", v.typeName(), ">=", w.typeName())); + } else { + throw new org.python.exceptions.TypeError(String.format( + "'%s' not supported between instances of '%s' and '%s'", ">=", v.typeName(), w.typeName())); + } + } + + public static org.python.Object __contains__(org.python.Object v, org.python.Object w) { + boolean v_builtin = isBuiltin(v); + org.python.Object result = null; + + if (v_builtin) { + result = v.__contains__(w); + } else { + result = invokeComparison(v, w, "__contains__"); + } + + if (result != org.python.types.NotImplementedType.NOT_IMPLEMENTED) { + return result; + } + + // Error case + if (org.Python.VERSION < 0x03060000) { + throw new org.python.exceptions.TypeError(String.format( + "unorderable types: %s() %s %s()", v.typeName(), "in", w.typeName())); + } else { + throw new org.python.exceptions.TypeError(String.format( + "'%s' not supported between instances of '%s' and '%s'", "in", v.typeName(), w.typeName())); + } + } + + public static org.python.Object __not_contains__(org.python.Object v, org.python.Object w) { + boolean v_builtin = isBuiltin(v); + org.python.Object result = null; + // Normal case + if (v_builtin) { + result = v.__not_contains__(w); + } else { + result = invokeComparison(v, w, "__not_contains__"); + } + + if (result != org.python.types.NotImplementedType.NOT_IMPLEMENTED) { + return result; } + // Error case if (org.Python.VERSION < 0x03060000) { throw new org.python.exceptions.TypeError(String.format( - "unorderable types: %s() %s %s()", v.typeName(), oper, w.typeName())); + "unorderable types: %s() %s %s()", v.typeName(), "not in", w.typeName())); } else { throw new org.python.exceptions.TypeError(String.format( - "'%s' not supported between instances of '%s' and '%s'", oper, v.typeName(), w.typeName())); + "'%s' not supported between instances of '%s' and '%s'", "not in", v.typeName(), w.typeName())); } } diff --git a/python/common/org/python/types/Super.java b/python/common/org/python/types/Super.java index f1b6eba02f..ff0d6a777d 100644 --- a/python/common/org/python/types/Super.java +++ b/python/common/org/python/types/Super.java @@ -60,7 +60,7 @@ public Super(org.python.Object klass, org.python.Object instance) { */ public boolean equals(java.lang.Object other) { if (other instanceof org.python.Object) { - org.python.Object result = org.python.types.Object.__cmp_bool__(this, (org.python.Object) other, org.python.types.Object.CMP_OP.EQ); + org.python.Object result = org.python.types.Object.__eq__(this, (org.python.Object) other); return ((org.python.types.Bool) result).value; } else { throw new org.python.exceptions.RuntimeError("Can't compare a Python object with non-Python object."); diff --git a/python/common/org/python/types/Tuple.java b/python/common/org/python/types/Tuple.java index 7f2c5652fc..ac97f061ef 100644 --- a/python/common/org/python/types/Tuple.java +++ b/python/common/org/python/types/Tuple.java @@ -119,8 +119,8 @@ public org.python.Object __lt__(org.python.Object other) { // check how many items are identical on the lists int i = 0; for (i = 0; i < count; i++) { - org.python.types.Bool result = (org.python.types.Bool) org.python.types.Object.__cmp_bool__( - this.value.get(i), otherTuple.value.get(i), org.python.types.Object.CMP_OP.EQ); + org.python.types.Bool result = (org.python.types.Bool) org.python.types.Object.__cmp_eq__( + this.value.get(i), otherTuple.value.get(i)); if (!result.value) { break; } @@ -128,8 +128,7 @@ public org.python.Object __lt__(org.python.Object other) { // not all items were identical, result is that of the first non-identical item if (i < count) { - return org.python.types.Object.__cmp_bool__(this.value.get(i), otherTuple.value.get(i), - org.python.types.Object.CMP_OP.LT); + return org.python.types.Object.__lt__(this.value.get(i), otherTuple.value.get(i)); } // all items were identical, break tie by size @@ -153,8 +152,8 @@ public org.python.Object __le__(org.python.Object other) { // check how many items are identical on the lists int i = 0; for (i = 0; i < count; i++) { - org.python.types.Bool result = (org.python.types.Bool) org.python.types.Object.__cmp_bool__( - this.value.get(i), otherTuple.value.get(i), org.python.types.Object.CMP_OP.EQ); + org.python.types.Bool result = (org.python.types.Bool) org.python.types.Object.__cmp_eq__( + this.value.get(i), otherTuple.value.get(i)); if (!result.value) { break; } @@ -162,8 +161,7 @@ public org.python.Object __le__(org.python.Object other) { // not all items were identical, result is that of the first non-identical item if (i < count) { - return org.python.types.Object.__cmp_bool__(this.value.get(i), otherTuple.value.get(i), - org.python.types.Object.CMP_OP.LE); + return org.python.types.Object.__le__(this.value.get(i), otherTuple.value.get(i)); } // all items were identical, break tie by size @@ -199,8 +197,8 @@ public org.python.Object __gt__(org.python.Object other) { // check how many items are identical on the lists int i = 0; for (i = 0; i < count; i++) { - org.python.types.Bool result = (org.python.types.Bool) org.python.types.Object.__cmp_bool__( - this.value.get(i), otherTuple.value.get(i), org.python.types.Object.CMP_OP.EQ); + org.python.types.Bool result = (org.python.types.Bool) org.python.types.Object.__cmp_eq__( + this.value.get(i), otherTuple.value.get(i)); if (!result.value) { break; } @@ -208,8 +206,7 @@ public org.python.Object __gt__(org.python.Object other) { // not all items were identical, result is that of the first non-identical item if (i < count) { - return org.python.types.Object.__cmp_bool__(this.value.get(i), otherTuple.value.get(i), - org.python.types.Object.CMP_OP.GT); + return org.python.types.Object.__gt__(this.value.get(i), otherTuple.value.get(i)); } // all items were identical, break tie by size @@ -233,8 +230,8 @@ public org.python.Object __ge__(org.python.Object other) { // check how many items are identical on the lists int i = 0; for (i = 0; i < count; i++) { - org.python.types.Bool result = (org.python.types.Bool) org.python.types.Object.__cmp_bool__( - this.value.get(i), otherTuple.value.get(i), org.python.types.Object.CMP_OP.EQ); + org.python.types.Bool result = (org.python.types.Bool) org.python.types.Object.__cmp_eq__( + this.value.get(i), otherTuple.value.get(i)); if (!result.value) { break; } @@ -242,8 +239,7 @@ public org.python.Object __ge__(org.python.Object other) { // not all items were identical, result is that of the first non-identical item if (i < count) { - return org.python.types.Object.__cmp_bool__(this.value.get(i), otherTuple.value.get(i), - org.python.types.Object.CMP_OP.GE); + return org.python.types.Object.__ge__(this.value.get(i), otherTuple.value.get(i)); } // all items were identical, break tie by size diff --git a/tests/benchmarks.py b/tests/benchmarks.py index f5655d660e..1f1a63762c 100644 --- a/tests/benchmarks.py +++ b/tests/benchmarks.py @@ -138,6 +138,37 @@ def yarn(n): main(i) """), timed=True) +def test_cmp(test_case): + print("Running", "test_cmp") + test_case.runAsJava(adjust(""" + x = None + s = "mary had a little lamb" + t = "humpty dumpty sat on a wall" + + for i in range(1000): + for j in range(1000): + x = s < t + x = s <= t + x = s == t + x = s != t + x = s > t + x = s >= t + + x = 3 < 5 + x = 3 <= 5 + x = 3 == 5 + x = 3 != 5 + x = 3 > 5 + x = 3 >= 5 + + x = 3 < True + x = 3.0 <= 5 + x = None == 5 + x = [3] != 5.0 + x = [3] > [5] + x = [3.0] > [5.0] + """), timed=True) + def main(): test_case = TranspileTestCase() test_case.setUpClass() @@ -147,6 +178,7 @@ def main(): test_class_var_load(test_case) test_function_var_load(test_case) test_code(test_case) + test_cmp(test_case) if __name__== "__main__": main() diff --git a/voc/python/ast.py b/voc/python/ast.py index c72e06d8be..ac4f37789f 100644 --- a/voc/python/ast.py +++ b/voc/python/ast.py @@ -1884,65 +1884,79 @@ def compare_to(arg): ) else: - if isinstance(arg, (ast.In, ast.NotIn)): + if isinstance(arg, (ast.Eq, ast.Is)): self.context.add_opcodes( - JavaOpcodes.SWAP() + JavaOpcodes.INVOKESTATIC( + 'org/python/types/Object', + '__eq__', + args=['Lorg/python/Object;', 'Lorg/python/Object;'], + returns='Lorg/python/Object;'), ) - oper = { - ast.Eq: '__eq__', - ast.Gt: '__gt__', - ast.GtE: '__ge__', - ast.Lt: '__lt__', - ast.LtE: '__le__', - ast.In: '__contains__', - ast.Is: '__eq__', - ast.IsNot: '__ne__', - ast.NotEq: '__ne__', - ast.NotIn: '__not_contains__', - }[type(arg)] - oper_symbol = { - ast.Eq: '==', - ast.Gt: '>', - ast.GtE: '>=', - ast.Lt: '<', - ast.LtE: '<=', - ast.In: 'in', - ast.Is: 'is', - ast.IsNot: 'is not', - ast.NotEq: '!=', - ast.NotIn: 'not in', - }[type(arg)] - reflect_oper = { - ast.Eq: '__eq__', - ast.Gt: '__lt__', - ast.GtE: '__le__', - ast.Lt: '__gt__', - ast.LtE: '__ge__', - ast.In: '__contains__', - ast.Is: '__eq__', - ast.IsNot: '__ne__', - ast.NotEq: '__ne__', - ast.NotIn: '__not_contains__', - }[type(arg)] + if isinstance(arg, (ast.NotEq, ast.IsNot)): + self.context.add_opcodes( + JavaOpcodes.INVOKESTATIC( + 'org/python/types/Object', + '__ne__', + args=['Lorg/python/Object;', 'Lorg/python/Object;'], + returns='Lorg/python/Object;'), + ) - self.context.add_opcodes( - JavaOpcodes.LDC_W(oper_symbol), - JavaOpcodes.LDC_W(oper), - JavaOpcodes.LDC_W(reflect_oper), - JavaOpcodes.INVOKESTATIC( - 'org/python/types/Object', - '__cmp__', - args=[ - 'Lorg/python/Object;', - 'Lorg/python/Object;', - 'Ljava/lang/String;', - 'Ljava/lang/String;', - 'Ljava/lang/String;', - ], - returns='Lorg/python/Object;', - ), - ) + if isinstance(arg, ast.Lt): + self.context.add_opcodes( + JavaOpcodes.INVOKESTATIC( + 'org/python/types/Object', + '__lt__', + args=['Lorg/python/Object;', 'Lorg/python/Object;'], + returns='Lorg/python/Object;'), + ) + + if isinstance(arg, ast.LtE): + self.context.add_opcodes( + JavaOpcodes.INVOKESTATIC( + 'org/python/types/Object', + '__le__', + args=['Lorg/python/Object;', 'Lorg/python/Object;'], + returns='Lorg/python/Object;'), + ) + + if isinstance(arg, ast.Gt): + self.context.add_opcodes( + JavaOpcodes.INVOKESTATIC( + 'org/python/types/Object', + '__gt__', + args=['Lorg/python/Object;', 'Lorg/python/Object;'], + returns='Lorg/python/Object;'), + ) + + if isinstance(arg, ast.GtE): + self.context.add_opcodes( + JavaOpcodes.INVOKESTATIC( + 'org/python/types/Object', + '__ge__', + args=['Lorg/python/Object;', 'Lorg/python/Object;'], + returns='Lorg/python/Object;'), + ) + + if isinstance(arg, ast.In): + self.context.add_opcodes( + JavaOpcodes.SWAP(), + JavaOpcodes.INVOKESTATIC( + 'org/python/types/Object', + '__contains__', + args=['Lorg/python/Object;', 'Lorg/python/Object;'], + returns='Lorg/python/Object;'), + ) + + if isinstance(arg, ast.NotIn): + self.context.add_opcodes( + JavaOpcodes.SWAP(), + JavaOpcodes.INVOKESTATIC( + 'org/python/types/Object', + '__not_contains__', + args=['Lorg/python/Object;', 'Lorg/python/Object;'], + returns='Lorg/python/Object;'), + ) self.visit(node.left) left = node.left