All Downloads are FREE. Search and download functionalities are using the official Maven repository.

prompto.compiler.ClassFile Maven / Gradle / Ivy

The newest version!
package prompto.compiler;

import java.io.OutputStream;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class ClassFile {
	
	ConstantsPool constantsPool;
	ClassConstant thisClass;
	ClassConstant superClass;
	List interfaces = new ArrayList<>();
	List fields = new ArrayList<>();
	List methods = new ArrayList<>();
	List attributes = new ArrayList<>();
	InnerClassesAttribute innerClasses = null;
	BootstrapMethodsAttribute bootstrapMethods = null;
	
	int accessFlags = Tags.ACC_SUPER | Modifier.PUBLIC;
	
	public ClassFile(Type thisClassName) {
		this.thisClass = new ClassConstant(thisClassName);
	}
	
	@Override
	public String toString() {
		return thisClass.toString();
	}

	public ConstantsPool getConstantsPool() {
		return constantsPool;
	}
	
	public ClassConstant getThisClass() {
		return thisClass;
	}
	
	public ClassConstant getSuperClass() {
		return superClass;
	}
	
	public void setSuperClass(ClassConstant superClass) {
		this.superClass = superClass;
	}
	
	public int getModifiers() {
		return accessFlags;
	}

	public void addModifier(int modifier) {
		if((modifier & Modifier.INTERFACE)!=0)
			accessFlags &= ~Tags.ACC_SUPER;
		accessFlags |= modifier;
	}
	
	public boolean isInterface() {
		return (accessFlags & Modifier.INTERFACE)!=0;
	}

	
	public void addInterface(Type type) {
		addInterface(new ClassConstant(type));
	}
	
	public void addInterface(ClassConstant interFace) {
		interfaces.add(interFace);
	}

	public void addField(FieldInfo field) {
		fields.add(field);
	}

	public MethodInfo newMethod(String name, Descriptor.Method descriptor) {
		MethodInfo method = new MethodInfo(this, name, descriptor);
		methods.add(method);
		return method;
	}
	
	public List getMethods() {
		return methods;
	}

	public boolean hasMethod(String methodName) {
		for(MethodInfo m : methods) {
			if(methodName.equals(m.getName().getValue()))
				return true;
		}
		return false;
	}
	
	public FieldInfo getFieldInfo(String fieldName) {
		return fields.stream().filter(f->f.getName().toString().equals(fieldName)).findFirst().orElse(null);
	}

	public void setEnclosingMethod(MethodInfo method) {
		System.err.println("TODO: setEnclosingMethod");
	}

	
	public void addAttribute(IAttribute attribute) {
		attributes.add(attribute);
	}
	
	public void addInnerClass(ClassFile classFile) {
		InnerClassInfo info = new InnerClassInfo(classFile, getThisClass());
		addInnerClass(info);
	}
	
	public void addInnerClass(InnerClassInfo info) {
		if(innerClasses==null) {
			innerClasses = new InnerClassesAttribute();
			attributes.add(innerClasses);
		}
		innerClasses.addInnerClass(info);
	}
	
	public void addBootstrapMethod(BootstrapMethod method) {
		if(bootstrapMethods==null) {
			bootstrapMethods = new BootstrapMethodsAttribute();
			attributes.add(bootstrapMethods);
		}
		bootstrapMethods.addBootstrapMethod(method);
	}
	
	public Collection getInnerClasses() {
		List list = new ArrayList<>();
		if(innerClasses!=null) 
			innerClasses.getClasses().forEach((ici)->
				list.add(ici.getClassFile()));
		return list;
	}



	public void writeTo(OutputStream o) throws CompilerException {
		constantsPool = registerConstants();
		ByteWriter writer = new ByteWriter(o);
		writeTo(writer);
	}

	private ConstantsPool registerConstants() {
		ConstantsPool pool = new ConstantsPool();
		thisClass.register(pool);
		if(superClass==null)
			superClass = new ClassConstant(Object.class);
		superClass.register(pool);
		interfaces.forEach((s)-> 
			s.register(pool));
		fields.forEach((f)-> 
			f.register(pool));
		methods.forEach((m)-> 
			m.register(pool));
		attributes.forEach((a)-> 
			a.register(pool));
		return pool;
	}

	private void writeTo(ByteWriter writer) throws CompilerException {
		/*
		ClassFile {
		    u4             magic;
		    u2             minor_version;
		    u2             major_version;
		    u2             constant_pool_count;
		    cp_info        constant_pool[constant_pool_count-1];
		    u2             access_flags;
		    u2             this_class;
		    u2             super_class;
		    u2             interfaces_count;
		    u2             interfaces[interfaces_count];
		    u2             fields_count;
		    field_info     fields[fields_count];
		    u2             methods_count;
		    method_info    methods[methods_count];
		    u2             attributes_count;
		    attribute_info attributes[attributes_count];
		}		
		*/
		writer.writeU4(Tags.MAGIC);
		writer.writeU2(Tags.MINOR);
		writer.writeU2(Tags.MAJOR);
		constantsPool.write(writer);
		writer.writeU2(accessFlags);
		writer.writeU2(thisClass.getIndexInConstantPool());
		writer.writeU2(superClass.getIndexInConstantPool());
		writer.writeU2(interfaces.size());
		interfaces.forEach((i)->
			writer.writeU2(i.getIndexInConstantPool()));
		writer.writeU2(fields.size());
		fields.forEach((f)->
			f.writeTo(writer));
		writer.writeU2(methods.size());
		methods.forEach((m)->
			m.writeTo(writer));
		writer.writeU2(attributes.size());
		attributes.forEach((a)->
			a.writeTo(writer));
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy