1
1
package dev .ultreon .pythonc ;
2
2
3
+ import org .jetbrains .annotations .NotNull ;
4
+ import org .jetbrains .annotations .Nullable ;
3
5
import org .objectweb .asm .MethodVisitor ;
4
6
import org .objectweb .asm .Type ;
5
7
8
+ import java .lang .reflect .Constructor ;
9
+ import java .lang .reflect .Field ;
10
+ import java .lang .reflect .Method ;
6
11
import java .lang .reflect .Modifier ;
7
- import java .util .Objects ;
12
+ import java .util .* ;
8
13
9
14
final class JClass implements JvmClass {
10
15
private final String className ;
11
16
private final Type asmType ;
12
17
private final Class <?> type ;
18
+ private String alias ;
19
+ private final HashMap <String , JvmField > fields = new HashMap <>();
20
+ private final Map <String , List <JvmFunction >> functions = new HashMap <>();
13
21
14
- JClass (String className ) {
22
+ JClass (String className , Class <?> type ) {
15
23
this .className = className ;
16
24
this .asmType = Type .getObjectType (className .replace ("." , "/" ));
17
- try {
18
- this .type = Class .forName (className .replace ("/" , "." ), false , getClass ().getClassLoader ());
19
- } catch (ClassNotFoundException e ) {
20
- throw new CompilerException ("JVM class not found: " + className );
21
- }
25
+ this .alias = alias ;
26
+ this .type = type ;
22
27
}
23
28
24
29
@ Override
@@ -85,8 +90,120 @@ public boolean isEnum() {
85
90
}
86
91
87
92
@ Override
88
- public boolean doesInherit (Class <?> type ) {
89
- return type .isAssignableFrom (this .type );
93
+ public boolean doesInherit (PythonCompiler compiler , Type type ) {
94
+ JvmClass jvmClass = PythonCompiler .classCache .get (type );
95
+ if (jvmClass instanceof JClass jClass ) {
96
+ return jClass .type .isAssignableFrom (this .type );
97
+ }
98
+ return false ;
99
+ }
100
+
101
+ @ Override
102
+ public JvmFunction constructor (PythonCompiler compiler , Type [] paramTypes ) {
103
+ Method method ;
104
+ Constructor <?>[] constructors = type .getConstructors ();
105
+ JvmClass [] ourParamTypes = new JvmClass [paramTypes .length ];
106
+ for (int i = 0 , paramTypesLength = paramTypes .length ; i < paramTypesLength ; i ++) {
107
+ Type paramType = paramTypes [i ];
108
+ if (!(PythonCompiler .classCache .load (compiler , paramType )))
109
+ throw new CompilerException ("Class '" + paramType .getClassName () + "' not found (" + compiler .getLocation (this ) + ")" );
110
+ ourParamTypes [i ] = PythonCompiler .classCache .get (paramType );
111
+ }
112
+
113
+ Constructor <?> theConstructor ;
114
+ methodLoop :
115
+ for (Constructor <?> constructor1 : constructors ) {
116
+ @ NotNull Class <?>[] parameterTypes = constructor1 .getParameterTypes ();
117
+ for (int i = 0 , parameterTypesLength = parameterTypes .length ; i < parameterTypesLength ; i ++) {
118
+ Class <?> theParamType = parameterTypes [i ];
119
+ if (!(PythonCompiler .classCache .load (compiler , Type .getType (theParamType ))))
120
+ throw new CompilerException ("Class '" + theParamType .getName () + "' not found (" + compiler .getLocation (this ) + ")" );
121
+
122
+ if (i > ourParamTypes .length - 1 ) {
123
+ continue methodLoop ;
124
+ }
125
+ if (!ourParamTypes [i ].doesInherit (compiler , Type .getType (theParamType ))) {
126
+ continue methodLoop ;
127
+ }
128
+ }
129
+
130
+ if (ourParamTypes .length != parameterTypes .length ) {
131
+ continue ;
132
+ }
133
+
134
+ JConstructor jFunction = new JConstructor ("__init__" , constructor1 , 0 , 0 );
135
+ this .functions .computeIfAbsent ("__init__" , k -> new ArrayList <>()).add (jFunction );
136
+ return jFunction ;
137
+ }
138
+
139
+ throw new CompilerException ("Constructor not found (" + compiler .getLocation (this ) + ")" );
140
+ }
141
+
142
+ @ Override
143
+ public @ Nullable JvmFunction function (PythonCompiler compiler , String name , Type [] paramTypes ) {
144
+ Method method ;
145
+ Method [] methodsByName = ClassUtils .getMethodsByName (type , name );
146
+ JvmClass [] ourParamTypes = new JvmClass [paramTypes .length ];
147
+ for (int i = 0 , paramTypesLength = paramTypes .length ; i < paramTypesLength ; i ++) {
148
+ Type paramType = paramTypes [i ];
149
+ if (!(PythonCompiler .classCache .load (compiler , paramType )))
150
+ throw new CompilerException ("Class '" + paramType .getClassName () + "' not found (" + compiler .getLocation (this ) + ")" );
151
+ ourParamTypes [i ] = PythonCompiler .classCache .get (paramType );
152
+ }
153
+
154
+ Method theMethod ;
155
+ methodLoop :
156
+ for (Method method1 : methodsByName ) {
157
+ @ NotNull Class <?>[] parameterTypes = method1 .getParameterTypes ();
158
+ for (int i = 0 , parameterTypesLength = parameterTypes .length ; i < parameterTypesLength ; i ++) {
159
+ Class <?> theParamType = parameterTypes [i ];
160
+ if (!(PythonCompiler .classCache .load (compiler , Type .getType (theParamType ))))
161
+ throw new CompilerException ("Class '" + theParamType .getName () + "' not found (" + compiler .getLocation (this ) + ")" );
162
+
163
+ if (!ourParamTypes [i ].doesInherit (compiler , Type .getType (theParamType ))) {
164
+ continue methodLoop ;
165
+ }
166
+ }
167
+
168
+ JFunction jFunction = new JFunction (name , method1 , 0 , 0 );
169
+ this .functions .computeIfAbsent (name , k -> new ArrayList <>()).add (jFunction );
170
+ return jFunction ;
171
+ }
172
+
173
+ throw new CompilerException ("Method '" + name + "' not found (" + compiler .getLocation (this ) + ")" );
174
+ }
175
+
176
+ @ Override
177
+ public boolean isPrimitive () {
178
+ return type .isPrimitive ();
179
+ }
180
+
181
+ @ Override
182
+ public @ Nullable JvmField field (PythonCompiler compiler , String name ) {
183
+ Field field ;
184
+ try {
185
+ field = this .type .getField (name );
186
+ } catch (NoSuchFieldException e ) {
187
+ return null ;
188
+ }
189
+ Class <?> type1 = field .getType ();
190
+ if (Modifier .isStatic (field .getModifiers ())) {
191
+ if (type1 .isPrimitive ()) {
192
+ Type asmType = Type .getType (type1 );
193
+ Field finalField = field ;
194
+ return fields .computeIfAbsent (name , k -> new JField (this , finalField , name , asmType ));
195
+ }
196
+ Field finalField = field ;
197
+ return fields .computeIfAbsent (name , k -> new JField (this , finalField , name , Type .getType (type1 )));
198
+ }
199
+ if (type1 .isPrimitive ()) {
200
+ Type asmType = Type .getType (type1 );
201
+ Field finalField1 = field ;
202
+ return fields .computeIfAbsent (name , k -> new JField (this , finalField1 , name , asmType ));
203
+ } else {
204
+ Field finalField2 = field ;
205
+ return fields .computeIfAbsent (name , k -> new JField (this , finalField2 , name , Type .getType (type1 )));
206
+ }
90
207
}
91
208
92
209
public String className () {
@@ -109,7 +226,7 @@ public int hashCode() {
109
226
@ Override
110
227
public String toString () {
111
228
return "JClass[" +
112
- "className=" + className + ']' ;
229
+ "className=" + className + ']' ;
113
230
}
114
231
115
232
}
0 commit comments