diff --git a/.gitignore b/.gitignore
index 8ecf1a2f..1bafd868 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,4 @@ out/
*.xslt
*.xml
+!.run/*.run.xml
diff --git a/.run/tests_gradle.run.xml b/.run/tests_gradle.run.xml
new file mode 100644
index 00000000..c979b2b3
--- /dev/null
+++ b/.run/tests_gradle.run.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+ false
+ true
+ false
+ true
+
+
+
\ No newline at end of file
diff --git a/.run/tests_intellij.run.xml b/.run/tests_intellij.run.xml
new file mode 100644
index 00000000..44a3a741
--- /dev/null
+++ b/.run/tests_intellij.run.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JavaBytecodeCompiler/build.gradle b/JavaBytecodeCompiler/build.gradle
index 730f4ea9..a828caa5 100644
--- a/JavaBytecodeCompiler/build.gradle
+++ b/JavaBytecodeCompiler/build.gradle
@@ -8,4 +8,5 @@ dependencies {
api libs.asm.commons
api project(':CodeModel')
api project(':JavaShared')
+ implementation project(':JavaRuntime')
}
diff --git a/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/JavaMangler.java b/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/JavaMangler.java
index fe3edbc7..b3976363 100644
--- a/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/JavaMangler.java
+++ b/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/JavaMangler.java
@@ -53,7 +53,7 @@ public String mangleScriptName(final SourceFile sourceFile) {
}
public String mangleScriptBodyMethod(final int methodsAmount) {
- return "script-body" + (methodsAmount == 0? "" : ('-' + Integer.toString(methodsAmount)));
+ return "$body" + (methodsAmount == 0? "" : ('$' + Integer.toString(methodsAmount)));
}
public String mangleSourceFileName(final HighLevelDefinition definition) {
@@ -116,40 +116,41 @@ public int hashCode() {
return builder.toString();
}
- public String mangleGeneratedLambdaName(final String interfaceName) {
+ public String mangleLambdaMethod(final String parentMethodName, final String interfaceName) {
final class LambdaId {
- final String target;
+ final String interfaceName;
+ final String method;
- LambdaId(final String target) {
- this.target = target;
+ LambdaId(final String interfaceName, final String method) {
+ this.interfaceName = interfaceName;
+ this.method = method;
}
@Override
public boolean equals(final Object o) {
- return this == o || o instanceof LambdaId && this.target.equals(((LambdaId) o).target);
+ return this == o || o instanceof LambdaId && this.interfaceName.equals(((LambdaId) o).interfaceName) && this.method.equals(((LambdaId) o).method);
}
@Override
public int hashCode() {
- return 17 * this.target.hashCode();
+ return 17 * (this.interfaceName.hashCode() + 31 * this.method.hashCode());
}
}
- final String interfaceTarget = interfaceName.replace('/', '_').replace('.', '_');
- // TODO("Rework package structure")
- return "zsynthetic/$Lambda$" + interfaceTarget + '$' + this.mangleCounters.get(new LambdaId(interfaceTarget));
- }
-
- public String mangleGeneratedLambdaName(final FunctionHeader header) {
- return this.mangleGeneratedLambdaName("$Generated" + EXP_TAR_MANGLE_FUNCTION_ID + this.encodeLengthNameFormat(this.mangleFunctionHeader(header)));
- }
-
- public String mangleCapturedParameter(final int parameterId, final boolean isThis) {
- if (isThis) {
- return "$this";
+ final String sanitizedMethodName;
+ if (parentMethodName == null) {
+ sanitizedMethodName = "$null";
+ } else if ("".equals(parentMethodName) || "".equals(parentMethodName)) {
+ sanitizedMethodName = "$_" + parentMethodName.substring(1, parentMethodName.length() - 1) + '_';
} else {
- return "$" + parameterId;
+ sanitizedMethodName = parentMethodName;
}
+ final String interfaceTarget = interfaceName.replace('/', '.');
+ final int lastDot = interfaceTarget.lastIndexOf('.');
+ final String canonicalInterfaceTarget = lastDot == -1 ? interfaceTarget : interfaceTarget.substring(lastDot + 1);
+ final LambdaId id = new LambdaId(canonicalInterfaceTarget, sanitizedMethodName);
+
+ return "$lambda$" + sanitizedMethodName + '$' + canonicalInterfaceTarget + '$' + this.mangleCounters.get(id);
}
private String mangleScriptName(final String rawName) {
diff --git a/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaExpressionVisitor.java b/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaExpressionVisitor.java
index 6e89710d..d13320cc 100644
--- a/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaExpressionVisitor.java
+++ b/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaExpressionVisitor.java
@@ -1,17 +1,13 @@
package org.openzen.zenscript.javabytecode.compiler;
-import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
-import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
-import org.openzen.zencode.shared.CodePosition;
import org.openzen.zenscript.codemodel.CompareType;
import org.openzen.zenscript.codemodel.FunctionHeader;
import org.openzen.zenscript.codemodel.OperatorType;
import org.openzen.zenscript.codemodel.definition.ExpansionDefinition;
import org.openzen.zenscript.codemodel.expression.captured.CapturedExpression;
import org.openzen.zenscript.codemodel.expression.captured.CapturedExpressionVisitor;
-import org.openzen.zenscript.codemodel.expression.captured.CapturedThisExpression;
import org.openzen.zenscript.codemodel.expression.modifiable.ModifiableExpression;
import org.openzen.zenscript.codemodel.identifiers.MethodID;
import org.openzen.zenscript.codemodel.identifiers.ModuleSymbol;
@@ -23,15 +19,12 @@
import org.openzen.zenscript.javabytecode.JavaLocalVariableInfo;
import org.openzen.zenscript.javabytecode.JavaMangler;
import org.openzen.zenscript.javabytecode.compiler.JavaModificationExpressionVisitor.PushOption;
-import org.openzen.zenscript.javabytecode.compiler.capturing.*;
-import org.openzen.zenscript.javabytecode.compiler.definitions.JavaMemberVisitor;
+import org.openzen.zenscript.javabytecode.compiler.lambda.LambdaIndyCompiler;
+import org.openzen.zenscript.javabytecode.compiler.lambda.capturing.JavaInvalidCapturedExpressionVisitor;
import org.openzen.zenscript.javashared.*;
-import org.openzen.zenscript.javashared.compiling.JavaCompilingMethod;
import org.openzen.zenscript.javashared.expressions.JavaFunctionInterfaceCastExpression;
import org.openzen.zenscript.javashared.types.JavaFunctionalInterfaceTypeID;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
import java.util.*;
import static org.openzen.zenscript.javabytecode.compiler.JavaMethodBytecodeCompiler.OBJECT_HASHCODE;
@@ -51,6 +44,7 @@ public class JavaExpressionVisitor implements ExpressionVisitor {
private final JavaUnboxingTypeVisitor optionalUnwrappingTypeVisitor;
private final JavaFieldBytecodeCompiler fieldCompiler;
public final JavaMethodBytecodeCompiler methodCompiler;
+ private final LambdaIndyCompiler lambdaIndyCompiler;
private final CapturedExpressionVisitor capturedExpressionVisitor;
public JavaExpressionVisitor(JavaBytecodeContext context, JavaCompiledModule module, JavaWriter javaWriter, JavaMangler javaMangler) {
@@ -68,6 +62,7 @@ public JavaExpressionVisitor(JavaBytecodeContext context, JavaCompiledModule mod
optionalUnwrappingTypeVisitor = JavaUnboxingTypeVisitor.forOptionalUnwrapping(javaWriter);
fieldCompiler = new JavaFieldBytecodeCompiler(javaWriter, this, true);
methodCompiler = new JavaMethodBytecodeCompiler(javaWriter, this, context, module);
+ this.lambdaIndyCompiler = LambdaIndyCompiler.of(this.javaWriter, this.javaMangler, this.context, this.module, this);
this.capturedExpressionVisitor = capturedExpressionVisitor;
}
@@ -474,113 +469,26 @@ public Void visitFunction(FunctionExpression expression) {
return null;
}*/
- final String[] interfaces;
- FunctionHeader header = expression.original == null ? expression.header : expression.original;
-
+ final String interfaceName;
if (expression.type instanceof JavaFunctionalInterfaceTypeID) {
//Let's implement the functional Interface instead
JavaFunctionalInterfaceTypeID type = (JavaFunctionalInterfaceTypeID) expression.type;
- final Method functionalInterfaceMethod = type.functionalInterfaceMethod;
-
//Should be the same, should it not?
- interfaces = new String[]{Type.getInternalName(functionalInterfaceMethod.getDeclaringClass())};
+ interfaceName = Type.getInternalName(type.functionalInterfaceMethod.getDeclaringClass());
} else {
//Normal way, no casting to functional interface
- interfaces = new String[]{context.getInternalName(new FunctionTypeID(header))};
- }
-
- final JavaNativeMethod methodInfo;
- final String className = this.javaMangler.mangleGeneratedLambdaName(interfaces[0]);
- {
- final JavaNativeMethod m = context.getFunctionalInterface(expression.original == null ? expression.type : new FunctionTypeID(expression.original));
- methodInfo = m.withModifiers(m.modifiers & ~JavaModifiers.ABSTRACT);
+ FunctionHeader header = expression.original == null ? expression.header : expression.original;
+ interfaceName = context.getInternalName(new FunctionTypeID(header));
}
- final ClassWriter lambdaCW = new JavaClassWriter(ClassWriter.COMPUTE_FRAMES);
- JavaClass lambdaClass = JavaClass.fromInternalName(className, JavaClass.Kind.CLASS);
- lambdaCW.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, className, null, "java/lang/Object", interfaces);
-
- JavaCompilingMethod actualCompiling = JavaMemberVisitor.compileBridgeableMethod(
- context,
- expression.position,
- lambdaCW,
- lambdaClass,
- methodInfo,
- expression.header,
- null
- );
- javaWriter.newObject(className);
- javaWriter.dup();
-
- // ToDo: Is this fine or do we need the actual signature here?
- // To check: write a test where the ctor desc and signature would differ and make sure the program compiles/executes
- final String constructorDescriptorAndSignature = calcFunctionDescriptor(expression.closure);
- JavaNativeMethod constructor = JavaNativeMethod.getConstructor(lambdaClass, constructorDescriptorAndSignature, Opcodes.ACC_PUBLIC);
- JavaCompilingMethod constructorCompiling = new JavaCompilingMethod(constructor, constructorDescriptorAndSignature);
- final JavaWriter constructorWriter = new JavaWriter(context.logger, expression.position, lambdaCW, constructorCompiling, null);
- constructorWriter.start();
- constructorWriter.loadObject(0);
- constructorWriter.dup();
- constructorWriter.invokeSpecial(Object.class, "", "()V");
-
- int i = 0;
- for (CapturedExpression capture : expression.closure.captures) {
- constructorWriter.dup();
- Type type = context.getType(capture.type);
- i++;
- String name = this.javaMangler.mangleCapturedParameter(i, capture instanceof CapturedThisExpression);
- lambdaCW.visitField(Opcodes.ACC_FINAL | Opcodes.ACC_PRIVATE, name, type.getDescriptor(), null, null).visitEnd();
-
- capture.accept(new JavaCapturedExpressionVisitorToPutCapturesOnTheStackBeforeCallingTheCtor(this));
-
- constructorWriter.load(type, i);
- constructorWriter.putField(className, name, type.getDescriptor());
- }
-
- constructorWriter.pop();
-
- javaWriter.invokeSpecial(className, "", constructorDescriptorAndSignature);
-
- constructorWriter.ret();
- constructorWriter.end();
-
- JavaWriter functionWriter = new JavaWriter(context.logger, expression.position, lambdaCW, actualCompiling, null);
- functionWriter.clazzVisitor.visitSource(expression.position.getFilename(), null);
- functionWriter.start();
- JavaExpressionVisitor withCapturedExpressionVisitor = new JavaExpressionVisitor(
- context,
- module,
- functionWriter,
- javaMangler,
- new JavaCapturedExpressionVisitorToAccessCapturesInsideTheLambda(
- context,
- functionWriter,
- javaMangler,
- className,
- expression
- )
- );
- expression.body.accept(new JavaStatementVisitor(context, withCapturedExpressionVisitor, javaMangler));
+ final JavaNativeMethod functionalMethod = context.getFunctionalInterface(expression.original == null ? expression.type : new FunctionTypeID(expression.original));
+ final JavaNativeMethod methodInfo = functionalMethod.withModifiers(functionalMethod.modifiers & ~JavaModifiers.ABSTRACT);
- functionWriter.ret();
- functionWriter.end();
-
- lambdaCW.visitEnd();
-
- context.register(className, lambdaCW.toByteArray());
+ this.lambdaIndyCompiler.compileFunctionExpressionViaIndy(expression, interfaceName, methodInfo);
return null;
}
- private String calcFunctionDescriptor(LambdaClosure closure) {
- StringJoiner joiner = new StringJoiner("", "(", ")V");
- for (CapturedExpression capture : closure.captures) {
- String descriptor = context.getDescriptor(capture.type);
- joiner.add(descriptor);
- }
- return joiner.toString();
- }
-
@Override
public Void visitGetField(GetFieldExpression expression) {
JavaField field = context.getJavaField(expression.field);
@@ -956,16 +864,17 @@ private void modify(ModifiableExpression source, Runnable modification, PushOpti
@Override
public Void visitPlatformSpecific(Expression expression) {
- if (expression instanceof JavaFunctionInterfaceCastExpression) {
- JavaFunctionInterfaceCastExpression jficExpression = (JavaFunctionInterfaceCastExpression) expression;
- if (jficExpression.value.type instanceof JavaFunctionalInterfaceTypeID) {
- jficExpression.value.accept(this);
- } else {
- visitFunctionalInterfaceWrapping(jficExpression);
- }
- } else {
- throw new AssertionError("Unrecognized platform expression: " + expression);
+ if (!(expression instanceof JavaFunctionInterfaceCastExpression)) {
+ throw new AssertionError("Unrecognized platform expression " + expression.getClass().getName() + ": " + expression);
}
+
+ final JavaFunctionInterfaceCastExpression jficExpression = (JavaFunctionInterfaceCastExpression) expression;
+
+ if (jficExpression.value.type instanceof JavaFunctionalInterfaceTypeID) {
+ return jficExpression.value.accept(this);
+ }
+
+ this.lambdaIndyCompiler.convertTypeOfFunctionExpressionViaIndy(jficExpression);
return null;
}
@@ -993,9 +902,11 @@ public void modify(ModificationExpression expression, PushOption pushOption) {
BuiltinMethodSymbol builtin = (BuiltinMethodSymbol) expression.method.method;
modify(expression.target, builtin, pushOption);
} else {
- modify(expression.target, () -> {
- context.getJavaMethod(expression.method).compileVirtualWithTargetOnTopOfStack(methodCompiler, expression.type, CallArguments.EMPTY);
- }, pushOption);
+ modify(
+ expression.target,
+ () -> context.getJavaMethod(expression.method).compileVirtualWithTargetOnTopOfStack(methodCompiler, expression.type, CallArguments.EMPTY),
+ pushOption
+ );
}
}
@@ -1068,141 +979,6 @@ public Void visitSetStaticField(SetStaticFieldExpression expression) {
return null;
}
- private void visitFunctionalInterfaceWrapping(JavaFunctionInterfaceCastExpression expression) {
- final FunctionCastWrapperClass wrapper = generateFunctionCastWrapperClass(
- expression.position,
- (FunctionTypeID) expression.value.type,
- expression.functionType);
-
- expression.value.accept(this);
- javaWriter.newObject(wrapper.className);
- javaWriter.dupX1();
- javaWriter.swap();
- javaWriter.invokeSpecial(wrapper.className, "", wrapper.constructorDesc);
- }
-
- private FunctionCastWrapperClass generateFunctionCastWrapperClass(CodePosition position, FunctionTypeID fromType, FunctionTypeID toType) {
- final String className = this.javaMangler.mangleGeneratedLambdaName(fromType.header);
- final JavaClass classInfo = JavaClass.fromInternalName(className, JavaClass.Kind.CLASS);
-
- String[] interfaces;
- String wrappedFromSignature = context.getDescriptor(fromType);
- String methodDescriptor;
- String methodSignature;
- Type[] methodParameterTypes;
- JavaNativeMethod implementationMethod;
- if (toType instanceof JavaFunctionalInterfaceTypeID) {
- JavaNativeMethod javaMethod = ((JavaFunctionalInterfaceTypeID) toType).method;
- implementationMethod = new JavaNativeMethod(
- classInfo,
- JavaNativeMethod.Kind.COMPILED,
- javaMethod.name,
- true,
- javaMethod.descriptor,
- javaMethod.modifiers & ~JavaModifiers.ABSTRACT,
- javaMethod.genericResult,
- javaMethod.typeParameterArguments);
-
- final Method functionalInterfaceMethod = ((JavaFunctionalInterfaceTypeID) toType).functionalInterfaceMethod;
-
- methodDescriptor = Type.getMethodDescriptor(functionalInterfaceMethod);
- // ToDo: Is signature===descriptor fine here or do we need the actual signature here?
- methodSignature = methodDescriptor;
- interfaces = new String[]{Type.getInternalName(functionalInterfaceMethod.getDeclaringClass())};
-
- final Class>[] methodParameterClasses = functionalInterfaceMethod.getParameterTypes();
- methodParameterTypes = new Type[methodParameterClasses.length];
- for (int i = 0; i < methodParameterClasses.length; i++) {
- final Class> methodParameterType = methodParameterClasses[i];
- methodParameterTypes[i] = Type.getType(methodParameterType);
- }
- } else {
- wrappedFromSignature = context.getMethodSignature(toType.header, true);
- methodDescriptor = context.getMethodDescriptor(toType.header);
- methodSignature = context.getMethodSignature(toType.header);
- interfaces = new String[]{context.getInternalName(toType)};
-
- JavaSynthesizedFunctionInstance function = context.getFunction(toType);
-
- implementationMethod = new JavaNativeMethod(
- classInfo,
- JavaNativeMethod.Kind.COMPILED,
- function.getMethod(),
- true,
- methodDescriptor,
- JavaModifiers.PUBLIC,
- false // TODO: generic result or not
- );
-
- methodParameterTypes = new Type[toType.header.parameters.length];
- for (int i = 0; i < methodParameterTypes.length; i++) {
- methodParameterTypes[i] = context.getType(toType.header.parameters[i].type);
- }
- }
-
- final JavaNativeMethod wrappedMethod = context.getFunctionalInterface(fromType);
- final String constructorDescriptor = "(" + wrappedFromSignature + ")V";
- // ToDo: Is signature===descriptor fine here or do we need the actual signature here?
- final String constructorSignature = "(" + wrappedFromSignature + ")V";
-
- final ClassWriter lambdaCW = new JavaClassWriter(ClassWriter.COMPUTE_FRAMES);
- lambdaCW.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, className, null, "java/lang/Object", interfaces);
-
- //The field storing the wrapped object
- {
- lambdaCW.visitField(Modifier.PRIVATE | Modifier.FINAL, "wrapped", wrappedFromSignature, null, null).visitEnd();
- }
-
- //Constructor
- {
- JavaNativeMethod constructor = JavaNativeMethod.getConstructor(classInfo, constructorDescriptor, Opcodes.ACC_PUBLIC);
- JavaCompilingMethod compiling = new JavaCompilingMethod(constructor, constructorSignature);
- final JavaWriter constructorWriter = new JavaWriter(context.logger, position, lambdaCW, compiling, null);
- constructorWriter.start();
- constructorWriter.loadObject(0);
- constructorWriter.dup();
- constructorWriter.invokeSpecial(Object.class, "", "()V");
-
- constructorWriter.loadObject(1);
- constructorWriter.putField(className, "wrapped", wrappedFromSignature);
-
- constructorWriter.ret();
- constructorWriter.end();
- }
-
- //The actual method
- {
- JavaCompilingMethod compiling = new JavaCompilingMethod(implementationMethod, methodSignature);
- final JavaWriter functionWriter = new JavaWriter(context.logger, position, lambdaCW, compiling, null);
- functionWriter.start();
-
- //this.wrapped
- functionWriter.loadObject(0);
- functionWriter.getField(className, "wrapped", wrappedFromSignature);
-
- //Load all function parameters
- for (int i = 0, currentLocalPosition = 1; i < methodParameterTypes.length; i++) {
- functionWriter.load(methodParameterTypes[i], currentLocalPosition);
- currentLocalPosition += methodParameterTypes[i].getSize();
- }
-
- //Invokes the wrapped interface's method and returns the result
- functionWriter.invokeInterface(wrappedMethod);
- final TypeID returnType = fromType.header.getReturnType();
- final Type rtype = context.getType(returnType);
- if (!CompilerUtils.isPrimitive(returnType)) {
- functionWriter.checkCast(rtype);
- }
- functionWriter.returnType(rtype);
- functionWriter.end();
- }
-
- lambdaCW.visitEnd();
- context.register(className, lambdaCW.toByteArray());
-
- return new FunctionCastWrapperClass(className, constructorDescriptor);
- }
-
@Override
public Void visitSupertypeCast(SupertypeCastExpression expression) {
expression.value.accept(this);
@@ -1341,14 +1117,4 @@ private Void tagVariableAndUpdateLastUsage(VariableID id) {
public JavaWriter getJavaWriter() {
return javaWriter;
}
-
- private static class FunctionCastWrapperClass {
- final String className;
- final String constructorDesc;
-
- FunctionCastWrapperClass(String className, String constructorDesc) {
- this.className = className;
- this.constructorDesc = constructorDesc;
- }
- }
}
diff --git a/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaMethodBytecodeCompiler.java b/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaMethodBytecodeCompiler.java
index 9ad94499..3e6edfad 100644
--- a/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaMethodBytecodeCompiler.java
+++ b/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaMethodBytecodeCompiler.java
@@ -124,7 +124,7 @@ public class JavaMethodBytecodeCompiler implements JavaMethodCompiler {
private static final JavaNativeMethod OBJECTS_EQUALS = new JavaNativeMethod(JavaClass.fromInternalName("java/util/Objects", JavaClass.Kind.CLASS), JavaNativeMethod.Kind.STATIC, "equals", false, "(Ljava/lang/Object;Ljava/lang/Object;)Z", 0, false);
- private static final JavaNativeMethod STRINGBUILDER_LENGTH = JavaNativeMethod.getNativeVirtual(JavaClass.STRINGBUILDER, "length", "()I");
+ private static final JavaNativeMethod STRINGBUILDER_LENGTH = JavaNativeMethod.getNativeVirtual(JavaClass.STRING_BUILDER, "length", "()I");
private final JavaWriter javaWriter;
private final JavaExpressionVisitor expressionVisitor;
diff --git a/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaWriter.java b/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaWriter.java
index 0c0b7473..4215f05e 100644
--- a/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaWriter.java
+++ b/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaWriter.java
@@ -7,6 +7,8 @@
import org.openzen.zenscript.codemodel.HighLevelDefinition;
import org.openzen.zenscript.codemodel.statement.VariableID;
import org.openzen.zenscript.javabytecode.JavaLocalVariableInfo;
+import org.openzen.zenscript.javabytecode.compiler.indy.JavaCondy;
+import org.openzen.zenscript.javabytecode.compiler.indy.JavaIndy;
import org.openzen.zenscript.javashared.JavaClass;
import org.openzen.zenscript.javashared.compiling.JavaCompilingMethod;
import org.openzen.zenscript.javashared.JavaNativeField;
@@ -15,13 +17,12 @@
import java.io.IOException;
import java.nio.file.Files;
-import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.function.UnaryOperator;
import static org.objectweb.asm.Opcodes.*;
@@ -295,7 +296,11 @@ public void ldc(Object value) {
if (debug)
logger.debug("ldc " + value);
- visitor.visitLdcInsn(value);
+ if (value instanceof JavaCondy) {
+ ((JavaCondy) value).visit(visitor::visitLdcInsn);
+ } else {
+ visitor.visitLdcInsn(value);
+ }
}
public void constant(byte value) {
@@ -384,6 +389,14 @@ public void constant(JavaClass cls) {
this.ldc(Type.getObjectType(cls.internalName));
}
+ public void constant(UnaryOperator valueBuilder) {
+ this.constant(JavaCondy.build(valueBuilder));
+ }
+
+ public void constant(JavaCondy value) {
+ value.visit(this::ldc);
+ }
+
public void pop() {
if (debug)
logger.debug("pop");
@@ -1086,7 +1099,7 @@ public void invokeSpecial(String ownerInternalName, String name, String descript
visitor.visitMethodInsn(INVOKESPECIAL, ownerInternalName, name, descriptor, false);
}
- public void invokeSpecial(Class owner, String name, String descriptor) {
+ public void invokeSpecial(Class> owner, String name, String descriptor) {
invokeSpecial(Type.getInternalName(owner), name, descriptor);
}
@@ -1112,6 +1125,17 @@ public void invokeInterface(JavaNativeMethod method) {
visitor.visitMethodInsn(INVOKEINTERFACE, method.cls.internalName, method.name, method.descriptor, true);
}
+ public void invokeDynamic(UnaryOperator indyBuilder) {
+ invokeDynamic(JavaIndy.build(indyBuilder));
+ }
+
+ public void invokeDynamic(JavaIndy indy) {
+ if (debug)
+ logger.debug("invokeDynamic " + indy);
+
+ indy.visit(visitor::visitInvokeDynamicInsn);
+ }
+
public void newObject(String internalName) {
if (debug)
logger.debug("newObject " + internalName);
diff --git a/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/capturing/JavaCapturedExpressionVisitorToAccessCapturesInsideTheLambda.java b/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/capturing/JavaCapturedExpressionVisitorToAccessCapturesInsideTheLambda.java
deleted file mode 100644
index fd034bda..00000000
--- a/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/capturing/JavaCapturedExpressionVisitorToAccessCapturesInsideTheLambda.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package org.openzen.zenscript.javabytecode.compiler.capturing;
-
-import org.openzen.zenscript.codemodel.expression.FunctionExpression;
-import org.openzen.zenscript.codemodel.expression.GetLocalVariableExpression;
-import org.openzen.zenscript.codemodel.expression.captured.*;
-import org.openzen.zenscript.javabytecode.JavaBytecodeContext;
-import org.openzen.zenscript.javabytecode.JavaMangler;
-import org.openzen.zenscript.javabytecode.compiler.JavaWriter;
-
-/**
- * {@link CapturedExpressionVisitor} used to access captured values inside a lambda expression.
- */
-public class JavaCapturedExpressionVisitorToAccessCapturesInsideTheLambda implements CapturedExpressionVisitor {
-
- private final String lambdaClassName;
- private final FunctionExpression functionExpression;
- private final JavaMangler javaMangler;
- private final JavaBytecodeContext context;
- private final JavaWriter javaWriter;
-
- public JavaCapturedExpressionVisitorToAccessCapturesInsideTheLambda(
- final JavaBytecodeContext context,
- final JavaWriter javaWriter,
- final JavaMangler javaMangler,
- final String lambdaClassName,
- final FunctionExpression functionExpression
- ) {
- this.context = context;
- this.javaWriter = javaWriter;
- this.lambdaClassName = lambdaClassName;
- this.functionExpression = functionExpression;
- this.javaMangler = javaMangler;
- }
- @Override
- public Void visitCapturedThis(CapturedThisExpression expression) {
- javaWriter.loadObject(0);
- javaWriter.getField(lambdaClassName, this.javaMangler.mangleCapturedParameter(1, true), context.getDescriptor(expression.type));
- return null;
- }
-
- @Override
- public Void visitCapturedParameter(CapturedParameterExpression expression) {
- final int position = calculateMemberPosition(expression, this.functionExpression);
-
- javaWriter.loadObject(0);
- javaWriter.getField(lambdaClassName, this.javaMangler.mangleCapturedParameter(position, false), context.getDescriptor(expression.parameter.type));
- return null;
- }
-
- @Override
- public Void visitCapturedLocal(CapturedLocalVariableExpression expression) {
- final int position = calculateMemberPosition(new GetLocalVariableExpression(expression.position, expression.variable), this.functionExpression);
-
- javaWriter.loadObject(0);
- javaWriter.getField(lambdaClassName, this.javaMangler.mangleCapturedParameter(position, false), context.getDescriptor(expression.type));
- return null;
- }
-
- @Override
- public Void visitRecaptured(CapturedClosureExpression expression) {
- final int position = findIndex(expression);
-
- javaWriter.loadObject(0);
- javaWriter.getField(lambdaClassName, this.javaMangler.mangleCapturedParameter(position, false), context.getDescriptor(expression.type));
- return null;
- }
-
- private static int findIndex(CapturedExpression expression) {
- int h = 1;
- for (CapturedExpression capture : expression.closure.captures) {
- if(capture.equals(expression)) {
- return h;
- }
- h++;
- }
-
- throw new IllegalStateException(expression.position.toString() + ": Captured Statement error");
- }
-
- private static int calculateMemberPosition(GetLocalVariableExpression localVariableExpression, FunctionExpression expression) {
- int h = 1;
- for (CapturedExpression capture : expression.closure.captures) {
- if (capture instanceof CapturedLocalVariableExpression && ((CapturedLocalVariableExpression) capture).variable == localVariableExpression.variable)
- return h;
- if (capture instanceof CapturedClosureExpression && ((CapturedClosureExpression) capture).value instanceof CapturedLocalVariableExpression && ((CapturedLocalVariableExpression) ((CapturedClosureExpression) capture).value).variable == localVariableExpression.variable)
- return h;
- h++;
- }
- throw new IllegalStateException(localVariableExpression.position.toString() + ": Captured Statement error");
- }
-
- private static int calculateMemberPosition(CapturedParameterExpression functionParameterExpression, FunctionExpression expression) {
- int h = 1;
-
- for (CapturedExpression capture : expression.closure.captures) {
- if (capture instanceof CapturedParameterExpression && ((CapturedParameterExpression) capture).parameter == functionParameterExpression.parameter)
- return h;
- h++;
- }
- throw new IllegalStateException(functionParameterExpression.position.toString() + ": Captured Statement error");
- }
-}
diff --git a/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/capturing/JavaCapturedExpressionVisitorToPutCapturesOnTheStackBeforeCallingTheCtor.java b/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/capturing/JavaCapturedExpressionVisitorToPutCapturesOnTheStackBeforeCallingTheCtor.java
deleted file mode 100644
index 84f12bdf..00000000
--- a/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/capturing/JavaCapturedExpressionVisitorToPutCapturesOnTheStackBeforeCallingTheCtor.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package org.openzen.zenscript.javabytecode.compiler.capturing;
-
-import org.openzen.zenscript.codemodel.expression.ExpressionVisitor;
-import org.openzen.zenscript.codemodel.expression.GetFunctionParameterExpression;
-import org.openzen.zenscript.codemodel.expression.GetLocalVariableExpression;
-import org.openzen.zenscript.codemodel.expression.ThisExpression;
-import org.openzen.zenscript.codemodel.expression.captured.*;
-
-/**
- * {@link CapturedExpressionVisitor} used to put the captured expressions on the stack.
- * The {@link org.openzen.zenscript.javabytecode.compiler.JavaExpressionVisitor} will use this class just before it invokes
- * the generated lambda class' constructor.
- */
-public class JavaCapturedExpressionVisitorToPutCapturesOnTheStackBeforeCallingTheCtor implements CapturedExpressionVisitor {
- private final ExpressionVisitor expressionVisitor;
-
- public JavaCapturedExpressionVisitorToPutCapturesOnTheStackBeforeCallingTheCtor(ExpressionVisitor expressionVisitor) {
- this.expressionVisitor = expressionVisitor;
- }
-
- @Override
- public Void visitCapturedThis(CapturedThisExpression expression) {
- return new ThisExpression(expression.position, expression.type).accept(expressionVisitor);
- }
-
- @Override
- public Void visitCapturedParameter(CapturedParameterExpression expression) {
- return new GetFunctionParameterExpression(expression.position, expression.parameter).accept(expressionVisitor);
- }
-
- @Override
- public Void visitCapturedLocal(CapturedLocalVariableExpression expression) {
- return new GetLocalVariableExpression(expression.position, expression.variable).accept(expressionVisitor);
- }
-
- @Override
- public Void visitRecaptured(CapturedClosureExpression expression) {
- return expression.value.accept(expressionVisitor);
- }
-}
diff --git a/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/definitions/JavaMemberVisitor.java b/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/definitions/JavaMemberVisitor.java
index 5606a35d..cb2b3485 100644
--- a/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/definitions/JavaMemberVisitor.java
+++ b/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/definitions/JavaMemberVisitor.java
@@ -432,6 +432,16 @@ public void end() {
clinitStatementVisitor.end();
}
+ public static JavaCompilingMethod compileBridgeableMethodNoSideEffect(final JavaNativeMethod overriddenMethodInfo, final String implementationDescriptor) {
+ // TODO("Restore signatures")
+ if (!Objects.equals(overriddenMethodInfo.descriptor, implementationDescriptor)) {
+ final JavaNativeMethod actualMethod = overriddenMethodInfo.createBridge(implementationDescriptor);
+ return new JavaCompilingMethod(actualMethod, null);
+ } else {
+ return new JavaCompilingMethod(overriddenMethodInfo, null);
+ }
+ }
+
public static JavaCompilingMethod compileBridgeableMethod(
JavaBytecodeContext context,
CodePosition position,
diff --git a/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/indy/BsmData.java b/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/indy/BsmData.java
new file mode 100644
index 00000000..f53e86da
--- /dev/null
+++ b/JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/indy/BsmData.java
@@ -0,0 +1,203 @@
+package org.openzen.zenscript.javabytecode.compiler.indy;
+
+import org.objectweb.asm.Type;
+import org.openzen.zenscript.javashared.JavaClass;
+import org.openzen.zenscript.javashared.JavaModifiers;
+import org.openzen.zenscript.javashared.JavaNativeMethod;
+import org.openzen.zenscript.javashared.compiling.JavaCompilingMethod;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.UnaryOperator;
+import java.util.stream.Stream;
+
+public final class BsmData {
+ public enum InvokeType {
+ STATIC,
+ VIRTUAL,
+ SPECIAL,
+ INTERFACE
+ }
+
+ public static final class Builder {
+ // TODO("Think about this")
+ private static final boolean ALLOW_RELAX = false;
+
+ private final IndyTarget indyTarget;
+ private final Constructor constructor;
+ private final List