package LBJ2;
import java.util.HashMap;
import LBJ2.IR.AST;
import LBJ2.IR.ClassifierAssignment;
import LBJ2.IR.ClassifierCastExpression;
import LBJ2.IR.ClassifierExpression;
import LBJ2.IR.ClassifierExpressionList;
import LBJ2.IR.ClassifierName;
import LBJ2.IR.CodedClassifier;
import LBJ2.IR.CompositeGenerator;
import LBJ2.IR.Conjunction;
import LBJ2.IR.ConstraintDeclaration;
import LBJ2.IR.InferenceDeclaration;
import LBJ2.IR.InferenceInvocation;
import LBJ2.IR.LearningClassifierExpression;
/**
* This pass performs common subexpression elimination on classifier
* expressions except for {@link ClassifierName}s and
* {@link LearningClassifierExpression}s.
*
* @author Nick Rizzolo
**/
public class ClassifierCSE extends Pass
{
/**
* Maps each classifier expression to the cannonical name that will
* represent it.
**/
private HashMap expressionToName;
/**
* Instantiates a pass that runs on an entire <code>AST</code>.
*
* @param ast The program to run this pass on.
**/
public ClassifierCSE(AST ast) { super(ast); }
/**
* Looks up the given expression in {@link #expressionToName}, returning
* a new {@link ClassifierName} if there was a name associated with it or
* <code>null</code> otherwise. In the case that a name was not already
* associated with the given expression, its own name is set up in
* association with it, with the following exceptions.
* {@link ClassifierName}s are excluded from the map since they are already
* merely names. {@link LearningClassifierExpression}s are also excluded,
* since each learning classifier expression should represent a separate
* and independent learned function even if its specification is identical
* to some other learning classifier.
*
* @param ce The expression to look up.
**/
private ClassifierName lookup(ClassifierExpression ce) {
ClassifierName cached = (ClassifierName) expressionToName.get(ce);
if (cached == null) {
if (!(ce instanceof ClassifierName)
&& !(ce instanceof ClassifierCastExpression)
&& !(ce instanceof LearningClassifierExpression)) {
cached =
new ClassifierName(ce.name.toString(), ce.line, ce.byteOffset);
cached.name = cached.referent;
cached.returnType = ce.returnType;
cached.argument = ce.argument;
cached.singleExampleCache = ce.singleExampleCache;
expressionToName.put(ce, cached);
}
return null;
}
ClassifierName result = (ClassifierName) cached.clone();
result.line = cached.line;
result.byteOffset = cached.byteOffset;
result.returnType = cached.returnType;
result.argument = cached.argument;
result.singleExampleCache = cached.singleExampleCache;
return result;
}
/**
* Runs this pass on all nodes of the indicated type.
*
* @param ast The node to process.
**/
public void run(AST ast) {
expressionToName = new HashMap();
runOnChildren(ast);
expressionToName = null;
}
/**
* Runs this pass on all nodes of the indicated type.
*
* @param ca The node to process.
**/
public void run(ClassifierAssignment ca) {
ca.expression.runPass(this);
ClassifierName name = lookup(ca.expression);
if (name != null) {
name.name = ca.expression.name;
name.returnType = ca.expression.returnType;
name.singleExampleCache = ca.expression.singleExampleCache;
ca.expression = name;
SemanticAnalysis.representationTable.put(name.name.toString(), name);
}
}
/**
* Runs this pass on all nodes of the indicated type.
*
* @param cce The node to process.
**/
public void run(ClassifierCastExpression cce) {
cce.expression.runPass(this);
ClassifierName name = lookup(cce.expression);
if (name != null) {
if (cce.expression.name.toString().indexOf("$$") == -1) {
name.name = cce.expression.name;
name.returnType = cce.expression.returnType;
name.singleExampleCache = cce.expression.singleExampleCache;
SemanticAnalysis.representationTable.put(name.name.toString(), name);
}
else SemanticAnalysis.representationTable.remove(cce.name.toString());
cce.expression = name;
}
}
/**
* Runs this pass on all nodes of the indicated type.
*
* @param cc The node to process.
**/
public void run(CodedClassifier cc) {
}
/**
* Runs this pass on all nodes of the indicated type.
*
* @param cg The node to process.
**/
public void run(CompositeGenerator cg) {
for (ClassifierExpressionList.ClassifierExpressionListIterator I =
cg.components.listIterator();
I.hasNext(); ) {
ClassifierExpression ce = I.nextItem();
ce.runPass(this);
ClassifierName name = lookup(ce);
if (name != null) {
SemanticAnalysis.representationTable.remove(ce.name.toString());
I.set(name);
}
}
}
/**
* Runs this pass on all nodes of the indicated type.
*
* @param c The node to process.
**/
public void run(Conjunction c) {
c.left.runPass(this);
ClassifierName name = lookup(c.left);
if (name != null) {
SemanticAnalysis.representationTable.remove(c.left.name.toString());
c.left = name;
}
c.right.runPass(this);
name = lookup(c.right);
if (name != null) {
SemanticAnalysis.representationTable.remove(c.right.name.toString());
c.right = name;
}
}
/**
* Runs this pass on all nodes of the indicated type.
*
* @param i The node to process.
**/
public void run(InferenceInvocation i) {
}
/**
* Runs this pass on all nodes of the indicated type.
*
* @param lce The node to process.
**/
public void run(LearningClassifierExpression lce) {
ClassifierName name;
if (lce.labeler != null) {
lce.labeler.runPass(this);
name = lookup(lce.labeler);
if (name != null) {
SemanticAnalysis.representationTable
.remove(lce.labeler.name.toString());
lce.labeler = name;
}
}
lce.extractor.runPass(this);
name = lookup(lce.extractor);
if (name != null) {
SemanticAnalysis.representationTable
.remove(lce.extractor.name.toString());
lce.extractor = name;
}
}
/**
* Runs this pass on all nodes of the indicated type.
*
* @param c The node to process.
**/
public void run(ConstraintDeclaration c) {
}
/**
* Runs this pass on all nodes of the indicated type.
*
* @param i The node to process.
**/
public void run(InferenceDeclaration i) {
}
}