package dyvilx.tools.compiler.ast.classes.metadata;

import dyvil.lang.Name;
import dyvil.reflect.Modifiers;
import dyvilx.tools.compiler.ast.classes.ClassBody;
import dyvilx.tools.compiler.ast.classes.IClass;
import dyvilx.tools.compiler.ast.context.IContext;
import dyvilx.tools.compiler.ast.field.IField;
import dyvilx.tools.compiler.ast.field.IProperty;
import dyvilx.tools.compiler.ast.header.IClassCompilableList;
import dyvilx.tools.compiler.ast.header.ICompilableList;
import dyvilx.tools.compiler.ast.member.MemberKind;
import dyvilx.tools.compiler.ast.method.IMethod;
import dyvilx.tools.compiler.ast.type.IType;
import dyvilx.tools.compiler.ast.type.builtin.Types;
import dyvilx.tools.compiler.backend.classes.ClassWriter;
import dyvilx.tools.compiler.backend.exception.BytecodeException;
import dyvilx.tools.compiler.util.Markers;
import dyvilx.tools.parsing.marker.MarkerList;

public class ExtensionMetadata implements IClassMetadata
{
	private final IClass theClass;

	public ExtensionMetadata(IClass theClass)
	{
		this.theClass = theClass;
	}

	@Override
	public MemberKind getKind()
	{
		return MemberKind.CLASS;
	}

	// Phases

	@Override
	public void resolveTypesHeader(MarkerList markers, IContext context)
	{
		this.theClass.setPosition(this.theClass.getSuperType().getPosition());
		this.theClass.setName(
			Name.fromQualified("extension_" + this.theClass.getSuperType().getInternalName().replace('/', '_')));
	}

	@Override
	public void resolveTypesBody(MarkerList markers, IContext context)
	{
		final ClassBody body = this.theClass.getBody();

		for (IField field : body.fields())
		{
			markers.add(Markers.semanticError(field.getPosition(), "extension.field.invalid"));
		}

		for (IProperty property : body.properties())
		{
			markers.add(Markers.semanticError(property.getPosition(), "extension.property.invalid"));
		}

		final IType superType = this.theClass.getSuperType();
		for (IMethod method : body.methods())
		{
			method.setThisType(superType);
			method.getAttributes().addFlag(Modifiers.EXTENSION);
		}
	}

	@Override
	public void cleanup(ICompilableList compilableList, IClassCompilableList classCompilableList)
	{
		this.theClass.setSuperType(Types.OBJECT);
		this.theClass.setTypeParameters(null);
	}

	// Compilation

	@Override
	public void write(ClassWriter writer) throws BytecodeException
	{

	}
}

@@ -1218,32 +1218,56 @@
 t context)%0A%09%7B%0A%09%09
+final IType superType = 
 this.theClass.se
@@ -1268,20 +1268,26 @@
 ass.
-setPosition(
+getSuperType();%0A%09%09
 this
@@ -1292,36 +1292,45 @@
 is.theClass.
-getS
+setPosition(s
 uperType
 ().getPositi
@@ -1313,26 +1313,24 @@
 on(superType
-()
 .getPosition
@@ -1362,110 +1362,623 @@
 ame(
-%0A%09%09%09Name.fromQualified(%22extension_%22 + this.theClass.getSuperType().getInternalName().replace('/', '_')
+mangleName(superType));%0A%09%7D%0A%0A%09private static Name mangleName(IType type)%0A%09%7B%0A%09%09final String signature = type.getSignature();%0A%09%09final StringBuilder mangled = new StringBuilder(%22extension_%22);%0A%0A%09%09for (int i = 0; i %3C signature.length(); i++)%0A%09%09%7B%0A%09%09%09final char c = signature.charAt(i);%0A%09%09%09switch (c)%0A%09%09%09%7B%0A%09%09%09case '%3C':%0A%09%09%09%09mangled.append(%22_$__%22);%0A%09%09%09%09break;%0A%09%09%09case '%3E':%0A%09%09%09%09mangled.append(%22__$_%22);%0A%09%09%09%09break;%0A%09%09%09case ',':%0A%09%09%09case ';':%0A%09%09%09%09mangled.append(%22__%22);%0A%09%09%09%09break;%0A%09%09%09case '/':%0A%09%09%09%09mangled.append(%22_%22);%0A%09%09%09%09break;%0A%09%09%09default:%0A%09%09%09%09mangled.append(c);%0A%09%09%09%09break;%0A%09%09%09%7D%0A%09%09%7D%0A%0A%09%09return Name.fromQualified(mangled.toString(
 ));%0A

Improve Extension Class Name Mangling