-
Notifications
You must be signed in to change notification settings - Fork 228
Expand file tree
/
Copy pathTypeExposer.java
More file actions
156 lines (137 loc) · 4.82 KB
/
TypeExposer.java
File metadata and controls
156 lines (137 loc) · 4.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package org.python.expose.generate;
import java.util.Collection;
import java.util.Set;
import org.python.core.BytecodeLoader;
import org.python.expose.BaseTypeBuilder;
import org.python.expose.ExposedType;
import org.python.expose.TypeBuilder;
import org.objectweb.asm.Type;
import org.python.util.Generic;
/**
* Generates a subclass of TypeBuilder to expose a class with the {@link ExposedType} annotation as
* a builtin Python type.
*/
public class TypeExposer extends Exposer {
private Type baseType;
private boolean isBaseType;
private String doc;
private Type onType;
private String name;
private Collection<MethodExposer> methods;
private Collection<DescriptorExposer> descriptors;
private int numNames;
private Exposer ne;
public TypeExposer(Type onType,
Type baseType,
boolean isBaseType,
String doc,
String name,
Collection<MethodExposer> methods,
Collection<DescriptorExposer> descriptors,
Exposer ne) {
super(BaseTypeBuilder.class, makeGeneratedName(onType));
this.baseType = baseType;
this.isBaseType = isBaseType;
this.doc = doc;
this.onType = onType;
this.name = name;
this.methods = methods;
this.descriptors = descriptors;
Set<String> names = Generic.set();
for(DescriptorExposer exposer : descriptors) {
if(!names.add(exposer.getName())) {
throwDupe(exposer.getName());
}
}
for(MethodExposer method : methods) {
String[] methNames = method.getNames();
for(String methName : methNames) {
if(!names.add(methName)) {
throwDupe(methName);
}
}
numNames += methNames.length;
}
this.ne = ne;
}
private void throwDupe(String exposedName) {
throw new InvalidExposingException("Only one item may be exposed on a type with a given name[name="
+ exposedName + ", class=" + onType.getClassName() + "]");
}
public static String makeGeneratedName(Type onType) {
return onType.getClassName() + "$PyExposer";
}
public TypeBuilder makeBuilder() {
BytecodeLoader.Loader l = new BytecodeLoader.Loader();
if(ne != null) {
ne.load(l);
}
for(DescriptorExposer de : descriptors) {
de.load(l);
}
for(MethodExposer me : methods) {
me.load(l);
}
Class<?> descriptor = load(l);
try {
return (TypeBuilder)descriptor.getDeclaredConstructor().newInstance();
} catch(Exception e) {
// If we're unable to create the generated class, the process is
// definitely ill, but that shouldn't be the case most of the time
// so make this a runtime exception
throw new RuntimeException("Unable to create generated builder", e);
}
}
public String getName() {
return name;
}
protected void generate() {
startConstructor();
mv.visitVarInsn(ALOAD, 0);
mv.visitLdcInsn(getName());
mv.visitLdcInsn(onType);
mv.visitLdcInsn(baseType);
mv.visitLdcInsn(isBaseType);
if (doc == null) {
mv.visitInsn(ACONST_NULL);
} else {
mv.visitLdcInsn(doc);
}
mv.visitLdcInsn(numNames);
mv.visitTypeInsn(ANEWARRAY, BUILTIN_METHOD.getInternalName());
mv.visitVarInsn(ASTORE, 1);
int i = 0;
for(MethodExposer exposer : methods) {
for(final String name : exposer.getNames()) {
mv.visitVarInsn(ALOAD, 1);
mv.visitLdcInsn(i++);
instantiate(exposer.getGeneratedType(), new Instantiator(STRING) {
public void pushArgs() {
mv.visitLdcInsn(name);
}
});
mv.visitInsn(AASTORE);
}
}
mv.visitVarInsn(ALOAD, 1);
mv.visitLdcInsn(descriptors.size());
mv.visitTypeInsn(ANEWARRAY, DATA_DESCR.getInternalName());
mv.visitVarInsn(ASTORE, 2);
i = 0;
for(DescriptorExposer desc : descriptors) {
mv.visitVarInsn(ALOAD, 2);
mv.visitLdcInsn(i++);
instantiate(desc.getGeneratedType());
mv.visitInsn(AASTORE);
}
mv.visitVarInsn(ALOAD, 2);
if(ne != null) {
instantiate(ne.getGeneratedType());
} else {
mv.visitInsn(ACONST_NULL);
}
superConstructor(STRING, CLASS, CLASS, BOOLEAN, STRING, ABUILTIN_METHOD, ADATA_DESCR,
PYNEWWRAPPER);
endConstructor();
}
}