Skip to content

Commit 91167ca

Browse files
committed
Rework indy support
- Fully support CONDY - Move them to their own package Signed-off-by: TheSilkMiner <thesilkminer@outlook.com>
1 parent 89eeef0 commit 91167ca

File tree

8 files changed

+625
-476
lines changed

8 files changed

+625
-476
lines changed

JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaIndyHelper.java

Lines changed: 0 additions & 468 deletions
This file was deleted.

JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaWriter.java

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import org.openzen.zenscript.codemodel.HighLevelDefinition;
88
import org.openzen.zenscript.codemodel.statement.VariableID;
99
import org.openzen.zenscript.javabytecode.JavaLocalVariableInfo;
10+
import org.openzen.zenscript.javabytecode.compiler.indy.JavaCondy;
11+
import org.openzen.zenscript.javabytecode.compiler.indy.JavaIndy;
1012
import org.openzen.zenscript.javashared.JavaClass;
1113
import org.openzen.zenscript.javashared.compiling.JavaCompilingMethod;
1214
import org.openzen.zenscript.javashared.JavaNativeField;
@@ -294,7 +296,11 @@ public void ldc(Object value) {
294296
if (debug)
295297
logger.debug("ldc " + value);
296298

297-
visitor.visitLdcInsn(value);
299+
if (value instanceof JavaCondy) {
300+
((JavaCondy) value).visit(visitor::visitLdcInsn);
301+
} else {
302+
visitor.visitLdcInsn(value);
303+
}
298304
}
299305

300306
public void constant(byte value) {
@@ -383,6 +389,14 @@ public void constant(JavaClass cls) {
383389
this.ldc(Type.getObjectType(cls.internalName));
384390
}
385391

392+
public void constant(UnaryOperator<JavaCondy.Builder> valueBuilder) {
393+
this.constant(JavaCondy.build(valueBuilder));
394+
}
395+
396+
public void constant(JavaCondy value) {
397+
value.visit(this::ldc);
398+
}
399+
386400
public void pop() {
387401
if (debug)
388402
logger.debug("pop");
@@ -1111,15 +1125,15 @@ public void invokeInterface(JavaNativeMethod method) {
11111125
visitor.visitMethodInsn(INVOKEINTERFACE, method.cls.internalName, method.name, method.descriptor, true);
11121126
}
11131127

1114-
public void invokeDynamic(UnaryOperator<JavaIndyHelper.Builder> indyDataBuilder) {
1115-
invokeDynamic(indyDataBuilder.apply(JavaIndyHelper.builder()).build());
1128+
public void invokeDynamic(UnaryOperator<JavaIndy.Builder> indyBuilder) {
1129+
invokeDynamic(JavaIndy.build(indyBuilder));
11161130
}
11171131

1118-
public void invokeDynamic(JavaIndyHelper indyData) {
1132+
public void invokeDynamic(JavaIndy indy) {
11191133
if (debug)
1120-
logger.debug("invokeDynamic " + indyData);
1134+
logger.debug("invokeDynamic " + indy);
11211135

1122-
indyData.visit(visitor::visitInvokeDynamicInsn);
1136+
indy.visit(visitor::visitInvokeDynamicInsn);
11231137
}
11241138

11251139
public void newObject(String internalName) {
Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
package org.openzen.zenscript.javabytecode.compiler.indy;
2+
3+
import org.objectweb.asm.Type;
4+
import org.openzen.zenscript.javashared.JavaClass;
5+
import org.openzen.zenscript.javashared.JavaModifiers;
6+
import org.openzen.zenscript.javashared.JavaNativeMethod;
7+
import org.openzen.zenscript.javashared.compiling.JavaCompilingMethod;
8+
9+
import java.util.ArrayList;
10+
import java.util.List;
11+
import java.util.Objects;
12+
import java.util.function.UnaryOperator;
13+
import java.util.stream.Stream;
14+
15+
public final class BsmData {
16+
public enum InvokeType {
17+
STATIC,
18+
VIRTUAL,
19+
SPECIAL,
20+
INTERFACE
21+
}
22+
23+
public static final class Builder {
24+
// TODO("Think about this")
25+
private static final boolean ALLOW_RELAX = false;
26+
27+
private final IndyTarget indyTarget;
28+
private final Constructor constructor;
29+
private final List<Object> args;
30+
31+
private JavaNativeMethod bsmMethod;
32+
private JavaClass owner;
33+
private String name;
34+
35+
private Builder(final IndyTarget indyTarget, final Constructor constructor) {
36+
this.indyTarget = indyTarget;
37+
this.constructor = constructor;
38+
this.args = new ArrayList<>();
39+
this.bsmMethod = null;
40+
this.owner = null;
41+
this.name = null;
42+
}
43+
44+
static Builder of(final IndyTarget indyTarget, final Constructor constructor) {
45+
return new Builder(indyTarget, constructor);
46+
}
47+
48+
public Builder method(final JavaNativeMethod bsmMethod) {
49+
Objects.requireNonNull(bsmMethod, "BSM Method specified cannot be null");
50+
if (!IndyHelpers.isValidBsm(bsmMethod, this.indyTarget, ALLOW_RELAX)) {
51+
throw new IllegalArgumentException("Provided BSM must be a valid BSM");
52+
}
53+
if (this.owner != null) {
54+
throw new IllegalStateException("BSM has already been specified in 'autodetect' mode");
55+
}
56+
if (this.bsmMethod != null) {
57+
throw new IllegalStateException("BSM has already been specified");
58+
}
59+
this.bsmMethod = bsmMethod;
60+
return this;
61+
}
62+
63+
public Builder method(final JavaClass owner, final String name) {
64+
Objects.requireNonNull(owner, "BSM owner cannot be null");
65+
Objects.requireNonNull(name, "BSM name cannot be null");
66+
if (this.bsmMethod != null) {
67+
throw new IllegalStateException("BSM has already been specified in 'fixed' mode");
68+
}
69+
if (this.owner != null) {
70+
throw new IllegalStateException("BSM has already been specified");
71+
}
72+
this.owner = owner;
73+
this.name = name;
74+
return this;
75+
}
76+
77+
public Builder arg(final int argument) {
78+
return this.arg((Object) argument);
79+
}
80+
81+
public Builder arg(final float argument) {
82+
return this.arg((Object) argument);
83+
}
84+
85+
public Builder arg(final long argument) {
86+
return this.arg((Object) argument);
87+
}
88+
89+
public Builder arg(final double argument) {
90+
return this.arg((Object) argument);
91+
}
92+
93+
public Builder arg(final String argument) {
94+
return this.arg((Object) argument);
95+
}
96+
97+
public Builder arg(final JavaClass clazz) {
98+
return this.arg((Object) clazz);
99+
}
100+
101+
public Builder arg(final Class<?> clazz) {
102+
return this.arg((Object) clazz);
103+
}
104+
105+
public Builder arg(final Type type) {
106+
return this.arg((Object) type);
107+
}
108+
109+
public Builder arg(final Type returnType, final Type... arguments) {
110+
return this.arg(Type.getMethodType(returnType, arguments));
111+
}
112+
113+
public Builder arg(final String returnType, final String... arguments) {
114+
return this.arg(Type.getType(returnType), Stream.of(arguments).map(Type::getType).toArray(Type[]::new));
115+
}
116+
117+
public Builder arg(final JavaCompilingMethod method) {
118+
return this.arg((Object) method);
119+
}
120+
121+
public Builder arg(final JavaNativeMethod method) {
122+
return this.arg((Object) method);
123+
}
124+
125+
public Builder arg(final InvokeType invokeType, final JavaClass owner, final String name, final Type desc) {
126+
switch (invokeType) {
127+
case STATIC: return this.arg(JavaNativeMethod.getStatic(owner, name, desc.getDescriptor(), JavaModifiers.STATIC));
128+
case SPECIAL: {
129+
if (IndyHelpers.CONSTRUCTOR_NAME.equals(name)) {
130+
return this.arg(JavaNativeMethod.getConstructor(owner, desc.getDescriptor(), 0));
131+
} else {
132+
return this.arg(JavaNativeMethod.getVirtual(owner, name, desc.getDescriptor(), 0));
133+
}
134+
}
135+
case VIRTUAL: return this.arg(JavaNativeMethod.getVirtual(owner, name, desc.getDescriptor(), 0));
136+
case INTERFACE: return this.arg(JavaNativeMethod.getInterface(owner, name, desc.getDescriptor()));
137+
}
138+
throw new IllegalArgumentException(String.valueOf(invokeType));
139+
}
140+
141+
@SuppressWarnings("SpellCheckingInspection")
142+
public Builder arg(final UnaryOperator<JavaCondy.Builder> condyBuilder) {
143+
return this.arg(condyBuilder.apply(JavaCondy.builder()).build());
144+
}
145+
146+
@SuppressWarnings("SpellCheckingInspection")
147+
public Builder arg(final JavaCondy condy) {
148+
return this.arg((Object) condy);
149+
}
150+
151+
private Builder arg(final Object argument) {
152+
Objects.requireNonNull(argument, "Null arguments are not supported when invoking BSMs");
153+
this.args.add(argument);
154+
return this;
155+
}
156+
157+
BsmData build() {
158+
if (this.bsmMethod == null && this.owner == null) {
159+
throw new IllegalStateException("BSM has not been specified");
160+
}
161+
final JavaNativeMethod method = this.findBsmMethod();
162+
return this.constructor.of(method, this.args);
163+
}
164+
165+
private JavaNativeMethod findBsmMethod() {
166+
if (this.bsmMethod != null) {
167+
return this.bsmMethod;
168+
}
169+
170+
return JavaNativeMethod.getStatic(this.owner, this.name, IndyHelpers.autoFillBsmDesc(this.indyTarget, this.args), JavaModifiers.PUBLIC | JavaModifiers.STATIC);
171+
}
172+
}
173+
174+
@FunctionalInterface
175+
interface Constructor {
176+
BsmData of(final JavaNativeMethod bsm, final List<?> args);
177+
}
178+
179+
private final JavaNativeMethod bsm;
180+
private final List<?> args;
181+
182+
private BsmData(final JavaNativeMethod bsm, final List<?> args) {
183+
this.bsm = bsm;
184+
this.args = args;
185+
}
186+
187+
static BsmData.Builder builder(final IndyTarget target) {
188+
return Builder.of(target, BsmData::new);
189+
}
190+
191+
JavaNativeMethod bsm() {
192+
return this.bsm;
193+
}
194+
195+
List<?> args() {
196+
return this.args;
197+
}
198+
199+
@Override
200+
public String toString() {
201+
return String.format("%s.%s%s, invoked with %s", this.bsm.cls.internalName, this.bsm.name, this.bsm.descriptor, this.args);
202+
}
203+
}

0 commit comments

Comments
 (0)