// Path: src/main/java/jasm/util/Pair.java
// public class Pair<FIRST,SECOND> {
// 	protected final FIRST first;
// 	protected final SECOND second;	
// 	
// 	public Pair(FIRST f, SECOND s) {
// 		first=f;
// 		second=s;			
// 	}		
// 	
// 	public FIRST first() { return first; }
// 	public SECOND second() { return second; }
// 	
// 	public int hashCode() {
// 		int fhc = first == null ? 0 : first.hashCode();
// 		int shc = second == null ? 0 : second.hashCode();
// 		return fhc ^ shc; 
// 	}
// 		
// 	public boolean equals(Object o) {
// 		if(o instanceof Pair) {
// 			Pair<FIRST, SECOND> p = (Pair<FIRST, SECOND>) o;
// 			boolean r = false;
// 			if(first != null) { r = first.equals(p.first()); }
// 			else { r = p.first() == first; }
// 			if(second != null) { r &= second.equals(p.second()); }
// 			else { r &= p.second() == second; }
// 			return r;				
// 		}
// 		return false;
// 	}
// 	
// 	public String toString() {
// 		String fstr = first != null ? first.toString() : "null";
// 		String sstr = second != null ? second.toString() : "null";
// 		return "(" + fstr + ", " + sstr + ")";
// 	}
// }


import jasm.util.Pair;
import java.util.*;

     */
	public static JvmType.Reference substitute(JvmType.Reference type, Map<String,JvmType.Reference> binding) {
		if (type instanceof JvmType.Variable) {
			// Ok, we've reached a type variable, so we can now bind this with
			// what we already have.
			JvmType.Variable v = (JvmType.Variable) type;
			JvmType.Reference r = binding.get(v.variable());
			if(r == null) {
				// if the variable is not part of the binding, then we simply do
                // not do anything with it.
				return v;
			} else {
				return r;
			}
		} else if(type instanceof JvmType.Wildcard) {
			JvmType.Wildcard wc = (JvmType.Wildcard) type;
			JvmType.Reference lb = wc.lowerBound();
			JvmType.Reference ub = wc.upperBound();
			if(lb != null) { lb = substitute(lb,binding); }
			if(ub != null) { ub = substitute(ub,binding); }
			return new JvmType.Wildcard(lb,ub);
		} else if(type instanceof JvmType.Array) {
			JvmType.Array at = (JvmType.Array) type;
			if(at.element() instanceof JvmType.Reference) {
				return new JvmType.Array(substitute((JvmType.Reference) at.element(),binding));
			} else {
				return type;
			}
		} else if(type instanceof JvmType.Clazz) {
			JvmType.Clazz ct = (JvmType.Clazz) type;

// Path: src/main/java/jasm/util/Pair.java
// public class Pair<FIRST,SECOND> {
// 	protected final FIRST first;
// 	protected final SECOND second;	
// 	
// 	public Pair(FIRST f, SECOND s) {
// 		first=f;
// 		second=s;			
// 	}		
// 	
// 	public FIRST first() { return first; }
// 	public SECOND second() { return second; }
// 	
// 	public int hashCode() {
// 		int fhc = first == null ? 0 : first.hashCode();
// 		int shc = second == null ? 0 : second.hashCode();
// 		return fhc ^ shc; 
// 	}
// 		
// 	public boolean equals(Object o) {
// 		if(o instanceof Pair) {
// 			Pair<FIRST, SECOND> p = (Pair<FIRST, SECOND>) o;
// 			boolean r = false;
// 			if(first != null) { r = first.equals(p.first()); }
// 			else { r = p.first() == first; }
// 			if(second != null) { r &= second.equals(p.second()); }
// 			else { r &= p.second() == second; }
// 			return r;				
// 		}
// 		return false;
// 	}
// 	
// 	public String toString() {
// 		String fstr = first != null ? first.toString() : "null";
// 		String sstr = second != null ? second.toString() : "null";
// 		return "(" + fstr + ", " + sstr + ")";
// 	}
// }


// Path: src/main/java/jasm/lang/JvmTypes.java
import jasm.util.Pair;
import java.util.*;

     */
	public static JvmType.Reference substitute(JvmType.Reference type, Map<String,JvmType.Reference> binding) {
		if (type instanceof JvmType.Variable) {
			// Ok, we've reached a type variable, so we can now bind this with
			// what we already have.
			JvmType.Variable v = (JvmType.Variable) type;
			JvmType.Reference r = binding.get(v.variable());
			if(r == null) {
				// if the variable is not part of the binding, then we simply do
                // not do anything with it.
				return v;
			} else {
				return r;
			}
		} else if(type instanceof JvmType.Wildcard) {
			JvmType.Wildcard wc = (JvmType.Wildcard) type;
			JvmType.Reference lb = wc.lowerBound();
			JvmType.Reference ub = wc.upperBound();
			if(lb != null) { lb = substitute(lb,binding); }
			if(ub != null) { ub = substitute(ub,binding); }
			return new JvmType.Wildcard(lb,ub);
		} else if(type instanceof JvmType.Array) {
			JvmType.Array at = (JvmType.Array) type;
			if(at.element() instanceof JvmType.Reference) {
				return new JvmType.Array(substitute((JvmType.Reference) at.element(),binding));
			} else {
				return type;
			}
		} else if(type instanceof JvmType.Clazz) {
			JvmType.Clazz ct = (JvmType.Clazz) type;

			ArrayList<Pair<String,List<JvmType.Reference>>> ncomponents = new ArrayList();
