use of dyvilx.tools.compiler.ast.classes.IClass in project Dyvil by Dyvil.
the class AbstractMethod method writeInvoke.
@Override
public void writeInvoke(MethodWriter writer, IValue receiver, ArgumentList arguments, ITypeContext typeContext, int lineNumber) throws BytecodeException {
if (this.typeParameters != null) {
this.typeParameters.writeArguments(writer, typeContext);
}
writer.visitLineNumber(lineNumber);
final int opcode;
final String mangledName = this.getInternalName();
final String descriptor = this.getDescriptor();
if (this.hasModifier(Modifiers.EXTENSION)) {
// extension method invocation
final Handle handle = new Handle(ClassFormat.H_INVOKESTATIC, this.enclosingClass.getInternalName(), mangledName, descriptor);
writer.visitInvokeDynamicInsn(mangledName, descriptor, EXTENSION_BSM, handle);
return;
}
final String owner;
final boolean isInterface;
if (receiver != null) {
final IType receiverType = receiver.getType();
if (receiver.isIgnoredClassAccess() && receiverType.hasTag(IType.TYPE_VAR)) {
// Dynamic invocation of a static method based on a type variable
writer.visitInvokeDynamicInsn(mangledName, descriptor.replace("(", "(Ljava/lang/Class;"), STATICVIRTUAL_BSM);
return;
}
if (receiver.valueTag() == IValue.SUPER) {
// Super-method invocation
opcode = Opcodes.INVOKESPECIAL;
owner = this.enclosingClass.getInternalName();
isInterface = this.enclosingClass.isInterface();
} else if (this.isStatic()) {
opcode = Opcodes.INVOKESTATIC;
owner = this.enclosingClass.getInternalName();
isInterface = this.enclosingClass.isInterface();
} else {
// bugfix: for non-static calls, we use the type of the receiver to avoid
// IllegalAccessExceptions on the owner class.
// Example: Calling length() on a StringBuilder object resolves to AbstractStringBuilder.length(),
// but AbstractStringBuilder is not accessible
final IClass receiverClass = receiverType.getTheClass();
opcode = this.getInvokeOpcode(receiverClass);
owner = receiverType.getInternalName();
isInterface = receiverClass.isInterface();
}
} else {
opcode = this.getInvokeOpcode();
owner = this.enclosingClass.getInternalName();
isInterface = this.enclosingClass.isInterface();
}
writer.visitMethodInsn(opcode, owner, mangledName, descriptor, isInterface);
}
use of dyvilx.tools.compiler.ast.classes.IClass in project Dyvil by Dyvil.
the class FieldPattern method toString.
@Override
public void toString(String prefix, StringBuilder buffer) {
final IClass enclosingClass = this.dataMember.getEnclosingClass();
if (enclosingClass != null) {
buffer.append(enclosingClass.getName()).append('.');
}
buffer.append(this.dataMember.getName());
}
use of dyvilx.tools.compiler.ast.classes.IClass in project Dyvil by Dyvil.
the class ObjectSurrogate method resolve.
@Override
public Pattern resolve(MarkerList markers, IContext context) {
if (this.type.typeTag() == IType.NAMED) {
NamedType namedType = (NamedType) this.type;
final Name name = namedType.getName();
IType parent = namedType.getParent();
if (parent != null) {
parent = parent.resolveType(markers, context);
namedType.setParent(parent);
IDataMember dataMember = parent.resolveField(name);
if (dataMember != null) {
return new FieldPattern(this.position, dataMember).resolve(markers, context);
}
} else {
IDataMember dataMember = context.resolveField(name);
if (dataMember != null) {
return new FieldPattern(this.position, dataMember).resolve(markers, context);
}
}
}
this.type = this.type.resolveType(markers, context);
final IClass theClass = this.type.getTheClass();
if (theClass != null && !theClass.hasModifier(Modifiers.OBJECT_CLASS)) {
markers.add(Markers.semanticError(this.position, "pattern.object", theClass.getName()));
}
return this;
}
use of dyvilx.tools.compiler.ast.classes.IClass in project Dyvil by Dyvil.
the class TupleSurrogate method withType.
@Override
public Pattern withType(IType type, MarkerList markers) {
final IClass tupleClass = TupleType.getTupleClass(this.patternCount);
if (tupleClass == null) {
return null;
}
final IType tupleType = tupleClass.getClassType();
if (!Types.isSuperClass(type, tupleType)) {
return null;
}
// reset type to recompute it later
this.tupleType = null;
final TypeParameterList typeParameters = tupleClass.getTypeParameters();
for (int i = 0; i < this.patternCount; i++) {
final IType elementType = Types.resolveTypeSafely(type, typeParameters.get(i));
final Pattern pattern = this.patterns[i];
final Pattern typedPattern = pattern.withType(elementType, markers);
if (typedPattern == null) {
final Marker marker = Markers.semanticError(pattern.getPosition(), "pattern.tuple.element.type");
marker.addInfo(Markers.getSemantic("pattern.type", pattern.getType()));
marker.addInfo(Markers.getSemantic("tuple.element.type", elementType));
markers.add(marker);
} else {
this.patterns[i] = typedPattern;
}
}
if (!Types.isSuperClass(tupleType, type)) {
return new TypeCheckPattern(this, type, tupleType);
}
return this;
}
use of dyvilx.tools.compiler.ast.classes.IClass in project Dyvil by Dyvil.
the class ClassUnit method compile.
@Override
public void compile() {
if (this.printMarkers()) {
return;
}
if (this.headerDeclaration != null) {
final File file = new File(this.outputDirectory, this.name.qualified + DyvilFileType.OBJECT_EXTENSION);
ObjectFormat.write(this.compiler, file, this);
}
for (int i = 0; i < this.classCount; i++) {
final IClass theClass = this.classes[i];
final File file = new File(this.outputDirectory, theClass.getFileName());
ClassWriter.compile(this.compiler, file, theClass);
}
for (int i = 0; i < this.innerClassCount; i++) {
final ICompilable compilable = this.innerClasses[i];
final File file = new File(this.outputDirectory, compilable.getFileName());
ClassWriter.compile(this.compiler, file, compilable);
}
}
Aggregations