From 8db81eb22f346623b9cb80a10a1571e656d6d075 Mon Sep 17 00:00:00 2001 From: Stan Hebben Date: Fri, 12 Apr 2024 22:43:18 +0200 Subject: [PATCH] Attempt to fix arrays/arrays-maps-2 --- .../compilation/ExpressionCompiler.java | 5 +- .../impl/capture/LocalThisExpression.java | 59 +++++++++++++++++++ .../impl/compiler/ExpressionCompilerImpl.java | 6 ++ .../impl/compiler/LocalSymbols.java | 14 ++++- .../compiler/JavaExpressionVisitor.java | 34 +++++++++-- .../compiler/JavaMethodBytecodeCompiler.java | 18 +++--- .../javashared/JavaTypeGenericVisitor.java | 18 +++--- .../expression/ParsedExpressionThis.java | 2 +- .../zencode-tests/arrays/arrays-map-2.zc | 28 +++------ .../visitors/ExpressionValidator.java | 3 + 10 files changed, 141 insertions(+), 46 deletions(-) create mode 100644 CodeModel/src/main/java/org/openzen/zenscript/codemodel/compilation/impl/capture/LocalThisExpression.java diff --git a/CodeModel/src/main/java/org/openzen/zenscript/codemodel/compilation/ExpressionCompiler.java b/CodeModel/src/main/java/org/openzen/zenscript/codemodel/compilation/ExpressionCompiler.java index e70e9bdd5..0bdcdaca1 100644 --- a/CodeModel/src/main/java/org/openzen/zenscript/codemodel/compilation/ExpressionCompiler.java +++ b/CodeModel/src/main/java/org/openzen/zenscript/codemodel/compilation/ExpressionCompiler.java @@ -4,9 +4,8 @@ import org.openzen.zencode.shared.CompileError; import org.openzen.zenscript.codemodel.FunctionHeader; import org.openzen.zenscript.codemodel.GenericName; -import org.openzen.zenscript.codemodel.VariableDefinition; +import org.openzen.zenscript.codemodel.compilation.impl.capture.LocalExpression; import org.openzen.zenscript.codemodel.expression.LambdaClosure; -import org.openzen.zenscript.codemodel.statement.VarStatement; import org.openzen.zenscript.codemodel.type.TypeID; import java.util.List; @@ -19,6 +18,8 @@ public interface ExpressionCompiler extends TypeResolver { Optional getThisType(); + Optional getThis(CodePosition position); + Optional getLocalType(); Optional getThrowableType(); diff --git a/CodeModel/src/main/java/org/openzen/zenscript/codemodel/compilation/impl/capture/LocalThisExpression.java b/CodeModel/src/main/java/org/openzen/zenscript/codemodel/compilation/impl/capture/LocalThisExpression.java new file mode 100644 index 000000000..12e219a82 --- /dev/null +++ b/CodeModel/src/main/java/org/openzen/zenscript/codemodel/compilation/impl/capture/LocalThisExpression.java @@ -0,0 +1,59 @@ +package org.openzen.zenscript.codemodel.compilation.impl.capture; + +import org.openzen.zencode.shared.CodePosition; +import org.openzen.zenscript.codemodel.FunctionParameter; +import org.openzen.zenscript.codemodel.compilation.CompilingExpression; +import org.openzen.zenscript.codemodel.compilation.ExpressionCompiler; +import org.openzen.zenscript.codemodel.compilation.expression.AbstractCompilingExpression; +import org.openzen.zenscript.codemodel.expression.*; +import org.openzen.zenscript.codemodel.ssa.CodeBlockStatement; +import org.openzen.zenscript.codemodel.ssa.SSAVariableCollector; +import org.openzen.zenscript.codemodel.type.TypeID; + +public class LocalThisExpression implements LocalExpression { + private final CodePosition position; + private final TypeID type; + + public LocalThisExpression(CodePosition position, TypeID type) { + this.position = position; + this.type = type; + } + + @Override + public LocalExpression capture(LambdaClosure closure) { + CapturedExpression value = new CapturedThisExpression(position, type, closure); + closure.add(value); + return new LocalCapturedExpression(value); + } + + @Override + public CompilingExpression compile(ExpressionCompiler compiler) { + return new Compiling(compiler, position, type); + } + + private static class Compiling extends AbstractCompilingExpression { + private final TypeID type; + + public Compiling(ExpressionCompiler compiler, CodePosition position, TypeID type) { + super(compiler, position); + + this.type = type; + } + + @Override + public Expression eval() { + return compiler.at(position).getThis(type); + } + + @Override + public CompilingExpression assign(CompilingExpression value) { + return this; + } + + @Override + public void collect(SSAVariableCollector collector) {} + + @Override + public void linkVariables(CodeBlockStatement.VariableLinker linker) {} + } +} diff --git a/CodeModel/src/main/java/org/openzen/zenscript/codemodel/compilation/impl/compiler/ExpressionCompilerImpl.java b/CodeModel/src/main/java/org/openzen/zenscript/codemodel/compilation/impl/compiler/ExpressionCompilerImpl.java index a2d404661..d91e1e066 100644 --- a/CodeModel/src/main/java/org/openzen/zenscript/codemodel/compilation/impl/compiler/ExpressionCompilerImpl.java +++ b/CodeModel/src/main/java/org/openzen/zenscript/codemodel/compilation/impl/compiler/ExpressionCompilerImpl.java @@ -6,6 +6,7 @@ import org.openzen.zenscript.codemodel.compilation.*; import org.openzen.zencode.shared.CodePosition; import org.openzen.zenscript.codemodel.compilation.impl.capture.LocalExpression; +import org.openzen.zenscript.codemodel.compilation.impl.capture.LocalThisExpression; import org.openzen.zenscript.codemodel.expression.*; import org.openzen.zenscript.codemodel.globals.IGlobal; import org.openzen.zenscript.codemodel.identifiers.instances.FieldInstance; @@ -56,6 +57,11 @@ public Optional getThisType() { return Optional.ofNullable(localType).map(LocalType::getThisType); } + @Override + public Optional getThis(CodePosition position) { + return getThisType().map(thisType -> locals.capture(position, new LocalThisExpression(position, thisType)).compile(this)); + } + @Override public Optional getLocalType() { return Optional.ofNullable(localType); diff --git a/CodeModel/src/main/java/org/openzen/zenscript/codemodel/compilation/impl/compiler/LocalSymbols.java b/CodeModel/src/main/java/org/openzen/zenscript/codemodel/compilation/impl/compiler/LocalSymbols.java index 583053238..d4c9dfe2f 100644 --- a/CodeModel/src/main/java/org/openzen/zenscript/codemodel/compilation/impl/compiler/LocalSymbols.java +++ b/CodeModel/src/main/java/org/openzen/zenscript/codemodel/compilation/impl/compiler/LocalSymbols.java @@ -5,11 +5,10 @@ import org.openzen.zenscript.codemodel.FunctionParameter; import org.openzen.zenscript.codemodel.compilation.CompilableExpression; import org.openzen.zenscript.codemodel.compilation.CompilingVariable; -import org.openzen.zenscript.codemodel.compilation.impl.capture.LocalExpression; -import org.openzen.zenscript.codemodel.compilation.impl.capture.LocalParameterExpression; -import org.openzen.zenscript.codemodel.compilation.impl.capture.LocalVariableExpression; +import org.openzen.zenscript.codemodel.compilation.impl.capture.*; import org.openzen.zenscript.codemodel.compilation.statement.CompilingLoopStatement; import org.openzen.zenscript.codemodel.expression.LambdaClosure; +import org.openzen.zenscript.codemodel.type.TypeID; import java.util.HashMap; import java.util.Map; @@ -112,6 +111,15 @@ else if (closure != null) return parent.findLocalVariable(position, name); } + public LocalExpression capture(CodePosition position, LocalExpression local) { + if (this.parent == null) + return local; + else if (closure != null) + return local.capture(closure); + else + return parent.capture(position, local); + } + public Optional getDollar() { return Optional.ofNullable(dollar); } 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 08034abed..e784a9b18 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 @@ -8,6 +8,7 @@ import org.openzen.zenscript.codemodel.CompareType; import org.openzen.zenscript.codemodel.FunctionParameter; import org.openzen.zenscript.codemodel.OperatorType; +import org.openzen.zenscript.codemodel.definition.ExpansionDefinition; import org.openzen.zenscript.codemodel.identifiers.MethodID; import org.openzen.zenscript.codemodel.identifiers.ModuleSymbol; import org.openzen.zenscript.codemodel.expression.*; @@ -311,7 +312,13 @@ public Void visitCapturedParameter(CapturedParameterExpression expression) { @Override public Void visitCapturedThis(CapturedThisExpression expression) { - return expression.accept(capturedExpressionVisitor); + // TODO - does this cover all situations? + int thisLocal = 0; + if (javaWriter.forDefinition instanceof ExpansionDefinition) { + thisLocal = javaWriter.forDefinition.typeParameters.length; + } + javaWriter.load(context.getType(expression.type), thisLocal); + return null; } @Override @@ -564,12 +571,19 @@ public Void visitFunction(FunctionExpression expression) { for (CapturedExpression capture : expression.closure.captures) { constructorWriter.dup(); Type type = context.getType(capture.type); - lambdaCW.visitField(Opcodes.ACC_FINAL | Opcodes.ACC_PRIVATE, "captured" + ++i, type.getDescriptor(), null, null).visitEnd(); + String name; + ++i; + if (capture instanceof CapturedThisExpression) { + name = "capturedThis"; + } else { + name = "captured" + i; + } + lambdaCW.visitField(Opcodes.ACC_FINAL | Opcodes.ACC_PRIVATE, name, type.getDescriptor(), null, null).visitEnd(); capture.accept(this); constructorWriter.load(type, i); - constructorWriter.putField(className, "captured" + i, type.getDescriptor()); + constructorWriter.putField(className, name, type.getDescriptor()); } constructorWriter.pop(); @@ -595,7 +609,6 @@ public Void visitGetLocalVariable(GetLocalVariableExpression varExpression) { return null; } - final int position = calculateMemberPosition(varExpression, expression); functionWriter.loadObject(0); functionWriter.getField(className, "captured" + position, context.getDescriptor(varExpression.variable.type)); @@ -609,6 +622,13 @@ public Void visitCapturedParameter(CapturedParameterExpression varExpression) { functionWriter.getField(className, "captured" + position, context.getDescriptor(varExpression.parameter.type)); return null; } + + @Override + public Void visitCapturedThis(CapturedThisExpression expression) { + functionWriter.loadObject(0); + functionWriter.getField(className, "capturedThis", context.getDescriptor(expression.type)); + return null; + } }); expression.body.accept(CSV); @@ -1243,7 +1263,11 @@ public Void visitSubtypeCast(SubtypeCastExpression expression) { @Override public Void visitThis(ThisExpression expression) { - javaWriter.load(context.getType(expression.type), 0); + int thisLocal = 0; + if (javaWriter.forDefinition instanceof ExpansionDefinition) { + thisLocal = javaWriter.forDefinition.typeParameters.length; + } + javaWriter.load(context.getType(expression.type), thisLocal); return null; } 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 26ddf7365..8bcf1038c 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 @@ -165,6 +165,12 @@ public Void nativeConstructor(JavaNativeMethod method, TypeID type, CallArgument @Override public Void nativeVirtualMethod(JavaNativeMethod method, TypeID returnType, Expression target, CallArguments arguments) { + if (arguments.expansionTypeArguments.length > 0) { + final JavaTypeExpressionVisitor javaTypeExpressionVisitor = new JavaTypeExpressionVisitor(context); + for (int i = 0; i < arguments.expansionTypeArguments.length; i++) { + arguments.expansionTypeArguments[i].accept(javaWriter, javaTypeExpressionVisitor); + } + } target.accept(expressionVisitor); return nativeStaticMethod(method, returnType, arguments); } @@ -172,9 +178,6 @@ public Void nativeVirtualMethod(JavaNativeMethod method, TypeID returnType, Expr @Override public Void nativeStaticMethod(JavaNativeMethod method, TypeID returnType, CallArguments arguments) { handleArguments(arguments.typeArguments.length, method, arguments); - if (method.compile) { - handleTypeArguments(method, arguments); - } if (method.kind == JavaNativeMethod.Kind.STATIC) { javaWriter.invokeStatic(method); @@ -205,14 +208,14 @@ public Void nativeStaticMethod(JavaNativeMethod method, TypeID returnType, CallA public Void nativeSpecialMethod(JavaNativeMethod method, TypeID returnType, Expression target, CallArguments arguments) { target.accept(expressionVisitor); handleArguments(arguments.typeArguments.length, method, arguments); - if (method.compile) { - handleTypeArguments(method, arguments); - } javaWriter.invokeSpecial(method); return null; } private void handleArguments(int typeArguments, JavaNativeMethod method, CallArguments arguments) { + if (method.compile) { + handleTypeArguments(method, arguments); + } for (int index = 0; index < arguments.arguments.length; index++) { Expression argument = arguments.arguments[index]; argument.accept(expressionVisitor); @@ -227,9 +230,6 @@ private void handleTypeArguments(JavaNativeMethod method, CallArguments argument if (arguments.typeArguments.length != method.typeParameterArguments.length) throw new IllegalArgumentException("Number of type parameters doesn't match"); - for (int i = 0; i < arguments.expansionTypeArguments.length; i++) { - arguments.expansionTypeArguments[i].accept(javaWriter, javaTypeExpressionVisitor); - } for (int i = 0; i < arguments.typeArguments.length; i++) { if (method.typeParameterArguments[i]) arguments.typeArguments[i].accept(javaWriter, javaTypeExpressionVisitor); diff --git a/JavaShared/src/main/java/org/openzen/zenscript/javashared/JavaTypeGenericVisitor.java b/JavaShared/src/main/java/org/openzen/zenscript/javashared/JavaTypeGenericVisitor.java index bb39a55ae..c8330fbd2 100644 --- a/JavaShared/src/main/java/org/openzen/zenscript/javashared/JavaTypeGenericVisitor.java +++ b/JavaShared/src/main/java/org/openzen/zenscript/javashared/JavaTypeGenericVisitor.java @@ -199,27 +199,31 @@ public String getMethodSignatureExpansion(FunctionHeader header, TypeID expanded final StringBuilder stringBuilder = new StringBuilder(); final ArrayList typeParameters = new ArrayList<>(); expandedClass.extractTypeParameters(typeParameters); - for (TypeParameter typeParameter : header.typeParameters) { - if (!typeParameters.contains(typeParameter)) { - typeParameters.add(typeParameter); - } - } - if (typeParameters.size() != 0) { + if (typeParameters.size() != 0 || header.typeParameters.length != 0) { stringBuilder.append("<"); for (TypeParameter typeParameter : typeParameters) { stringBuilder.append(typeParameter.name); stringBuilder.append(":Ljava/lang/Object;"); } + for (TypeParameter typeParameter : header.typeParameters) { + stringBuilder.append(typeParameter.name); + stringBuilder.append(":Ljava/lang/Object;"); + } stringBuilder.append(">"); } stringBuilder.append("("); - stringBuilder.append(context.getSignature(expandedClass)); for (TypeParameter typeParameter : typeParameters) { stringBuilder.append("Ljava/lang/Class;"); } + stringBuilder.append(context.getSignature(expandedClass)); + for (TypeParameter typeParameter : header.typeParameters) { + stringBuilder.append("Ljava/lang/Class;"); + } stringBuilder.append(getGenericSignature(header.parameters)); stringBuilder.append(")"); stringBuilder.append(context.getSignature(header.getReturnType())); diff --git a/Parser/src/main/java/org/openzen/zenscript/parser/expression/ParsedExpressionThis.java b/Parser/src/main/java/org/openzen/zenscript/parser/expression/ParsedExpressionThis.java index e19c463d2..952a954e8 100644 --- a/Parser/src/main/java/org/openzen/zenscript/parser/expression/ParsedExpressionThis.java +++ b/Parser/src/main/java/org/openzen/zenscript/parser/expression/ParsedExpressionThis.java @@ -33,7 +33,7 @@ public Compiling(ExpressionCompiler compiler, CodePosition position, LocalType t @Override public Expression eval() { - return compiler.at(position).getThis(this.type.getThisType()); + return compiler.getThis(position).orElseThrow(() -> new AssertionError("what?")).eval(); } @Override diff --git a/ScriptingEngineTester/src/main/resources/zencode-tests/arrays/arrays-map-2.zc b/ScriptingEngineTester/src/main/resources/zencode-tests/arrays/arrays-map-2.zc index 1603c891c..4c16f4c33 100644 --- a/ScriptingEngineTester/src/main/resources/zencode-tests/arrays/arrays-map-2.zc +++ b/ScriptingEngineTester/src/main/resources/zencode-tests/arrays/arrays-map-2.zc @@ -1,26 +1,16 @@ -#output: 2 -#output: 4 -#output: 6 +#output: a1 +#output: a2 +#output: a3 public expand T[] { public map(projection as function(value as T) as U) as U[] { - var values = new U[](length); - for i, value in this - values[i] = projection(value); - return values; - } - - [Native("mapKeyValues")] - public map(projection as function(index as usize, value as T) as U) as U[] { - var values = new U[](length); - for i, value in this - values[i] = projection(i, value); - return values; + return new U[](length, index => projection(this[index])); } } -var a = [1, 2, 3]; -var b = a.map(x => x * 2); -for item in b { +var a = ["1", "2", "3"]; +var b = a.map(x => "a" + x); +println(typeof(b)); +/*for item in b { println(item); -} +}*/ diff --git a/Validator/src/main/java/org/openzen/zenscript/validator/visitors/ExpressionValidator.java b/Validator/src/main/java/org/openzen/zenscript/validator/visitors/ExpressionValidator.java index f36125ae4..f2cde7c42 100644 --- a/Validator/src/main/java/org/openzen/zenscript/validator/visitors/ExpressionValidator.java +++ b/Validator/src/main/java/org/openzen/zenscript/validator/visitors/ExpressionValidator.java @@ -738,6 +738,9 @@ private void checkNotStatic(CodePosition position, MethodInstance member) { private void checkCallArguments(CodePosition position, FunctionHeader originalHeader, FunctionHeader instancedHeader, CallArguments arguments) { ValidationUtils.validateTypeArguments(validator, position, originalHeader.typeParameters, arguments.typeArguments); + if (arguments.typeArguments.length != 0) { + instancedHeader = instancedHeader.instanceForCall(arguments); + } boolean isVariadic = instancedHeader.isVariadicCall(arguments); for (int i = 0; i < arguments.arguments.length; i++) {