package de.gaalop.maple;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.tree.CommonTreeNodeStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import de.gaalop.Notifications;
import de.gaalop.cfg.AssignmentNode;
import de.gaalop.cfg.BlockEndNode;
import de.gaalop.cfg.BreakNode;
import de.gaalop.cfg.ColorNode;
import de.gaalop.cfg.ControlFlowGraph;
import de.gaalop.cfg.ControlFlowVisitor;
import de.gaalop.cfg.EmptyControlFlowVisitor;
import de.gaalop.cfg.EndNode;
import de.gaalop.cfg.ExpressionStatement;
import de.gaalop.cfg.IfThenElseNode;
import de.gaalop.cfg.LoopNode;
import de.gaalop.cfg.Macro;
import de.gaalop.cfg.Node;
import de.gaalop.cfg.SequentialNode;
import de.gaalop.cfg.StartNode;
import de.gaalop.cfg.StoreResultNode;
import de.gaalop.dfg.BinaryOperation;
import de.gaalop.dfg.EmptyExpressionVisitor;
import de.gaalop.dfg.Equality;
import de.gaalop.dfg.Expression;
import de.gaalop.dfg.ExpressionFactory;
import de.gaalop.dfg.FloatConstant;
import de.gaalop.dfg.Inequality;
import de.gaalop.dfg.Multiplication;
import de.gaalop.dfg.MultivectorComponent;
import de.gaalop.dfg.Relation;
import de.gaalop.dfg.Subtraction;
import de.gaalop.dfg.Variable;
import de.gaalop.maple.engine.MapleEngine;
import de.gaalop.maple.engine.MapleEngineException;
import de.gaalop.maple.parser.MapleLexer;
import de.gaalop.maple.parser.MapleParser;
import de.gaalop.maple.parser.MapleTransformer;
/**
* This visitor creates code for Maple.
*/
public class MapleCfgVisitor_optAllInIf implements ControlFlowVisitor {
/**
* Simple helper visitor used to inline parts of conditional statements.
*
* @author Christian Schwinn
*
*/
private class InlineBlockVisitor extends EmptyControlFlowVisitor {
private final IfThenElseNode root;
private final Node branch;
private final Node successor;
/**
* Creates a new visitor with given root and branch.
*
* @param root root node from which to inline a branch
* @param branch first node of branch to be inlined
*/
public InlineBlockVisitor(IfThenElseNode root, Node branch) {
this.root = root;
this.branch = branch;
successor = root.getSuccessor();
}
private void replaceSuccessor(Node oldSuccessor, Node newSuccessor) {
Set<Node> predecessors = new HashSet<Node>(oldSuccessor.getPredecessors());
for (Node p : predecessors) {
p.replaceSuccessor(oldSuccessor, newSuccessor);
}
}
@Override
public void visit(IfThenElseNode node) {
// we peek only to next level of nested statements
if (node == root) {
if (node.getPositive() == branch) {
if (!(branch instanceof BlockEndNode)) {
replaceSuccessor(node, branch);
}
node.getPositive().accept(this);
} else if (node.getNegative() == branch) {
if (!(branch instanceof BlockEndNode)) {
replaceSuccessor(node, branch);
}
node.getNegative().accept(this);
}
graph.removeNode(node);
}
node.getSuccessor().accept(this);
}
@Override
public void visit(BlockEndNode node) {
// this relies on the fact that nested statements are being ignored in visit(IfThenElseNode),
// otherwise successor could be the wrong one
if (node.getBase() == root) {
replaceSuccessor(node, successor);
}
}
}
private class InitializeVariablesVisitor extends EmptyControlFlowVisitor {
private final LoopNode root;
InitializeVariablesVisitor(LoopNode node) {
this.root = node;
}
@Override
public void visit(StartNode node) {
throw new IllegalStateException("This visitor is intended to be called on loop nodes only.");
}
@Override
public void visit(AssignmentNode node) {
// optimize current value of variable and add variables for coefficients in front of block
Variable variable = node.getVariable();
// optimize current value of variable and add variables for coefficients in front of block
initializeCoefficients(variable);
// optimize value in a temporary variable and add missing initializations
initializeMissingCoefficients(node);
// reset Maple binding with linear combination of variables for coefficients
resetVariable(variable);
node.getSuccessor().accept(this);
}
@Override
public void visit(LoopNode node) {
node.getBody().accept(this);
if (node != root) {
node.getSuccessor().accept(this);
}
}
}
private class UnrollLoopsVisitor extends EmptyControlFlowVisitor {
/**
* Removes break statements from the given node.
*
* @author Christian Schwinn
*
*/
private class RemoveBreakVisitor extends EmptyControlFlowVisitor {
private final IfThenElseNode root;
RemoveBreakVisitor(IfThenElseNode root) {
this.root = root;
}
@Override
public void visit(StartNode node) {
throw new IllegalStateException("This visitor is allowed to be called only on IfThenElseNodes");
}
@Override
public void visit(IfThenElseNode node) {
node.getPositive().accept(this);
node.getNegative().accept(this);
if (node != root) {
node.getSuccessor().accept(this);
}
}
@Override
public void visit(BreakNode node) {
Node successor = node.getSuccessor();
node.getGraph().removeNode(node);
successor.accept(this);
}
}
private LoopNode root;
SequentialNode firstNewNode;
boolean showWarning;
public UnrollLoopsVisitor(LoopNode root) {
this.root = root;
}
/**
* Inserts a new node before the current node.
*
* @param newNode node to be inserted before the current node
*/
private void insertNewNode(SequentialNode newNode) {
if (firstNewNode == null) {
firstNewNode = newNode;
}
root.insertBefore(newNode);
}
@Override
public void visit(StartNode node) {
throw new IllegalStateException("This visitor should be invoked on a loop node only.");
}
@Override
public void visit(AssignmentNode node) {
insertNewNode(node.copy());
node.getSuccessor().accept(this);
}
@Override
public void visit(StoreResultNode node) {
insertNewNode(node.copy());
node.getSuccessor().accept(this);
}
@Override
public void visit(LoopNode node) {
if (node == root) {
for (int i = 0; i < node.getIterations(); i++) {
node.getBody().accept(this);
}
node.getGraph().removeNode(node);
} else {
insertNewNode(node.copy());
// ignore nested loops (process them later)
node.getSuccessor().accept(this);
}
// do not visit root's successor
}
@Override
public void visit(IfThenElseNode node) {
IfThenElseNode newNode = (IfThenElseNode) node.copy();
insertNewNode(newNode);
boolean endOfLoop = node.getSuccessor() instanceof BlockEndNode;
boolean startOfLoop = false;
for (Node pred : node.getPredecessors()) {
if (pred instanceof LoopNode) {
LoopNode loop = (LoopNode) pred;
if (loop.getBody() == node) {
startOfLoop = true;
}
}
}
if (!(endOfLoop || startOfLoop)) {
showWarning = true;
}
RemoveBreakVisitor visitor = new RemoveBreakVisitor(newNode);
newNode.accept(visitor);
node.getSuccessor().accept(this);
}
@Override
public void visit(ExpressionStatement node) {
insertNewNode(node.copy());
node.getSuccessor().accept(this);
}
}
/**
* This visitor re-orders compare operations like >, <= or == to a left-hand side expression that is compared to 0.
*
* @author Christian Schwinn
*
*/
private class ReorderConditionVisitor extends EmptyExpressionVisitor {
private IfThenElseNode root;
public ReorderConditionVisitor(IfThenElseNode root) {
this.root = root;
}
private void reorderToLeft(BinaryOperation node) {
Expression left = node.getLeft();
Expression right = node.getRight();
Subtraction lhs = ExpressionFactory.subtract(left.copy(), right.copy());
Variable condition = new Variable("condition_" + conditionSuffix++);
Expression newRight = new FloatConstant(0);
try {
String assignment = generateCode(condition) + ":=" + generateCode(lhs) + ";";
engine.evaluate(assignment);
String opt = simplify(condition);
List<AssignmentNode> newNodes = parseMapleCode(graph, opt);
graph.addScalarVariable(condition);
for (AssignmentNode newAssignment : newNodes) {
if (newAssignment.getVariable() instanceof MultivectorComponent) {
MultivectorComponent mc = (MultivectorComponent) newAssignment.getVariable();
if (mc.getBladeIndex() == 0) {
AssignmentNode scalarPart = new AssignmentNode(graph, condition, newAssignment.getValue());
root.insertBefore(scalarPart);
} else {
throw new IllegalArgumentException("Condition in if-statement '" + root.getCondition()
+ "' is not scalar and cannot be evaluated.");
}
}
}
} catch (MapleEngineException e) {
throw new RuntimeException("Unable to optimize condition " + lhs + " in Maple.", e);
}
node.replaceExpression(left, condition);
node.replaceExpression(right, newRight);
node.getLeft().accept(this);
}
private boolean containsTrueOrFalse(Expression expression) {
UsedVariablesVisitor visitor = new UsedVariablesVisitor();
expression.accept(visitor);
for (Variable v : visitor.getVariables()) {
if ("true".equals(v.getName()) || "false".equals(v.getName())) {
return true;
}
}
return false;
}
/**
* Compares equalities and inequalities component-wise. Both multivectors are optimized and subtracted to get
* the components which are different. For these components, a comparison is added to the condition.
*
* @param node equality or inequality node
* @param equality whether to compare for equality or inequality (convenience to avoid instanceof checks)
*/
private void compareComponents(BinaryOperation node, boolean equality) {
Expression left = node.getLeft();
Expression right = node.getRight();
if (containsTrueOrFalse(left) || containsTrueOrFalse(right)) {
return;
}
Subtraction difference = ExpressionFactory.subtract(left.copy(), right.copy());
Variable lVar = new Variable("condition_" + conditionSuffix++);
Variable rVar = new Variable("condition_" + conditionSuffix++);
Variable diff = new Variable("__temp__");
try {
engine.evaluate(generateCode(lVar) + ":=" + generateCode(left) + ";");
engine.evaluate(generateCode(rVar) + ":=" + generateCode(right) + ";");
engine.evaluate(generateCode(diff) + ":=" + generateCode(difference) + ";");
initializeCoefficients(lVar);
initializeCoefficients(rVar);
Set<Integer> lVarCoeffs = new HashSet<Integer>();
Set<Integer> rVarCoeffs = new HashSet<Integer>();
for (MultivectorComponent comp : initializedVariables.get(lVar)) {
lVarCoeffs.add(comp.getBladeIndex());
}
for (MultivectorComponent comp : initializedVariables.get(rVar)) {
rVarCoeffs.add(comp.getBladeIndex());
}
BinaryOperation newCondition = null;
for (AssignmentNode diffOpt : optimizeVariable(graph, diff)) {
if (diffOpt.getVariable() instanceof MultivectorComponent) {
MultivectorComponent comp = (MultivectorComponent) diffOpt.getVariable();
int index = comp.getBladeIndex();
Expression lVarNew = getNewExpression(lVar, lVarCoeffs, index);
Expression rVarNew = getNewExpression(rVar, rVarCoeffs, index);
BinaryOperation comparison;
if (equality) {
comparison = new Equality(lVarNew, rVarNew);
} else {
comparison = new Inequality(lVarNew, rVarNew);
}
if (newCondition == null) {
newCondition = comparison;
} else {
newCondition = ExpressionFactory.and(newCondition, comparison);
}
}
}
root.replaceExpression(node, newCondition);
} catch (MapleEngineException e) {
throw new RuntimeException("Could not optimize (in)equality " + node + " in condition "
+ root.getCondition(), e);
}
}
private Expression getNewExpression(Variable var, Set<Integer> coeffs, int index) {
Expression newExp;
if (coeffs.contains(index)) {
newExp = new Variable(getTempVarName(var.getName(), index));
} else {
newExp = new FloatConstant(0.0f);
}
return newExp;
}
@Override
public void visit(Equality node) {
compareComponents(node, true);
}
@Override
public void visit(Inequality node) {
compareComponents(node, false);
}
@Override
public void visit(Relation node) {
reorderToLeft(node);
}
}
private Log log = LogFactory.getLog(MapleCfgVisitor_optAllInIf.class);
private static final String suffix = "_opt";
static int conditionSuffix = 0;
MapleEngine engine;
private HashMap<String, String> oldMinVal;
private HashMap<String, String> oldMaxVal;
Plugin plugin;
/** Used to distinguish normal assignments and such from a loop or if-statement where GA must be eliminated. */
private int blockDepth = 0;
private SequentialNode currentRoot;
Map<Variable, Set<MultivectorComponent>> initializedVariables = new HashMap<Variable, Set<MultivectorComponent>>();
private final List<Variable> unknownVariables = new ArrayList<Variable>();
ControlFlowGraph graph;
public MapleCfgVisitor_optAllInIf(MapleEngine engine, Plugin plugin) {
this.engine = engine;
this.plugin = plugin;
}
@Override
public void visit(StartNode startNode) {
graph = startNode.getGraph();
unknownVariables.addAll(graph.getInputVariables());
plugin.notifyStart();
startNode.getSuccessor().accept(this);
}
@Override
public void visit(AssignmentNode node) {
Variable variable = node.getVariable();
Expression value = node.getValue();
Node successor = node.getSuccessor();
UsedVariablesVisitor usedVariables = new UsedVariablesVisitor();
value.accept(usedVariables);
for (Variable var : usedVariables.getVariables()) {
if (unknownVariables.contains(var)) {
unknownVariables.add(variable);
break;
}
}
if (blockDepth > 0) {
// optimize current value of variable and add variables for coefficients in front of block
initializeCoefficients(node.getVariable());
// optimize value in a temporary variable and add missing initializations
initializeMissingCoefficients(node);
// reset Maple binding with linear combination of variables for coefficients
resetVariable(variable);
}
// perform actual calculation
assignVariable(variable, value);
if (blockDepth > 0) {
// optimize new value and reset Maple binding with linear combination of new value
assignCoefficients(node, variable);
}
// notify observers about progress (must be called before successor.accept(this))
plugin.notifyProgress();
graph.removeNode(node);
successor.accept(this);
}
void initializeCoefficients(Variable variable) {
// FIXME: multiple if-statements lead to unnecessary initialization before second if, e.g. x__0 = x__0
// TODO: must remove stuff like var_opt[i] = ...; from gaalop / cliffordperformant
List<AssignmentNode> coefficients = optimizeVariable(graph, variable);
for (AssignmentNode coefficient : coefficients) {
if (coefficient.getVariable() instanceof MultivectorComponent) {
MultivectorComponent component = (MultivectorComponent) coefficient.getVariable();
if (component.getBladeIndex() == 0 && coefficients.size() == 1) {
// check that Maple result is not of type x := 'x'
String optName = coefficient.getVariable().getName();
Variable coeffVariable = new Variable(optName.substring(0, optName.lastIndexOf(suffix)));
if (coeffVariable.equals(coefficient.getValue())) {
coefficient.setValue(new FloatConstant(0));
// throw new RuntimeException("Variable " + variable + " is not initialized in global space.");
}
}
initializeCoefficient(variable, coefficient.getValue(), component);
}
}
}
private void initializeCoefficient(Variable variable, Expression value, MultivectorComponent component) {
Variable tempVar = new Variable(getTempVarName(component));
if (initializedVariables.get(variable) == null) {
initializedVariables.put(variable, new HashSet<MultivectorComponent>());
}
Set<MultivectorComponent> initCoefficients = initializedVariables.get(variable);
if (!initCoefficients.contains(component)) {
graph.addScalarVariable(tempVar);
AssignmentNode initialization = new AssignmentNode(graph, tempVar, value);
currentRoot.insertBefore(initialization);
initCoefficients.add(component);
}
}
void initializeMissingCoefficients(AssignmentNode node) {
Variable temp = new Variable("__temp__");
assignVariable(temp, node.getValue());
List<MultivectorComponent> coefficients = getComponents(optimizeVariable(graph, temp));
for (MultivectorComponent coefficient : coefficients) {
Variable originalVariable = node.getVariable();
String optVarName = originalVariable.getName() + suffix;
MultivectorComponent originalComp = new MultivectorComponent(optVarName, coefficient.getBladeIndex());
Variable tempVar = new Variable(getTempVarName(originalComp));
if (initializedVariables.get(originalVariable) == null) {
initializedVariables.put(originalVariable, new HashSet<MultivectorComponent>());
}
Set<MultivectorComponent> initCoefficients = initializedVariables.get(originalVariable);
if (!initCoefficients.contains(originalComp)) {
graph.addScalarVariable(tempVar);
AssignmentNode initialization = new AssignmentNode(graph, tempVar, new FloatConstant(0));
currentRoot.insertBefore(initialization);
initCoefficients.add(originalComp);
}
}
}
private void assignCoefficients(AssignmentNode base, Variable variable) {
List<AssignmentNode> coefficients = optimizeVariable(graph, variable);
List<MultivectorComponent> newValues = new ArrayList<MultivectorComponent>();
for (AssignmentNode coefficient : coefficients) {
if (coefficient.getVariable() instanceof MultivectorComponent) {
MultivectorComponent mc = (MultivectorComponent) coefficient.getVariable();
newValues.add(mc);
Variable newVariable = new Variable(getTempVarName(mc));
Expression newValue = coefficient.getValue();
if (!newVariable.equals(newValue)) {
AssignmentNode newAssignment = new AssignmentNode(graph, newVariable, newValue);
base.insertBefore(newAssignment);
}
}
}
resetZeroCoefficients(base, variable, newValues);
resetVariable(variable);
}
private void resetZeroCoefficients(AssignmentNode base, Variable variable, List<MultivectorComponent> newValues) {
List<MultivectorComponent> zeroCoefficients = new ArrayList<MultivectorComponent>();
for (MultivectorComponent initCoeff : initializedVariables.get(variable)) {
if (!newValues.contains(initCoeff)) {
// this component is not part of the multivector anymore
zeroCoefficients.add(initCoeff);
}
}
for (MultivectorComponent zeroCoeff : zeroCoefficients) {
Variable newVariable = new Variable(getTempVarName(zeroCoeff));
AssignmentNode resetToZero = new AssignmentNode(graph, newVariable, new FloatConstant(0));
base.insertBefore(resetToZero);
}
}
void resetVariable(Variable variable) {
Set<MultivectorComponent> components = initializedVariables.get(variable);
if (components == null || components.size() == 0) {
throw new IllegalStateException("No components to reset for variable " + variable);
}
Expression[] products = new Expression[components.size()];
int i = 0;
for (MultivectorComponent mc : components) {
Variable coefficient = new Variable(getTempVarName(mc));
Expression blade = graph.getAlgebraDefinitionFile().getBladeExpression(mc.getBladeIndex());
Multiplication product = ExpressionFactory.product(coefficient, blade);
products[i++] = product;
}
Expression sum;
if (products.length > 1) {
sum = ExpressionFactory.sum(products);
} else {
sum = products[0];
}
assignVariable(variable, sum);
}
/**
* Extracts the {@link MultivectorComponent}s from a list of coefficients.
*
* @param coefficients nodes from the Maple parser
* @return list of multivector components
*/
private List<MultivectorComponent> getComponents(List<AssignmentNode> coefficients) {
List<MultivectorComponent> components = new ArrayList<MultivectorComponent>();
for (AssignmentNode coefficient : coefficients) {
if (coefficient.getVariable() instanceof MultivectorComponent) {
components.add((MultivectorComponent) coefficient.getVariable());
}
}
return components;
}
/**
* Translates the given variable and value to Maple syntax and executes it.
*
* @param variable
* @param value
*/
private void assignVariable(Variable variable, Expression value) {
String variableCode = generateCode(variable);
StringBuilder codeBuffer = new StringBuilder();
codeBuffer.append(variableCode);
codeBuffer.append(" := ");
codeBuffer.append(generateCode(value));
codeBuffer.append(";\n");
try {
engine.evaluate(codeBuffer.toString());
} catch (MapleEngineException e) {
throw new RuntimeException("Unable to process assignment " + variable + " := " + value + " in Maple.", e);
}
}
String generateCode(Expression expression) {
MapleDfgVisitor visitor = new MapleDfgVisitor();
expression.accept(visitor);
return visitor.getCode();
}
private String getTempVarName(MultivectorComponent component) {
return getTempVarName(component.getName(), component.getBladeIndex());
}
String getTempVarName(String variable, int index) {
return variable.replace('e', 'E').replace(suffix, "") + "__" + index;
}
@Override
public void visit(ExpressionStatement node) {
String command = generateCode(node.getExpression());
command += ";\n";
try {
engine.evaluate(command);
} catch (MapleEngineException e) {
throw new RuntimeException("Unable to simplify statement " + node + " in Maple.", e);
}
graph.removeNode(node);
node.getSuccessor().accept(this);
}
@Override
public void visit(StoreResultNode node) {
// FIXME: if this is in a branch, optimized coefficients may not be reused later (must use linear combination!)
List<AssignmentNode> newNodes = optimizeVariable(graph, node.getValue());
for (SequentialNode newNode : newNodes) {
node.insertBefore(newNode);
}
node.getSuccessor().accept(this);
}
/**
* Simplifies the given variable and parses the Maple code to return the new nodes.
*/
List<AssignmentNode> optimizeVariable(ControlFlowGraph graph, Variable v) {
String simplification = simplify(v);
log.debug("Maple simplification of " + v + ": " + simplification);
return parseMapleCode(graph, simplification);
}
/**
* Simplifies a single Expression node.
*
* @param expression The data flow graph that should be simplified
* @return The code Maple returned as the simplification.
*/
String simplify(Expression expression) {
StringBuilder codeBuffer = new StringBuilder();
codeBuffer.append("gaalop(");
codeBuffer.append(generateCode(expression));
codeBuffer.append(");\n");
try {
return engine.evaluate(codeBuffer.toString());
} catch (MapleEngineException e) {
throw new RuntimeException("Unable to apply gaalop() function on expression " + expression + " in Maple.",
e);
}
}
/**
* Parses a snippet of maple code and returns a list of CFG nodes that implement the returned maple expressions.
*
* @param graph The control flow graph the new nodes should be created in.
* @param mapleCode The code returned by Maple.
* @return A list of control flow nodes modeling the returned code.
*/
List<AssignmentNode> parseMapleCode(ControlFlowGraph graph, String mapleCode) {
oldMinVal = new HashMap<String, String>();
oldMaxVal = new HashMap<String, String>();
/* fill the Maps with the min and maxvalues from the nodes */
for (Variable v : graph.getInputVariables()) {
if (v.getMinValue() != null)
oldMinVal.put(v.getName(), v.getMinValue());
if (v.getMaxValue() != null)
oldMaxVal.put(v.getName(), v.getMaxValue());
}
MapleLexer lexer = new MapleLexer(new ANTLRStringStream(mapleCode));
MapleParser parser = new MapleParser(new CommonTokenStream(lexer));
try {
MapleParser.program_return result = parser.program();
MapleTransformer transformer = new MapleTransformer(new CommonTreeNodeStream(result.getTree()));
return transformer.script(graph, oldMinVal, oldMaxVal);
} catch (RecognitionException e) {
throw new RuntimeException(e);
}
}
@Override
public void visit(IfThenElseNode node) {
if (blockDepth == 0) {
currentRoot = node;
}
Expression condition = node.getCondition();
UsedVariablesVisitor usedVariables = new UsedVariablesVisitor();
condition.accept(usedVariables);
boolean unknown = false;
for (Variable var : usedVariables.getVariables()) {
if (unknownVariables.contains(var)) {
unknown = true;
break;
}
}
if (!unknown) {
// try to evaluate condition to true or false
String evalb = "evalb(" + generateCode(condition) + ");";
try {
String result = engine.evaluate(evalb);
log.debug("evalb result for condition " + condition + ": " + result);
if ("true\n".equals(result)) {
InlineBlockVisitor inliner = new InlineBlockVisitor(node, node.getPositive());
node.accept(inliner);
node.getPositive().accept(this);
} else if ("false\n".equals(result)) {
InlineBlockVisitor inliner = new InlineBlockVisitor(node, node.getNegative());
node.accept(inliner);
node.getNegative().accept(this);
} else {
unknown = true;
}
} catch (MapleEngineException e) {
e.printStackTrace();
unknown = true;
}
}
if (unknown) {
// condition contains unknown variables or evalb has failed to evaluate to true or false
handleUnknownBranches(node, condition);
node.getSuccessor().accept(this);
}
}
private void handleUnknownBranches(IfThenElseNode node, Expression condition) {
ReorderConditionVisitor reorder = new ReorderConditionVisitor(node);
condition.accept(reorder);
blockDepth++;
node.getPositive().accept(this);
node.getNegative().accept(this);
blockDepth--;
if (blockDepth == 0) {
initializedVariables.clear();
}
}
@Override
public void visit(LoopNode node) {
if (node.getIterations() > 0) {
UnrollLoopsVisitor ulv = new UnrollLoopsVisitor(node);
node.accept(ulv);
if (ulv.showWarning) {
Notifications.addWarning("Make sure that termination conditions for unroll-loops are "
+ "always at beginning or end of a loop.\n"
+ "Otherwise, partial loop bodies cannot be unrolled.");
}
ulv.firstNewNode.accept(this);
} else {
if (blockDepth == 0) {
currentRoot = node;
}
InitializeVariablesVisitor visitor = new InitializeVariablesVisitor(node);
node.accept(visitor);
blockDepth++;
node.getBody().accept(this);
blockDepth--;
if (blockDepth == 0) {
initializedVariables.clear();
}
node.getSuccessor().accept(this);
}
}
@Override
public void visit(BreakNode node) {
// nothing to do
}
@Override
public void visit(BlockEndNode node) {
// nothing to do
}
@Override
public void visit(EndNode endNode) {
}
@Override
public void visit(Macro node) {
throw new IllegalStateException("Macros should have been inlined.");
}
@Override
public void visit(ColorNode node) {
node.getSuccessor().accept(this);
}
}