CollectionCompiler.java
package com.mackenziehigh.autumn.lang.compiler.compilers;
import com.mackenziehigh.autumn.resources.Finished;
import java.util.LinkedList;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.TypeInsnNode;
/**
* This class generates bytecode that creates a linked-list with predefined elements.
*
* @author Mackenzie High
*/
@Finished("2014/07/12")
abstract class CollectionCompiler<T>
{
/**
* This method is invoked in order to compile an element in the list.
* This method must add bytecode, which produces the element's value, to the code().
* The element must be an object reference.
* In other words, this method must auto-box the element, if needed.
*
* @param element is the element to compile.
*/
public abstract void compile(T element);
/**
* This method provides the list that stores the generated bytecode.
*
* @return the aforedescribed list.
*/
public abstract InsnList code();
/**
* This method returns the class representation of the collection type.
*
* @return the type of collection be created.
*/
public Class type()
{
return LinkedList.class;
}
/**
* This method generates bytecode that executes the elements of a given list
* and then adds the results of the executions to a newly created linked list.
*
* <p>
* After the bytecode is executed, a new linked-list is the top-element of the operand-stack.
* </p>
*
* @param elements are the elements to of the new list to generate bytecode for.
*/
public final void compile(final Iterable<T> elements)
{
final String type = Type.getInternalName(type());
// -----------------------------------------------------------------------------------------
// Precondition of the Operand-Stack: .....
// -----------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------
// Postcondition of the Operand-Stack: [collection]
// .....
// -----------------------------------------------------------------------------------------
code().add(new TypeInsnNode(Opcodes.NEW, type));
// -----------------------------------------------------------------------------------------
// Postcondition of the Operand-Stack: [collection]
// [collection]
// .....
// -----------------------------------------------------------------------------------------
code().add(new InsnNode(Opcodes.DUP));
// -----------------------------------------------------------------------------------------
// Postcondition of the Operand-Stack: [collection]
// .....
// -----------------------------------------------------------------------------------------
code().add(new MethodInsnNode(Opcodes.INVOKESPECIAL, type, "<init>", "()V"));
// Compile each element.
for (T element : elements)
{
// -------------------------------------------------------------------------------------
// Postcondition of the Operand-Stack: [collection]
// [collection]
// .....
// -------------------------------------------------------------------------------------
code().add(new InsnNode(Opcodes.DUP));
// -------------------------------------------------------------------------------------
// Postcondition of the Operand-Stack: [element]
// [collection]
// [collection]
// .....
// -------------------------------------------------------------------------------------
compile(element);
// -------------------------------------------------------------------------------------
// Postcondition of the Operand-Stack: [boolean]
// [collection]
// .....
// -------------------------------------------------------------------------------------
code().add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, type, "add", "(Ljava/lang/Object;)Z"));
// -------------------------------------------------------------------------------------
// Postcondition of the Operand-Stack: [collection]
// .....
// -------------------------------------------------------------------------------------
code().add(new InsnNode(Opcodes.POP));
}
// -----------------------------------------------------------------------------------------
// Condition of the Operand-Stack: [collection]
// .....
// -----------------------------------------------------------------------------------------
}
}