package de.gaalop.clucalc.output; import de.gaalop.cfg.AlgebraDefinitionFile; import de.gaalop.dfg.*; /** * Creates CLUCalc code for a single expression. The code can afterwards be queried via {@link #getCode()}. */ public class DfgVisitor implements ExpressionVisitor { private StringBuilder code = new StringBuilder(); private final String optSuffix; private final String suffix; public DfgVisitor(String suffix, String optSuffix) { this.suffix = suffix; this.optSuffix = optSuffix; } public String getCode() { return code.toString(); } private void handleInfix(BinaryOperation operation, String operator, boolean withSpaces) { addChild(operation, operation.getLeft()); if (withSpaces) { code.append(' '); code.append(operator); code.append(' '); } else { code.append(operator); } addChild(operation, operation.getRight()); } private void addChild(Expression parent, Expression child) { if (OperatorPriority.hasLowerPriority(parent, child)) { code.append('('); child.accept(this); code.append(')'); } else { child.accept(this); } } @Override public void visit(Subtraction subtraction) { handleInfix(subtraction, "-", true); } @Override public void visit(Addition addition) { handleInfix(addition, "+", true); } @Override public void visit(Division division) { handleInfix(division, "/", true); } @Override public void visit(InnerProduct innerProduct) { handleInfix(innerProduct, ".", true); // throw new UnsupportedOperationException("Inner product is unsupported for code generation."); } @Override public void visit(Multiplication multiplication) { handleInfix(multiplication, "*", true); } @Override public void visit(MathFunctionCall mathFunctionCall) { code.append(mathFunctionCall.getFunction().toString()); code.append('('); mathFunctionCall.getOperand().accept(this); code.append(')'); } @Override public void visit(Variable variable) { if (variable.globalAccess()) { code.append("::"); } code.append(variable.getName().replace(optSuffix, suffix)); } @Override public void visit(MultivectorComponent component) { code.append(component.getName().replace(optSuffix, suffix)); code.append('('); code.append(component.getBladeIndex() + 1); code.append(')'); } @Override public void visit(Exponentiation exponentiation) { handleInfix(exponentiation, "^^", false); } @Override public void visit(FloatConstant floatConstant) { code.append(Double.toString(floatConstant.getValue()).replace('E', 'e')); } @Override public void visit(OuterProduct outerProduct) { handleInfix(outerProduct, "^", false); } @Override public void visit(BaseVector baseVector) { code.append(baseVector.toString()); } @Override public void visit(Negation negation) { code.append('('); code.append('-'); addChild(negation, negation.getOperand()); code.append(')'); } @Override public void visit(Reverse node) { code.append('~'); addChild(node, node.getOperand()); } @Override public void visit(LogicalOr node) { handleInfix(node, "||", true); } @Override public void visit(LogicalAnd node) { handleInfix(node, "&&", true); } @Override public void visit(LogicalNegation node) { code.append("!!"); addChild(node, node.getOperand()); } @Override public void visit(Equality node) { handleInfix(node, "==", true); } @Override public void visit(Inequality node) { handleInfix(node, "!=", true); } @Override public void visit(Relation relation) { handleInfix(relation, relation.getTypeString(), false); } @Override public void visit(FunctionArgument node) { code.append("_P("); code.append(node.getIndex()); code.append(")"); } @Override public void visit(MacroCall node) { // make sure access is always global (no restriction) code.append("::"); code.append(node.getName()); code.append("("); for (Expression arg : node.getArguments()) { arg.accept(this); code.append(", "); } if (node.getArguments().size() > 0) { code.delete(code.length() - 2, code.length()); } code.append(")"); } }