/* * Created on Apr 19, 2005 * * TODO To change the template for this generated file go to * Window - Preferences - Java - Code Style - Code Templates */ package cs227b.teamIago.resolver; import java.util.ArrayList; /** * @author Nick * * TODO To change the template for this generated type comment go to * Window - Preferences - Java - Code Style - Code Templates */ public class Substitution { protected ArrayList associations; /** * */ public Substitution() { associations = new ArrayList(); } public Substitution (Substitution copy) { associations = new ArrayList(); for (int i = 0; i < copy.associations.size(); i++) { associations.add(copy.associations.get(i)); } } public Substitution (Substitution copy, Variable v, Expression sub) { this(copy); Association a = new Association(v,sub); associations.add(a); } public boolean assigns(Variable v) { return (maps(v) != null); } public Expression maps(Variable v) { for (int i = 0; i < associations.size(); i++) { Association a = (Association) associations.get(i); if (a.assigns(v)) return a.getSub(); } return null; } public void addAssocNoIdentCheck(Variable v, Expression sub) { Expression exp = maps(v); if (exp == null) { Association a = new Association(v,sub); associations.add(a); return; } else if (exp.equals(sub)) return; else { /* System.err.println("No match: variable reassigned in substitution \"" + v.toString() + " -> " + sub.toString() + "\""); */ return; } } public void addAssoc(Variable v, Expression sub) { if (v.equals(sub)) return; addAssocNoIdentCheck(v,sub); } public boolean refines(Substitution other) { // return associations.containsAll(other.associations); // This was a vast oversimplification. // For instance, {X->a,Y->b} should be a // refinement of {X->a, Y->W}, but by the logic // above, since it isn't {X->a, Y->W, W->b} then // the second isn't a refinement of the first. for (int i = 0; i < other.associations.size(); ++i) { Association vSub = (Association)other.associations.get(i); Variable v = vSub.getVar(); Variable v2 = vSub.getVar(); Expression vA, vB; while (true) { vA = maps(v); if (vA == null) { vA = v; break; } else if (vA instanceof Variable) v = (Variable) vA; else break; } while (true) { vB = other.maps(v); if (vB == null) { vB = v; break; } else if (vB instanceof Variable) v = (Variable) vB; else break; } if (vB instanceof Variable) continue; else if (!vB.equals(vA)) return false; } return true; } /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ public boolean equals(Object match) { if (! (match instanceof Substitution)) return false; Substitution other = (Substitution) match; if (!refines(other)) return false; if (!other.refines(this)) return false; return true; } public boolean empty() { return (associations.size() == 0); } /* (non-Javadoc) * @see java.lang.Object#toString() */ public String toString() { // TODO Auto-generated method stub String s = new String(); s = s + "[ "; for (int i = 0; i < associations.size(); i++) { s += associations.get(i).toString(); if ( i < associations.size() - 1) s += ", "; } s += " ]"; return s; } // Apply the substitution to itself repeatedly // until every mapping maps out of the domain of // the substitution public Substitution factor() { Substitution psi = new Substitution(); for (int i = 0; i < associations.size(); ++i) { Association vSub = (Association)associations.get(i); Variable v; Expression mapNew, mapOld;; mapNew = mapOld = v = vSub.getVar(); while (true) { mapNew = mapOld.apply(this); if (mapNew == null) { mapNew = mapOld; break; } else if (mapNew.equals(mapOld)) break; else mapOld = mapNew; } psi.addAssoc(v,mapNew); } return psi; } // Restict a substitution to only the variables // occurring in expression e public Substitution restrict(Expression e) { Substitution psi = factor(); ExpList domain = e.getVars(); Substitution sigma = new Substitution(); for (int i= 0; i < domain.size(); ++i) { Variable v = (Variable) domain.get(i); Expression map = psi.maps(v); sigma.addAssoc(v,map); } return sigma; } public Substitution apply(Substitution other) { Substitution otherC = other.factor(); Substitution psi = new Substitution(); for (int i=0; i < associations.size(); ++i) { Association vSub = (Association) associations.get(i); Variable v = vSub.getVar(); Expression oldMap = vSub.getSub(); psi.addAssoc(v,oldMap.apply(otherC)); } for (int i=0; i < other.associations.size(); ++i) { Association vSub = (Association) other.associations.get(i); Variable v = vSub.getVar(); Expression oldMap = vSub.getSub(); if (!psi.assigns(v)) psi.addAssoc(v,oldMap.apply(otherC)); } return psi; } }