1
1
package ai .timefold .jpyinterpreter .implementors ;
2
2
3
3
import java .lang .reflect .Field ;
4
+ import java .math .BigDecimal ;
4
5
import java .math .BigInteger ;
5
6
import java .util .IdentityHashMap ;
6
7
import java .util .Iterator ;
31
32
import ai .timefold .jpyinterpreter .types .collections .PythonLikeTuple ;
32
33
import ai .timefold .jpyinterpreter .types .errors .TypeError ;
33
34
import ai .timefold .jpyinterpreter .types .numeric .PythonBoolean ;
35
+ import ai .timefold .jpyinterpreter .types .numeric .PythonDecimal ;
34
36
import ai .timefold .jpyinterpreter .types .numeric .PythonFloat ;
35
37
import ai .timefold .jpyinterpreter .types .numeric .PythonInteger ;
36
38
import ai .timefold .jpyinterpreter .types .numeric .PythonNumber ;
@@ -65,76 +67,79 @@ public static PythonLikeObject wrapJavaObject(Object object, Map<Object, PythonL
65
67
return existingObject ;
66
68
}
67
69
68
- if (object instanceof OpaqueJavaReference ) {
69
- return (( OpaqueJavaReference ) object ) .proxy ();
70
+ if (object instanceof OpaqueJavaReference opaqueJavaReference ) {
71
+ return opaqueJavaReference .proxy ();
70
72
}
71
73
72
- if (object instanceof PythonLikeObject ) {
74
+ if (object instanceof PythonLikeObject instance ) {
73
75
// Object already a PythonLikeObject; need to do nothing
74
- return ( PythonLikeObject ) object ;
76
+ return instance ;
75
77
}
76
78
77
79
if (object instanceof Byte || object instanceof Short || object instanceof Integer || object instanceof Long ) {
78
80
return PythonInteger .valueOf (((Number ) object ).longValue ());
79
81
}
80
82
81
- if (object instanceof BigInteger ) {
82
- return PythonInteger .valueOf ((BigInteger ) object );
83
+ if (object instanceof BigInteger integer ) {
84
+ return PythonInteger .valueOf (integer );
85
+ }
86
+
87
+ if (object instanceof BigDecimal decimal ) {
88
+ return new PythonDecimal (decimal );
83
89
}
84
90
85
91
if (object instanceof Float || object instanceof Double ) {
86
92
return PythonFloat .valueOf (((Number ) object ).doubleValue ());
87
93
}
88
94
89
- if (object instanceof Boolean ) {
90
- return PythonBoolean .valueOf (( Boolean ) object );
95
+ if (object instanceof Boolean booleanValue ) {
96
+ return PythonBoolean .valueOf (booleanValue );
91
97
}
92
98
93
- if (object instanceof String ) {
94
- return PythonString .valueOf (( String ) object );
99
+ if (object instanceof String string ) {
100
+ return PythonString .valueOf (string );
95
101
}
96
102
97
- if (object instanceof Iterator ) {
98
- return new DelegatePythonIterator <>(( Iterator ) object );
103
+ if (object instanceof Iterator iterator ) {
104
+ return new DelegatePythonIterator <>(iterator );
99
105
}
100
106
101
- if (object instanceof List ) {
107
+ if (object instanceof List list ) {
102
108
PythonLikeList out = new PythonLikeList ();
103
109
createdObjectMap .put (object , out );
104
- for (Object item : ( List ) object ) {
110
+ for (Object item : list ) {
105
111
out .add (wrapJavaObject (item ));
106
112
}
107
113
return out ;
108
114
}
109
115
110
- if (object instanceof Set ) {
116
+ if (object instanceof Set set ) {
111
117
PythonLikeSet out = new PythonLikeSet ();
112
118
createdObjectMap .put (object , out );
113
- for (Object item : ( Set ) object ) {
119
+ for (Object item : set ) {
114
120
out .add (wrapJavaObject (item ));
115
121
}
116
122
return out ;
117
123
}
118
124
119
- if (object instanceof Map ) {
125
+ if (object instanceof Map map ) {
120
126
PythonLikeDict out = new PythonLikeDict ();
121
127
createdObjectMap .put (object , out );
122
- Set <Map .Entry <?, ?>> entrySet = (( Map ) object ) .entrySet ();
128
+ Set <Map .Entry <?, ?>> entrySet = map .entrySet ();
123
129
for (Map .Entry <?, ?> entry : entrySet ) {
124
130
out .put (wrapJavaObject (entry .getKey ()), wrapJavaObject (entry .getValue ()));
125
131
}
126
132
return out ;
127
133
}
128
134
129
- if (object instanceof Class ) {
130
- Class <?> maybeFunctionClass = (Class <?>) object ;
135
+ if (object instanceof Class maybeFunctionClass ) {
131
136
if (Set .of (maybeFunctionClass .getInterfaces ()).contains (PythonLikeFunction .class )) {
132
137
return new PythonCode ((Class <? extends PythonLikeFunction >) maybeFunctionClass );
133
138
}
134
139
}
135
140
136
- if (object instanceof OpaquePythonReference ) {
137
- return new PythonObjectWrapper (( OpaquePythonReference ) object );
141
+ if (object instanceof OpaquePythonReference opaquePythonReference ) {
142
+ return new PythonObjectWrapper (opaquePythonReference );
138
143
}
139
144
140
145
// Default: return a JavaObjectWrapper
@@ -161,6 +166,10 @@ public static PythonLikeType getPythonLikeType(Class<?> javaClass) {
161
166
return BuiltinTypes .INT_TYPE ;
162
167
}
163
168
169
+ if (BigDecimal .class .equals (javaClass ) || PythonDecimal .class .equals (javaClass )) {
170
+ return BuiltinTypes .DECIMAL_TYPE ;
171
+ }
172
+
164
173
if (float .class .equals (javaClass ) || double .class .equals (javaClass ) ||
165
174
Float .class .equals (javaClass ) || Double .class .equals (javaClass ) ||
166
175
PythonFloat .class .equals (javaClass )) {
@@ -273,7 +282,7 @@ public static <T> T convertPythonObjectToJavaType(Class<? extends T> type, Pytho
273
282
PythonNumber pythonNumber = (PythonNumber ) object ;
274
283
Number value = pythonNumber .getValue ();
275
284
276
- if (type .equals (BigInteger .class )) {
285
+ if (type .equals (BigInteger .class ) || type . equals ( BigDecimal . class ) ) {
277
286
return (T ) value ;
278
287
}
279
288
@@ -355,13 +364,23 @@ public static void returnValue(MethodVisitor methodVisitor, MethodDescriptor met
355
364
Type .INT_TYPE .equals (returnAsmType ) ||
356
365
Type .LONG_TYPE .equals (returnAsmType ) ||
357
366
Type .FLOAT_TYPE .equals (returnAsmType ) ||
358
- Type .DOUBLE_TYPE .equals (returnAsmType )) {
367
+ Type .DOUBLE_TYPE .equals (returnAsmType ) ||
368
+ Type .getType (BigInteger .class ).equals (returnAsmType ) ||
369
+ Type .getType (BigDecimal .class ).equals (returnAsmType )) {
359
370
methodVisitor .visitTypeInsn (Opcodes .CHECKCAST , Type .getInternalName (PythonNumber .class ));
360
371
methodVisitor .visitMethodInsn (Opcodes .INVOKEINTERFACE ,
361
372
Type .getInternalName (PythonNumber .class ),
362
373
"getValue" ,
363
374
Type .getMethodDescriptor (Type .getType (Number .class )),
364
375
true );
376
+
377
+ if (Type .getType (BigInteger .class ).equals (returnAsmType ) ||
378
+ Type .getType (BigDecimal .class ).equals (returnAsmType )) {
379
+ methodVisitor .visitTypeInsn (Opcodes .CHECKCAST , returnAsmType .getInternalName ());
380
+ methodVisitor .visitInsn (Opcodes .ARETURN );
381
+ return ;
382
+ }
383
+
365
384
String wrapperClassName = null ;
366
385
String methodName = null ;
367
386
String methodDescriptor = null ;
0 commit comments