use of dyvilx.tools.compiler.backend.MethodWriter in project Dyvil by Dyvil.
the class CodeClass method write.
@Override
public void write(ClassWriter writer) throws BytecodeException {
// Header
String signature = this.getSignature();
String superClass = null;
String[] interfaces = this.getInterfaceArray();
if (this.superType != null) {
superClass = this.superType.getInternalName();
}
final long flags = ModifierUtil.getFlags(this);
int modifiers = ModifierUtil.getJavaModifiers(flags);
if ((modifiers & Modifiers.INTERFACE) == 0) {
modifiers |= ASMConstants.ACC_SUPER;
}
writer.visit(ClassFormat.CLASS_VERSION, modifiers, this.getInternalName(), signature, superClass, interfaces);
// Source
writer.visitSource(this.getHeader().getName() + DyvilFileType.DYVIL_EXTENSION, null);
if (this.enclosingClass != null) {
this.writeInnerClassInfo(writer);
}
// Annotations
this.writeAnnotations(writer, flags);
if (this.superType != null) {
IClass iclass = this.superType.getTheClass();
if (iclass != null) {
iclass.writeInnerClassInfo(writer);
}
}
if (this.interfaces != null) {
for (IType type : this.interfaces) {
final IClass iclass = type.getTheClass();
if (iclass != null) {
iclass.writeInnerClassInfo(writer);
}
}
}
// Compute Trait Classes
final Set<IClass> traitClasses;
if ((modifiers & Modifiers.INTERFACE) == 0) {
traitClasses = new ArraySet<>();
this.traitInit = !fillTraitClasses(this, traitClasses, true) && !traitClasses.isEmpty();
} else {
traitClasses = null;
}
for (int i = 0; i < this.compilableCount; i++) {
this.compilables[i].write(writer);
}
this.metadata.write(writer);
this.writeClassParameters(writer);
if (this.body != null) {
this.body.write(writer);
}
this.metadata.writePost(writer);
// Create the static <clinit> method
MethodWriter initWriter = new MethodWriterImpl(writer, writer.visitMethod(Modifiers.STATIC, "<clinit>", "()V", null, null));
initWriter.visitCode();
this.writeStaticInit(initWriter);
initWriter.visitEnd(Types.VOID);
if (traitClasses == null || traitClasses.isEmpty()) {
return;
}
// Create the virtual <traitinit> method
initWriter = new MethodWriterImpl(writer, writer.visitMethod(Modifiers.PROTECTED, TraitMetadata.INIT_NAME, "()V", null, null));
initWriter.visitCode();
initWriter.setLocalType(0, this.getInternalName());
for (IClass traitClass : traitClasses) {
final String internal = traitClass.getInternalName();
// Load 'this'
initWriter.visitVarInsn(Opcodes.ALOAD, 0);
// Invoke the static <traitinit> method of the trait class
initWriter.visitMethodInsn(Opcodes.INVOKESTATIC, internal, TraitMetadata.INIT_NAME, "(L" + internal + ";)V", true);
}
initWriter.visitInsn(Opcodes.RETURN);
initWriter.visitEnd();
}
use of dyvilx.tools.compiler.backend.MethodWriter in project Dyvil by Dyvil.
the class CodeConstructor method write.
@Override
public void write(ClassWriter writer) throws BytecodeException {
final long flags = ModifierUtil.getFlags(this);
final MethodWriter methodWriter = new MethodWriterImpl(writer, writer.visitMethod(ModifierUtil.getJavaModifiers(flags), "<init>", this.getDescriptor(), this.getSignature(), this.getInternalExceptions()));
// Write Modifiers and Annotations
ModifierUtil.writeModifiers(methodWriter, flags);
this.attributes.write(methodWriter);
if (this.hasModifier(Modifiers.DEPRECATED) && this.getAnnotation(Deprecation.DEPRECATED_CLASS) == null) {
methodWriter.visitAnnotation(Deprecation.DYVIL_EXTENDED, true).visitEnd();
}
// Write Parameters
methodWriter.setThisType(this.enclosingClass.getInternalName());
this.parameters.write(methodWriter);
// Write Code
final Label start = new Label();
final Label end = new Label();
methodWriter.visitCode();
methodWriter.visitLabel(start);
if (this.initializerCall != null) {
this.initializerCall.writeExpression(methodWriter, Types.VOID);
}
if (this.initializerCall == null || this.initializerCall.isSuper()) {
this.enclosingClass.writeClassInit(methodWriter);
}
if (this.value != null) {
this.value.writeExpression(methodWriter, Types.VOID);
}
methodWriter.visitLabel(end);
methodWriter.visitEnd(Types.VOID);
// Write Local Variable Data
methodWriter.visitLocalVariable("this", 'L' + this.enclosingClass.getInternalName() + ';', null, start, end, 0);
this.parameters.writeLocals(methodWriter, start, end);
}
use of dyvilx.tools.compiler.backend.MethodWriter in project Dyvil by Dyvil.
the class IParameter method writeParameter.
default void writeParameter(MethodWriter writer) {
final AttributeList annotations = this.getAttributes();
final IType type = this.getInternalType();
final long flags = ModifierUtil.getFlags(this);
final int index = this.getIndex();
final int localIndex = writer.localCount();
this.setLocalIndex(localIndex);
// Add the ACC_VARARGS modifier if necessary
final int javaModifiers = ModifierUtil.getJavaModifiers(flags) | (this.isVarargs() ? Modifiers.ACC_VARARGS : 0);
writer.visitParameter(localIndex, this.getQualifiedLabel(), type, javaModifiers);
// Annotations
final AnnotatableVisitor visitor = (desc, visible) -> writer.visitParameterAnnotation(index, desc, visible);
if (annotations != null) {
annotations.write(visitor);
}
ModifierUtil.writeModifiers(visitor, flags);
IType.writeAnnotations(type, writer, TypeReference.newFormalParameterReference(index), "");
}
use of dyvilx.tools.compiler.backend.MethodWriter in project Dyvil by Dyvil.
the class IParameter method writeDefaultValue.
default void writeDefaultValue(ClassWriter writer) {
final IValue value = this.getValue();
assert value != null;
final ICallableMember method = this.getMethod();
final IType type = this.getType();
final String name;
final int access;
if (method == null) {
name = "init$paramDefault$" + this.getInternalName();
access = Modifiers.STATIC;
} else {
name = method.getInternalName() + "$paramDefault$" + this.getInternalName();
access = (method.getAttributes().flags() & Modifiers.MEMBER_MODIFIERS) | Modifiers.STATIC;
}
final String desc = "()" + this.getDescriptor();
final String signature = "()" + this.getSignature();
final MethodWriter mw = new MethodWriterImpl(writer, writer.visitMethod(access, name, desc, signature, null));
mw.visitCode();
value.writeExpression(mw, type);
mw.visitEnd(type);
}
use of dyvilx.tools.compiler.backend.MethodWriter in project Dyvil by Dyvil.
the class CaseClassMetadata method write.
@Override
public void write(ClassWriter writer) throws BytecodeException {
super.write(writer);
MethodWriter mw;
final String internal = this.theClass.getInternalName();
if ((this.members & EQUALS) == 0) {
mw = new MethodWriterImpl(writer, writer.visitMethod(Modifiers.PUBLIC, "equals", "(Ljava/lang/Object;)Z", null, null));
mw.setThisType(internal);
mw.visitParameter(1, "obj", Types.OBJECT, 0);
mw.visitCode();
CaseClasses.writeEquals(mw, this.theClass);
mw.visitEnd();
}
if ((this.members & HASHCODE) == 0) {
mw = new MethodWriterImpl(writer, writer.visitMethod(Modifiers.PUBLIC, "hashCode", "()I", null, null));
mw.setThisType(internal);
mw.visitCode();
CaseClasses.writeHashCode(mw, this.theClass);
mw.visitEnd();
}
if ((this.members & TOSTRING) == 0) {
mw = new MethodWriterImpl(writer, writer.visitMethod(Modifiers.PUBLIC, "toString", "()Ljava/lang/String;", null, null));
mw.setThisType(internal);
mw.visitCode();
CaseClasses.writeToString(mw, this.theClass);
mw.visitEnd();
}
}
Aggregations