Skip to content

Commit

Permalink
Merge pull request #182 from ZenCodeLang/feature/refactor-javanative-…
Browse files Browse the repository at this point in the history
…stdlib-classes

WIP: move javanative type resolution into own class
  • Loading branch information
stanhebben authored Oct 18, 2024
2 parents 6e9bd58 + 5634b1c commit 92ea82d
Show file tree
Hide file tree
Showing 40 changed files with 277 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,12 @@ public ResolvingType resolve(TypeID[] typeArguments) {
for (IDefinitionMember member : this.members) {
member.registerTo(type, members, mapper);
}
List<TypeID> interfaces = this.members.stream().map(IDefinitionMember::asImplementation).filter(Optional::isPresent).map(Optional::get).collect(Collectors.toList());
List<TypeID> interfaces = this.members.stream()
.map(IDefinitionMember::asImplementation)
.filter(Optional::isPresent)
.map(Optional::get)
.map(mapper::map)
.collect(Collectors.toList());

members.method(new MethodInstance(BuiltinMethodSymbol.OBJECT_SAME, new FunctionHeader(BasicTypeID.BOOL, type), type));
members.method(new MethodInstance(BuiltinMethodSymbol.OBJECT_NOTSAME, new FunctionHeader(BasicTypeID.BOOL, type), type));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ public Void visitCustomIterator(IteratorMember member) {

@Override
public Void visitImplementation(ImplementationMember implementation) {
for (MemberAnnotation annotation : implementation.annotations)
annotation.apply(implementation);

for (IDefinitionMember member : implementation.members) {
member.accept(this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public CastedExpression of(Expression value) {
if (value.type.equals(type) || type == BasicTypeID.UNDETERMINED)
return new CastedExpression(CastedExpression.Level.EXACT, value);
if (value.type.isInvalid())
return CastedExpression.invalid(value);
return CastedExpression.invalidType(value);

ResolvedType resolvedTargetType = compiler.resolve(type);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,12 @@ public static CastedExpression invalid(CodePosition position, CompileError error
return new CastedExpression(position, error);
}

public static CastedExpression invalid(Expression expression) {
return new CastedExpression(Level.INVALID, expression);
public static CastedExpression invalid(Expression expression, CompileError error) {
return new CastedExpression(Level.INVALID, expression, error);
}

public static CastedExpression invalidType(Expression expression) {
return new CastedExpression(Level.INVALID, expression, expression.type.asInvalid().error);
}

public final Level level;
Expand All @@ -59,6 +63,12 @@ public CastedExpression(CodePosition position, CompileError error) {
this.error = error;
}

private CastedExpression(Level level, Expression value, CompileError error) {
this.level = level;
this.value = value;
this.error = error;
}

public boolean isFailed() {
return level == Level.INVALID;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,10 @@ public static CompileError invalidTypeArguments() {
return new CompileError(CompileExceptionCode.INVALID_TYPE_ARGUMENTS, "Invalid number of type arguments");
}

public static CompileError invalidType() {
return new CompileError(CompileExceptionCode.INVALID_TYPE, "Invalid type");
}

public static CompileError noInnerType(TypeID type, String name) {
return new CompileError(CompileExceptionCode.NO_SUCH_TYPE, "No such inner type in " + type + ": " + name);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public Expression eval(ExpressionBuilder builder, CallEvaluator<T> evaluator) {

public CastedExpression cast(ExpressionBuilder builder, CastedEval eval, CallEvaluator<T> evaluator) {
if (this.error != null) {
return CastedExpression.invalid(builder.invalid(error));
return CastedExpression.invalid(builder.invalid(error), error);
} else {
return eval.of(evaluator.eval(builder, method, arguments));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
package org.openzen.zenscript.codemodel.definition;

import org.openzen.zenscript.codemodel.GenericName;
import org.openzen.zenscript.codemodel.identifiers.ExpansionSymbol;
import org.openzen.zenscript.codemodel.identifiers.TypeSymbol;
import org.openzen.zenscript.codemodel.type.DefinitionTypeID;
import org.openzen.zenscript.codemodel.type.TypeID;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.*;

public class ZSPackage {
public final String name;
Expand Down Expand Up @@ -39,6 +35,10 @@ public boolean contains(String name) {
return types.containsKey(name) || subPackages.containsKey(name);
}

public TypeSymbol getImport(String[] name) {
return getImport(Arrays.asList(name), 0);
}

public TypeSymbol getImport(List<String> name, int depth) {
if (depth >= name.size())
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ public boolean isInvalid() {
return true;
}

@Override
public InvalidTypeID asInvalid() {
return this;
}

@Override
public ResolvingType resolve() {
return MemberSet.create(this).build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.openzen.zencode.shared.CodePosition;
import org.openzen.zenscript.codemodel.GenericMapper;
import org.openzen.zenscript.codemodel.compilation.CompileErrors;
import org.openzen.zenscript.codemodel.compilation.ResolvedType;
import org.openzen.zenscript.codemodel.compilation.ResolvingType;
import org.openzen.zenscript.codemodel.expression.Expression;
Expand Down Expand Up @@ -88,6 +89,10 @@ default boolean isInvalid() {
return false;
}

default InvalidTypeID asInvalid() {
return new InvalidTypeID(CodePosition.UNKNOWN, CompileErrors.invalidType());
}

default boolean canCastImplicitTo(TypeID other) {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public ArrayHelperType getWithOneDimensionLess() {
public void newArray(JavaWriter javaWriter) {
if(elementType instanceof GenericTypeID) {

elementType.accept(javaWriter, new JavaTypeExpressionVisitor(context));
elementType.accept(javaWriter, new JavaTypeExpressionVisitor(context, false));
javaWriter.swap();
final JavaClass arrayClass = JavaClass.fromInternalName("java/lang/reflect/Array", JavaClass.Kind.CLASS);
javaWriter.invokeStatic(JavaNativeMethod.getStatic(arrayClass, "newInstance", "(Ljava/lang/Class;I)Ljava/lang/Object;", 0));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ void visitMultiDimArray(JavaWriter javaWriter, int[] sizeLocations, int[] counte

final ArrayHelperType elementType = currentArrayType.getWithOneDimensionLess();
if (arrayType.elementType.isGeneric()) {
arrayType.elementType.accept(javaWriter, new JavaTypeExpressionVisitor(context));
arrayType.elementType.accept(javaWriter, new JavaTypeExpressionVisitor(context, false));
javaWriter.loadInt(currentArraySizeLocation);
javaWriter.invokeStatic(ARRAY_NEWINSTANCE);
javaWriter.checkCast(context.getInternalName(arrayType));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
private final JavaUnboxingTypeVisitor unboxingTypeVisitor;
private final JavaUnboxingTypeVisitor optionalUnwrappingTypeVisitor;
private final JavaFieldBytecodeCompiler fieldCompiler;
private final JavaMethodBytecodeCompiler methodCompiler;
public final JavaMethodBytecodeCompiler methodCompiler;
private final CapturedExpressionVisitor<Void> capturedExpressionVisitor;

public JavaExpressionVisitor(JavaBytecodeContext context, JavaCompiledModule module, JavaWriter javaWriter, JavaMangler javaMangler) {
Expand Down Expand Up @@ -105,7 +105,7 @@ public Void visitAndAnd(AndAndExpression expression) {
public Void visitArray(ArrayExpression expression) {
Type type = context.getType(expression.arrayType.elementType);
if (expression.arrayType.elementType.isGeneric()) {
expression.arrayType.elementType.accept(javaWriter, new JavaTypeExpressionVisitor(context));
expression.arrayType.elementType.accept(javaWriter, new JavaTypeExpressionVisitor(context, false));
javaWriter.constant(expression.expressions.length);
javaWriter.invokeStatic(ARRAY_NEWINSTANCE);
javaWriter.checkCast(context.getInternalName(expression.arrayType));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,22 +149,40 @@ public Void nativeConstructor(JavaNativeMethod method, TypeID type, CallArgument
AtomicInteger typeArguments = new AtomicInteger(0);
if (method.compile) {
type.asDefinition().ifPresent(definitionType -> {
final JavaTypeExpressionVisitor javaTypeExpressionVisitor = new JavaTypeExpressionVisitor(context);
final JavaTypeExpressionVisitor javaTypeExpressionVisitor = new JavaTypeExpressionVisitor(context, false);
typeArguments.set(definitionType.typeArguments.length);
for (TypeID typeParameter : definitionType.typeArguments) {
typeParameter.accept(javaWriter, javaTypeExpressionVisitor);
}
});
}
handleArguments(typeArguments.get(), method, arguments, false);
handleArguments(typeArguments.get(), method, arguments, false, false);
javaWriter.invokeSpecial(method);
return null;
}

@Override
public Void nativeBaseConstructor(JavaNativeMethod method, TypeID type, CallArguments arguments) {
javaWriter.loadObject(0);
AtomicInteger typeArguments = new AtomicInteger(0);
if (method.compile) {
type.asDefinition().ifPresent(definitionType -> {
final JavaTypeExpressionVisitor javaTypeExpressionVisitor = new JavaTypeExpressionVisitor(context, true);
typeArguments.set(definitionType.typeArguments.length);
for (TypeID typeParameter : definitionType.typeArguments) {
typeParameter.accept(javaWriter, javaTypeExpressionVisitor);
}
});
}
handleArguments(typeArguments.get(), method, arguments, false, false);
javaWriter.invokeSpecial(method);
return null;
}

@Override
public Void nativeVirtualMethod(JavaNativeMethod method, TypeID returnType, Expression target, CallArguments arguments) {
if (arguments.expansionTypeArguments.length > 0) {
final JavaTypeExpressionVisitor javaTypeExpressionVisitor = new JavaTypeExpressionVisitor(context);
final JavaTypeExpressionVisitor javaTypeExpressionVisitor = new JavaTypeExpressionVisitor(context, false);
for (int i = 0; i < arguments.expansionTypeArguments.length; i++) {
arguments.expansionTypeArguments[i].accept(javaWriter, javaTypeExpressionVisitor);
}
Expand All @@ -181,7 +199,7 @@ public Void nativeStaticMethod(JavaNativeMethod method, TypeID returnType, CallA
}

public void nativeMethod(JavaNativeMethod method, TypeID returnType, CallArguments arguments, boolean asStatic) {
handleArguments(arguments.typeArguments.length, method, arguments, asStatic);
handleArguments(arguments.typeArguments.length, method, arguments, asStatic, false);

if (method.kind == JavaNativeMethod.Kind.STATIC) {
javaWriter.invokeStatic(method);
Expand Down Expand Up @@ -209,14 +227,19 @@ public void nativeMethod(JavaNativeMethod method, TypeID returnType, CallArgumen
@Override
public Void nativeSpecialMethod(JavaNativeMethod method, TypeID returnType, Expression target, CallArguments arguments) {
target.accept(expressionVisitor);
handleArguments(arguments.typeArguments.length, method, arguments, false);
handleArguments(arguments.typeArguments.length, method, arguments, false, false);
javaWriter.invokeSpecial(method);
return null;
}

private void handleArguments(int typeArguments, JavaNativeMethod method, CallArguments arguments, boolean asStatic) {
private void handleArguments(
int typeArguments,
JavaNativeMethod method,
CallArguments arguments,
boolean asStatic,
boolean insideConstructor) {
if (method.compile) {
handleTypeArguments(method, arguments);
handleTypeArguments(method, arguments, insideConstructor);
}

// This happens e.g. for Strings where compareTo is a static method in zencode but a virtual one in Java
Expand All @@ -236,8 +259,8 @@ private void handleArguments(int typeArguments, JavaNativeMethod method, CallArg
}
}

private void handleTypeArguments(JavaNativeMethod method, CallArguments arguments) {
final JavaTypeExpressionVisitor javaTypeExpressionVisitor = new JavaTypeExpressionVisitor(context);
private void handleTypeArguments(JavaNativeMethod method, CallArguments arguments, boolean insideConstructor) {
final JavaTypeExpressionVisitor javaTypeExpressionVisitor = new JavaTypeExpressionVisitor(context, insideConstructor);
if (arguments.typeArguments.length != method.typeParameterArguments.length)
throw new IllegalArgumentException("Number of type parameters doesn't match");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.openzen.zenscript.javabytecode.JavaMangler;
import org.openzen.zenscript.javabytecode.compiler.JavaModificationExpressionVisitor.PushOption;
import org.openzen.zenscript.javashared.JavaCompiledModule;
import org.openzen.zenscript.javashared.JavaNativeMethod;
import org.openzen.zenscript.javashared.JavaParameterInfo;
import org.openzen.zenscript.javashared.expressions.JavaFunctionInterfaceCastExpression;

Expand All @@ -27,14 +28,22 @@ public class JavaNonPushingExpressionVisitor implements ExpressionVisitor<Void>
private final JavaExpressionVisitor original;
private final JavaFieldBytecodeCompiler fieldCompiler;
private final JavaMangler mangler;

public JavaNonPushingExpressionVisitor(JavaBytecodeContext context, JavaCompiledModule module, JavaWriter javaWriter, JavaMangler mangler, JavaExpressionVisitor original) {
private final JavaMethodBytecodeCompiler methodCompiler;

public JavaNonPushingExpressionVisitor(
JavaBytecodeContext context,
JavaCompiledModule module,
JavaWriter javaWriter,
JavaMangler mangler,
JavaExpressionVisitor original
) {
this.context = context;
this.module = module;
this.javaWriter = javaWriter;
this.original = original;
this.mangler = mangler;
fieldCompiler = new JavaFieldBytecodeCompiler(javaWriter, original, false);
this.methodCompiler = original.methodCompiler;
}

@Override
Expand Down Expand Up @@ -198,27 +207,29 @@ public Void visitConstructorThisCall(ConstructorThisCallExpression expression) {
javaWriter.loadInt(2);
}

context.getJavaMethod(expression.constructor).compileBaseConstructor(
methodCompiler,
expression.constructor.getTarget(),
expression.arguments);

/*methodCompiler.handleArguments(0, expression.constructor.getHeader(), expression.arguments, false);
for (Expression argument : expression.arguments.arguments) {
argument.accept(original);
}
String internalName = context.getInternalName(expression.objectType);
javaWriter.invokeSpecial(internalName, "<init>", javaWriter.forDefinition.isEnum()
? context.getEnumConstructorDescriptor(expression.constructor.getHeader())
: context.getMethodDescriptor(expression.constructor.getHeader().withReturnType(BasicTypeID.VOID)));
: context.getMethodDescriptor(expression.constructor.getHeader().withReturnType(BasicTypeID.VOID)));*/
return null;
}

@Override
public Void visitConstructorSuperCall(ConstructorSuperCallExpression expression) {
javaWriter.loadObject(0);
for (Expression argument : expression.arguments.arguments) {
argument.accept(original);
}
//No super calls in enums possible, and that's already handled in the enum constructor itself.
javaWriter.invokeSpecial(
context.getInternalName(expression.constructor.getTarget()),
"<init>",
context.getMethodDescriptor(expression.constructor.getHeader().withReturnType(BasicTypeID.VOID)));
context.getJavaMethod(expression.constructor).compileBaseConstructor(
methodCompiler,
expression.constructor.getTarget(),
expression.arguments);

CompilerUtils.writeDefaultFieldInitializers(context, javaWriter, javaWriter.forDefinition, mangler, false);
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,12 @@ public JavaStatementVisitor(JavaBytecodeContext context, JavaExpressionVisitor e
this.javaWriter = expressionVisitor.getJavaWriter();
this.context = context;
this.expressionVisitor = expressionVisitor;
this.nonPushingExpressionVisitor = new JavaNonPushingExpressionVisitor(expressionVisitor.context, expressionVisitor.module, expressionVisitor.javaWriter, javaMangler, expressionVisitor);
this.nonPushingExpressionVisitor = new JavaNonPushingExpressionVisitor(
expressionVisitor.context,
expressionVisitor.module,
expressionVisitor.javaWriter,
javaMangler,
expressionVisitor);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@
*/
public class JavaTypeExpressionVisitor implements TypeVisitorWithContext<JavaWriter, Void, RuntimeException> {
private final JavaBytecodeContext context;
private final boolean insideConstructor;

public JavaTypeExpressionVisitor(JavaBytecodeContext context) {
public JavaTypeExpressionVisitor(JavaBytecodeContext context, boolean insideConstructor) {
this.context = context;
this.insideConstructor = insideConstructor;
}

@Override
Expand Down Expand Up @@ -98,7 +100,7 @@ public Void visitDefinition(JavaWriter writer, DefinitionTypeID definition) {
@Override
public Void visitGeneric(JavaWriter writer, GenericTypeID generic) {
JavaTypeParameterInfo info = context.target.getTypeParameterInfo(generic.parameter);
if (info.field != null) {
if (info.field != null && !insideConstructor) {
writer.loadObject(0); // this
writer.getField(info.field);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ public Void visitConstructor(ConstructorMember member) {
constructorWriter.nameParameter(0, "index");
}

// TODO: these must be initialized after calling the super constructor (it now ends up before it)
// this seems to work fine, but it might break
for (TypeParameter typeParameter : definition.typeParameters) {
constructorWriter.nameParameter(0, "typeof" + typeParameter.name);
constructorWriter.nameVariable(
Expand Down Expand Up @@ -341,6 +343,10 @@ public Void visitCustomIterator(IteratorMember member) {

@Override
public Void visitImplementation(ImplementationMember member) {
if (member.getTag(NativeTag.class) != null) {
return null;
}

JavaImplementation implementation = context.getJavaImplementation(member);
if (implementation.inline) {
for (IDefinitionMember imember : member.members)
Expand Down
Loading

0 comments on commit 92ea82d

Please sign in to comment.