Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
105 commits
Select commit Hold shift + click to select a range
6212083
Begin multi-project structure natural to Gradle
jeff5 Jul 31, 2020
a6b94a7
Delete extlibs: an end to bundled JARs
jeff5 Jul 31, 2020
ed74ab1
Travis CI on JDKs 8, 11, 13 and add Windows to OSes
cclauss Jun 15, 2020
f3b0978
Improvements to Travis CI coverage and greenness
jeff5 Jul 30, 2020
26d21e6
Build (empty project) with Gradle on Travis CI
jeff5 Jul 31, 2020
5cce78e
Remove bugtests and some IDE files
jeff5 Aug 1, 2020
1569a2a
Emphasise 3.8 status in README and add link to 2.7
jeff5 Jan 18, 2021
6dd607f
Travis CI: Add comment linking to homebrew-openjdk (#88)
cclauss Mar 19, 2021
7ed1426
Foundation classes of the v3.8 data model
jeff5 Jul 11, 2021
af4fbdd
[Build fails] Move PyLong and parts of stringlib from 2 to 3
jeff5 Jul 14, 2021
4a26e5a
Get the re-used Jython 2 code to compile
jeff5 Jul 18, 2021
5333c0d
Support Python in the Gradle build
jeff5 Jul 20, 2021
4d44f98
Add the bool type and extend a test to it
jeff5 Jul 22, 2021
482e402
Formatting change to PyType
jeff5 Jul 22, 2021
457eab2
Expose special functions as slots in Operations
jeff5 Jul 22, 2021
bf47faf
Add a test of binary slot wrappers and refactor
jeff5 Jul 24, 2021
938d911
Begin to fill and use the op_* slots
jeff5 Jul 25, 2021
88203df
Begin to generate method specialisations in PyLongMethods
jeff5 Jul 25, 2021
42b4cd0
Implement int division and modulus
jeff5 Aug 1, 2021
1d7a057
Add all the special method slots and Javadoc them
jeff5 Aug 1, 2021
6122964
Rely on generated versions of the special methods (slots)
jeff5 Aug 5, 2021
aa95cf5
Copyright notices and some formatting
jeff5 Aug 5, 2021
d11547d
[Build fails] Remove stop-gap PyFloat
jeff5 Sep 4, 2021
809c1d5
[Build fails] Move Jython 2 PyFloat into core project
jeff5 Sep 4, 2021
f15cdda
Convert the implementation of float to Jython 3.8
jeff5 Sep 12, 2021
c331c8d
Floating-point floor-division and modulus conforms to Python 3
jeff5 Sep 15, 2021
35fd1b0
Switch to GitHub actions for unit test
jeff5 Oct 11, 2021
4d8b554
Implement Comparison enum and abstract API
jeff5 Nov 9, 2021
12edcb4
[Build fails] Remove stop-gap PyTuple
jeff5 Nov 10, 2021
2e068e9
[Build fails] Move Jython 2 PyTuple, PySequence and PySlice to core
jeff5 Nov 10, 2021
6011ff0
[Build fails] Preparatory work on sequence delegate and slices
jeff5 Nov 10, 2021
e02b795
[Build fails] Mark up PyTuple commenting out exposer annotations
jeff5 Nov 10, 2021
842aedc
Update PyTuple to Jython 3
jeff5 Nov 10, 2021
1f625e1
Implement slice for PyTuple and test
jeff5 Nov 18, 2021
0471501
[Build fails] Remove stop-gap PyUnicode
jeff5 Nov 21, 2021
d3fccaa
[Build fails] Move Jython 2 PyUnicode to new core
jeff5 Nov 21, 2021
309cacb
[Build fails] Mark-up exposed methods
jeff5 Nov 21, 2021
5099cb5
[Build fails] Move PyString code into PyUnicode
jeff5 Nov 27, 2021
38b824f
[Build fails] Re-write str.find, split, replace and similar
jeff5 Dec 14, 2021
fa90941
[Build fails] Many predicates and transformations in str
jeff5 Dec 23, 2021
ca0d3a9
[Build fails] Implement the strip methods in str and simplify
jeff5 Dec 24, 2021
87f9a73
[Build fails] Move Jython 2 format iterators to core
jeff5 Dec 30, 2021
5418dc4
Port __format__ support to Jython 3
jeff5 Dec 30, 2021
b110a0b
Make core:javadoc task run cleanly
jeff5 Dec 30, 2021
7c9cc0e
Factor out the int array builders from PyUnicode
jeff5 Jan 1, 2022
9ec6d47
Test that a Python str supports sequence operations
jeff5 Jan 1, 2022
0e32beb
Fix typos in comments and some formatting
jeff5 Jan 3, 2022
87ea2d5
Add test of our UTF-16 expectations
jeff5 Jan 3, 2022
18048f3
Merge PyUnicode for Jython 3 PR #147
jeff5 Jan 29, 2022
0ec6d5e
Simple Python examples and results
jeff5 Mar 28, 2022
4b60425
[Build fails] Remove stop-gap PyList
jeff5 Mar 29, 2022
258563c
[Build fails] Move legacy PyList to core project
jeff5 Mar 29, 2022
ce2c84c
[Build fails] Bulk changes to PyList method declarations
jeff5 Mar 30, 2022
5d9519c
Apply sequence delegate pattern to PyList
jeff5 Apr 3, 2022
a576d7a
Refactor PyList.sort
jeff5 Apr 8, 2022
6492c22
Additional exceptions and public types
jeff5 Apr 8, 2022
de55e18
Rudimentary implementation of bytes type
jeff5 Apr 9, 2022
fa0f2ca
Stop-gap implementation of dict type
jeff5 Apr 9, 2022
714bfce
Add framework classes for frame and code objects
jeff5 Apr 9, 2022
797725e
Implementations of code and frame for 3.8 byte code
jeff5 Apr 10, 2022
e0b852b
Implement a marshal module and test
jeff5 Apr 10, 2022
026336f
Demonstrate we can run some CPython byte code
jeff5 Apr 10, 2022
2efa2c5
Upgrade GitHub Actions on main branch (#167)
cclauss Apr 16, 2022
9f78e26
Merge branch 'main' into list-3.8
jeff5 May 3, 2022
ea7ebd3
Merge PyList implementation from PR #165
jeff5 May 3, 2022
ee7c68d
Merge PyList from 'main' into cpython-bytecode-3.8
jeff5 May 4, 2022
475cec8
Merge Cpython bytecode interpreter (PR #166)
jeff5 May 4, 2022
e5c27d7
Minor improvements in PyUnicode
jeff5 Aug 20, 2022
22b1093
Provide a parser for method argument lists
jeff5 Aug 20, 2022
64d3f0e
Enumerate methods in a built-in type
jeff5 Aug 21, 2022
98ee87e
Extend and refactor TypeExposerTest
jeff5 Aug 21, 2022
35b13c7
Implement method objects for built-in types
jeff5 Aug 21, 2022
90b30ba
Identifiers are interned java.lang.String by preference
jeff5 Aug 25, 2022
6d9882d
Implement calls on built-in from CPython byte code
jeff5 Aug 25, 2022
193631a
Implement Exposed.Member
jeff5 Sep 21, 2022
ff0a37a
Implement exposed get, set and delete
jeff5 Sep 23, 2022
d139bdd
Further test specification of Exposed.Member, Getter, etc.
jeff5 Sep 23, 2022
0ba2efe
Ensure that Java-inherited fields can be exposed
jeff5 Dec 16, 2022
b16dc42
Strengthen get-set descriptor exposure test
jeff5 Dec 16, 2022
eca847e
Explicitly choose Python 3.8 in build
jeff5 Dec 16, 2022
36f6aef
Merge branch 'main' into expose-bi-attr-3.8
jeff5 Dec 16, 2022
03cc1f1
Means expose attributes and members of built-in types PR #210
jeff5 Dec 17, 2022
48fbaba
Rename PyJavaMethod to PyJavaFunction
jeff5 Dec 30, 2022
e815693
Introduce the ModuleExposer and a test
jeff5 Dec 30, 2022
c4ba9fe
Test calling functions with a range of signatures
jeff5 Dec 31, 2022
27f79d7
PEP 489-ish extension module initialisation
jeff5 Jan 2, 2023
2b12cad
Begin a builtins module
jeff5 Jan 2, 2023
7a167a9
Show access to built-ins from byte code
jeff5 Jan 2, 2023
050bbf4
Implement simple conditional branching
jeff5 Jan 6, 2023
15b3f85
Disassemble Python examples used in tests
jeff5 Jan 6, 2023
e6c26d1
Implement indexed access opcodes
jeff5 Jan 6, 2023
09729ba
Implement comparison opcode
jeff5 Jan 7, 2023
9d11bd4
Expose functions from modules #227
jeff5 Feb 4, 2023
953bf0d
Merge branch 'main' into flow-control-opcodes-3.8
jeff5 Feb 4, 2023
8be597d
Merge flow control #229
jeff5 Feb 4, 2023
c9e2bc6
Update Gradle wrapper to 7.6
jeff5 Jun 4, 2023
7eaddca
Minimum Java version is 17
jeff5 Jun 4, 2023
75aef11
Use JUnit 5.10
jeff5 Jun 4, 2023
4efc90a
Rename CPython-specific classes for 3.11
jeff5 Jun 7, 2023
22f728e
Update classes needed for execution to 3.11
jeff5 Jun 8, 2023
c9da398
Introduce the 3.11 opcodes and implement some
jeff5 Jun 8, 2023
e9eeb64
Implement flow control opcodes
jeff5 Jun 8, 2023
a9a4942
Update workflow Java wrapper and permissions
jeff5 Jul 15, 2023
7e57b5c
Make java_object_gen.py friendly to use via API. (#294)
Stewori Dec 25, 2023
6449c88
Add APIdia badge for Jython 3 snapshot. (#358)
Stewori Sep 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Implement comparison opcode
We access existing comparison implementations from CPython byte code.
This allows us to provide examples of if-else and while loops. We fix a
minor bug this revealed in PyUnicode.
  • Loading branch information
jeff5 committed Jan 7, 2023
commit 09729baae082ad779dacd6c82bdf5519dc390eb5
11 changes: 10 additions & 1 deletion core/src/main/java/org/python/core/CPython38Frame.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c)2022 Jython Developers.
// Copyright (c)2023 Jython Developers.
// Licensed to PSF under a contributor agreement.
package org.python.core;

Expand Down Expand Up @@ -246,6 +246,15 @@ Object eval() {
s[sp - 1] = Abstract.getAttr(s[sp - 1], name);
break;

case Opcode.COMPARE_OP:
// v | w | -> | op(v,w) |
// -------^sp -----------^sp
w = s[--sp]; // POP
v = s[sp - 1]; // TOP
s[sp - 1] = Comparison.from(opword & 0xff).apply(v, w);
oparg = 0;
break;

case Opcode.JUMP_FORWARD:
ip += (oparg | opword & 0xff) >> 1;
oparg = 0;
Expand Down
39 changes: 24 additions & 15 deletions core/src/main/java/org/python/core/Comparison.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c)2021 Jython Developers.
// Copyright (c)2023 Jython Developers.
// Licensed to PSF under a contributor agreement.
package org.python.core;

Expand Down Expand Up @@ -61,39 +61,48 @@ enum Comparison {
boolean toBool(int c) { return c >= 0; }
},

/** The (reflected) {@code __contains__} operation. */
/**
* The {@code in} operation (reflected {@code __contains__}). Note
* that "{@code v in seq}" compiles to<pre>
* LOAD_NAME 0 (v)
* LOAD_NAME 1 (seq)
* COMPARE_OP 6 (in)
* </pre> which must lead to {@code seq.__contains__(v)}.
*/
IN("in", Slot.op_contains) {

@Override
boolean toBool(int c) { return c >= 0; }

@Override
Object apply(Object v, Object w) throws Throwable {
Operations vOps = Operations.of(v);
Object apply(Object v, Object seq) throws Throwable {
Operations ops = Operations.of(seq);
try {
MethodHandle contains = slot.getSlot(vOps);
return (boolean)contains.invokeExact(w, v);
MethodHandle contains = slot.getSlot(ops);
return (boolean)contains.invokeExact(seq, v);
} catch (Slot.EmptyException e) {
throw new TypeError(NOT_CONTAINER, vOps.type(v).name);
throw new TypeError(NOT_CONTAINER, ops.type(seq).name);
}
}
},

/** The inverted (reflected) {@code __contains__} operation. */
/**
* The inverted {@code in} operation (reflected
* {@code __contains__}).
*/
NOT_IN("not in", Slot.op_contains) {

@Override
boolean toBool(int c) { return c < 0; }

@Override
Object apply(Object v, Object w) throws Throwable {
Operations vOps = Operations.of(v);
;
Object apply(Object v, Object seq) throws Throwable {
Operations ops = Operations.of(seq);
try {
MethodHandle contains = slot.getSlot(vOps);
return (boolean)contains.invokeExact(w, v);
MethodHandle contains = slot.getSlot(ops);
return !(boolean)contains.invokeExact(seq, v);
} catch (Slot.EmptyException e) {
throw new TypeError(NOT_CONTAINER, vOps.type(v).name);
throw new TypeError(NOT_CONTAINER, ops.type(seq).name);
}
}
},
Expand Down Expand Up @@ -161,7 +170,7 @@ Object apply(Object v, Object w) throws Throwable {
public String toString() { return text; }

/**
* Translate CPython {@code Opcode.COMPARE_OP} opcode argument to
* Translate CPython {@link Opcode#COMPARE_OP} opcode argument to
* Comparison constant.
*
* @param oparg opcode argument
Expand Down
17 changes: 10 additions & 7 deletions core/src/main/java/org/python/core/PyUnicode.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c)2021 Jython Developers.
// Copyright (c)2023 Jython Developers.
// Licensed to PSF under a contributor agreement.
package org.python.core;

Expand Down Expand Up @@ -409,14 +409,17 @@ private static boolean __contains__(String self, Object o) {

private static boolean contains(CodepointDelegate s, Object o) {
try {
CodepointDelegate p = adapt(s);
CodepointDelegate p = adapt(o);
PySlice.Indices slice = getSliceIndices(s, null, null);
return find(s, p, slice) >= 0;
} catch (NoConversion nc) {
throw Abstract.requiredTypeError("a string", o);
throw Abstract.typeError(IN_STRING_TYPE, o);
}
}

private static final String IN_STRING_TYPE =
"'in <string>' requires string as left operand, not %s";

/*
@ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.unicode___add___doc)
*/
Expand Down Expand Up @@ -2730,7 +2733,7 @@ static final Object __format__(Object self, Object formatSpec) {
* object to format and output. If {@code field_name} is not
* {@code None}, it is looked up, formatted with {@code format_spec}
* and {@code conversion} and then used.
*
*
* @param formatString to parse
* @return an iterator of format {@code tuple}s
*/
Expand All @@ -2745,7 +2748,7 @@ static Object formatter_parser(Object formatString) {

/**
* Implementation of {@code _string.formatter_field_name_split}.
*
*
* @param fieldName to split into components
* @return a tuple of the first field name component and the rest
*/
Expand Down Expand Up @@ -4476,7 +4479,7 @@ public double atof() {
*/
@Deprecated // See _PyUnicode_TransformDecimalAndSpaceToASCII
private String encodeDecimal() {

// XXX This all has a has a Jython 2 smell: bytes/str confusion.
// XXX Also, String and PyUnicode implementations are needed.
// XXX Follow CPython _PyUnicode_TransformDecimalAndSpaceToASCII
Expand Down Expand Up @@ -4910,7 +4913,7 @@ public static PyLong atol(String self, int base) {
* @param value the format string when {@code enclosingIterator} is not null
* @return the formatted string based on the arguments
* @throws TypeError if {@code __repr__} or {@code __str__} conversions returned a non-string.
* @throws Throwable from other errors in
* @throws Throwable from other errors in {@code __repr__} or {@code __str__}
*/
// XXX make this support format(String) too
private String buildFormattedString(Object[] args, String[] keywords,
Expand Down
7 changes: 4 additions & 3 deletions core/src/test/java/org/python/core/CPython38CodeTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ void co_consts() {
@DisplayName("We can execute simple ...")
@ParameterizedTest(name = "{0}.py")
@ValueSource(strings = {"load_store_name", "unary_op", "binary_op", "bool_left_arith",
"bool_right_arith", "tuple_index", "list_index", "call_method_builtin"})
"bool_right_arith", "comparison", "tuple_index", "list_index", "call_method_builtin"})
void executeSimple(String name) {
CPython38Code code = readCode(name);
PyDict globals = new PyDict();
Expand All @@ -140,9 +140,10 @@ void executeSimple(String name) {
* @param name of the Python example
*/
@SuppressWarnings("static-method")
@DisplayName("We can execute branches ...")
@DisplayName("We can execute branches and while loops ...")
@ParameterizedTest(name = "{0}.py")
@ValueSource(strings = {"simple_if", "multi_if"})
@ValueSource(strings = {"simple_if", "multi_if", "simple_loop", "tuple_dot_product",
"list_dot_product"})
void executeBranchAndLoop(String name) {
CPython38Code code = readCode(name);
PyDict globals = new PyDict();
Expand Down
6 changes: 4 additions & 2 deletions core/src/test/java/org/python/core/PyListTest.java
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Copyright (c)2023 Jython Developers.
// Licensed to PSF under a contributor agreement.
package org.python.core;

import static org.junit.jupiter.api.Assertions.assertEquals;
Expand Down Expand Up @@ -159,7 +161,7 @@ private static Arguments sortExample(List<Object> sorted, long seed,

/**
* A toString that limits the array size
*
*
* @param a the array to return as a string
* @param n maximum number of array elements to show
* @return string representation of {@code a}
Expand All @@ -176,7 +178,7 @@ private static String shortString(ArrayList<Object> a, int n) {

/**
* Randomise the order of elements in a list.
*
*
* @param m to randomise
* @param r random generator
*/
Expand Down
55 changes: 55 additions & 0 deletions core/src/test/pythonExample/comparison.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# comparison.py

# Tests of the order comparisons

a = 2
b = 4

lt = a < b
le = a <= b
eq = a == b
ne = a != b
ge = a >= b
gt = a > b


a = 4
b = 2

lt1 = a < b
le1 = a <= b
eq1 = a == b
ne1 = a != b
ge1 = a >= b
gt1 = a > b


a = 2
b = 2

lt2 = a < b
le2 = a <= b
eq2 = a == b
ne2 = a != b
ge2 = a >= b
gt2 = a > b

# Tests of 'in'

t = ("cow", 2, "pig", None, 42.0)
f0 = 1 in t
f1 = "c" in t
t1x = "c" not in t
f2 = 42.1 in t
f3 = (2,) in t
f4 = "c" in t[2]


t0 = 2 in t
t1 = "pig" in t
f1x = "pig" not in t
t2 = None in t
t3 = 42 in t
t4 = "p" in t[2]


17 changes: 17 additions & 0 deletions core/src/test/pythonExample/list_dot_product.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# list_dot_product.py

# Multiply-add of float vectors (without for loops)
# Also, multiplication as repetition.

n = 2

a = [1.2, 3.4, 5.6, 7.8] * (3 * n)
b = (4 * n) * [1.2, 4.5, 7.8]
n = 12 * n # lists are this long

i = 0
sum = 0.0

while i < n:
sum = sum + a[i] * b[i]
i = i + 1
10 changes: 10 additions & 0 deletions core/src/test/pythonExample/simple_loop.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# simple_loop.py

n = 6

# ? n, sum
sum = 0
while n > 0:
sum = sum + n
n = n - 1

25 changes: 25 additions & 0 deletions core/src/test/pythonExample/tuple_dot_product.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# tuple_dot_product.py

# Multiply-add of int and float vectors (without for loops)

a = (2, 3, 4)
b = (3, 4, 6)
n = 3

# ? sum

sum = a[0] * b[0]
i = 1
while i < n:
sum = sum + a[i] * b[i]
i = i + 1

a= (1., 2., 3., 4.)
b = (4., 3., 4., 5.)
n = 4

sum2 = a[0] * b[0]
i = 1
while i < n:
sum2 = sum2 + a[i] * b[i]
i = i + 1