package com.sun.tools.javac.code;
import static com.sun.tools.javac.code.Kinds.VAR;
import java.util.Iterator;
import com.sun.tools.javac.code.Symbol.VarSymbol;
import com.sun.tools.javac.code.Type.ClassType;
import com.sun.tools.javac.comp.Attr;
import com.sun.tools.javac.comp.AttrContext;
import com.sun.tools.javac.comp.Env;
import com.sun.tools.javac.comp.Resolve;
import com.sun.tools.javac.tree.JCTree.JCArrayAccess;
import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
import com.sun.tools.javac.tree.JCTree.JCIdent;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Name;
/**
* Interfaces for performing type, region, and effect substitutions.
*
* @author Rob Bocchino
*/
public class Substitute {
/**
* Class representing a substitution
* @author Rob Bocchino
*
* @param <Elt> Type of element to substitute into
* @param <From> Type of parameter
* @param <To> Type of argument
*/
public static abstract class Subst<Elt,From,To> {
/**
* A basic substitution
* @param elt Element on which to perform substitution
* @param from Parameter of substitution
* @param to Argument of substitution
* @return elt after substituting arg for param
*/
public abstract Elt basic(Elt elt, From from, To to);
/**
* Iterated substitution. The default implemementation is to apply
* 'basic' for each pair of elements from 'from' and 'to'.
* @param elt Element on which to perform substitution
* @param from Parameters of substitution
* @param to Arguments of substitution
* @return elt after substituting args for params
*/
public Elt iterable(Elt elt, Iterable<From> from, Iterable<To> to) {
Iterator<From> fromIterator = from.iterator();
Iterator<To> toIterator = to.iterator();
while (fromIterator.hasNext() && toIterator.hasNext()) {
elt = basic (elt, fromIterator.next(), toIterator.next());
}
return elt;
}
}
/**
* Perform substitution using iterable collections of params and args.
* @param subst Substitution operation
* @param elt Element on which to perform substitution
* @param from Params of substitution
* @param to Args of substitution
* @return Result of substitution
*/
public static <Elt,From,To> Elt
iterable(Subst<Elt,From,To> subst, Elt elt,
Iterable<From> from, Iterable<To> to)
{
return subst.iterable(elt,from,to);
}
/**
* Substitute single param/arg pair into a list
*/
public static <Elt,From,To> List<Elt> intoList
(Subst<Elt,From,To> subst, List<Elt> elts, From from, To to)
{
ListBuffer<Elt> lb = ListBuffer.lb();
for (Elt elt : elts) {
lb.append(subst.basic(elt, from, to));
}
return lb.toList();
}
/**
* Substitute iterable collections of params and args into list
*/
public static <Elt,From,To> List<Elt> listIntoList
(Subst<Elt,From,To> subst, List<Elt> elts, List<From> from, List<To> to)
{
ListBuffer<Elt> lb = ListBuffer.lb();
for (Elt elt : elts) {
lb.append(subst.iterable(elt, from, to));
}
return lb.toList();
}
/** Interface representing RPL substitutions */
public interface SubstRPLs<T extends SubstRPLs<T>> {
/** Substitute 'to' RPLs for 'from' RPLs */
public T substRPLParams(Iterable<RPL> from, Iterable<RPL> to);
/** Do TR param substitutions implied by type bindings */
public T substTRParams(Iterable<Type> from, Iterable<Type> to);
/** Substitute an RPL for a variable */
public T substRPLForVar(VarSymbol from, RPL to);
}
/** Apply RPL and TR param substitution to an element */
public static <T extends SubstRPLs<T>> T allRPLParams
(T elt, Type t)
{
if (elt == null || t == null) return elt;
T result = elt.substRPLParams(t.tsym.type.getRPLArguments(),
t.getRPLArguments());
result = result.substTRParams(t.tsym.type.getTypeArguments(),
t.getTypeArguments());
return result;
}
/** Interface representing 'as member of' translation */
public interface AsMemberOf<T extends AsMemberOf<T>> {
/** 'this' as a member of type t */
public T asMemberOf(Type t, Types types);
}
/** Interface representing index substitution */
public interface SubstIndex<T extends SubstIndex<T>> {
/** 'this' after substituting index */
public T substIndex(VarSymbol from, JCExpression to);
}
/** Interface representing substitution of RPL for var */
public interface SubstRPLForVar<T extends SubstRPLForVar<T>> {
/** 'this' after substituting RPL for var */
public T substRPLForVar(VarSymbol from, RPL to);
}
}