WALA/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/rewrite/AstConstantFolder.java

86 lines
2.9 KiB
Java

package com.ibm.wala.cast.tree.rewrite;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import com.ibm.wala.cast.tree.CAstControlFlowMap;
import com.ibm.wala.cast.tree.CAstEntity;
import com.ibm.wala.cast.tree.CAstNode;
import com.ibm.wala.cast.tree.CAstNodeTypeMap;
import com.ibm.wala.cast.tree.CAstSourcePositionMap;
import com.ibm.wala.cast.tree.impl.CAstImpl;
import com.ibm.wala.cast.tree.impl.DelegatingEntity;
import com.ibm.wala.cast.tree.rewrite.CAstBasicRewriter.NonCopyingContext;
import com.ibm.wala.cast.tree.rewrite.CAstRewriter.Rewrite;
import com.ibm.wala.cast.util.AstConstantCollector;
import com.ibm.wala.util.collections.EmptyIterator;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.collections.Pair;
public class AstConstantFolder {
static class AssignSkipContext extends NonCopyingContext {
private Set<CAstNode> skip = HashSetFactory.make();
}
public static CAstEntity fold(CAstEntity ce) {
Map<String,Object> constants = AstConstantCollector.collectConstants(ce);
if (constants.isEmpty()) {
return ce;
} else {
Rewrite nce = new CAstCloner(new CAstImpl(), new AssignSkipContext(), true) {
@Override
protected CAstNode copyNodes(CAstNode root, CAstControlFlowMap cfg, NonCopyingContext c,
Map<Pair<CAstNode, NoKey>, CAstNode> nodeMap) {
if (root.getKind() == CAstNode.ASSIGN) {
((AssignSkipContext)c).skip.add(root.getChild(0));
}
if (root.getKind() == CAstNode.VAR && constants.containsKey(root.getChild(0).getValue()) && ! ((AssignSkipContext)c).skip.contains(root)) {
return Ast.makeConstant(constants.get(root.getChild(0).getValue()));
} else {
return super.copyNodes(root, cfg, c, nodeMap);
}
}
}.rewrite(ce.getAST(), ce.getControlFlow(), ce.getSourceMap(), ce.getNodeTypeMap(), ce.getAllScopedEntities(), ce.getArgumentDefaults());
return new DelegatingEntity(ce) {
@Override
public CAstNode getAST() {
return nce.newRoot();
}
@Override
public CAstControlFlowMap getControlFlow() {
return nce.newCfg();
}
@Override
public CAstSourcePositionMap getSourceMap() {
return nce.newPos();
}
@Override
public CAstNodeTypeMap getNodeTypeMap() {
return nce.newTypes();
}
@Override
public Map<CAstNode, Collection<CAstEntity>> getAllScopedEntities() {
return nce.newChildren();
}
@Override
public Iterator<CAstEntity> getScopedEntities(CAstNode construct) {
Collection<CAstEntity> children = nce.newChildren().get(construct);
return children==null? EmptyIterator.instance(): children.iterator();
}
};
}
}
}