package de.gaalop.maple; import de.gaalop.dfg.*; /** * Created by IntelliJ IDEA. User: Sebastian Date: 08.02.2009 Time: 17:21:49 To change this template use File | Settings | File * Templates. */ public class MapleDfgVisitor implements ExpressionVisitor { private StringBuilder codeBuffer = new StringBuilder(); private boolean cliffordMode = true; public boolean isCliffordMode() { return cliffordMode; } public void setCliffordMode(boolean cliffordMode) { this.cliffordMode = cliffordMode; } public String getCode() { return codeBuffer.toString(); } private void handleInfix(BinaryOperation op, String opcode) { codeBuffer.append("("); op.getLeft().accept(this); codeBuffer.append(' '); codeBuffer.append(opcode); codeBuffer.append(' '); op.getRight().accept(this); codeBuffer.append(")"); } @Override public void visit(Subtraction subtraction) { handleInfix(subtraction, "-"); } @Override public void visit(Addition addition) { handleInfix(addition, "+"); } @Override public void visit(Division division) { if (division.getRight().equals(new FloatConstant(0.0f))) { throw new IllegalArgumentException("Division by zero: " + division); } codeBuffer.append("subs(Id=1,"); handleInfix(division, ") &c inverse(simplify("); codeBuffer.append("))"); } @Override public void visit(InnerProduct innerProduct) { if (!cliffordMode) { throw new IllegalStateException("This visitor cannot process the inner product in non-clifford mode."); } codeBuffer.append("subs(Id=1,innerproduct("); codeBuffer.append("simplify("); innerProduct.getLeft().accept(this); codeBuffer.append("), simplify("); innerProduct.getRight().accept(this); codeBuffer.append(")))"); } @Override public void visit(Multiplication multiplication) { if (cliffordMode) { codeBuffer.append("subs(Id=1,"); handleInfix(multiplication, "&c"); codeBuffer.append(')'); } else { handleInfix(multiplication, "*"); } } @Override public void visit(MathFunctionCall mathFunctionCall) { MathFunction function = mathFunctionCall.getFunction(); if (function == MathFunction.ABS) { // Special case: abs() -> mul_abs() (see cliffordfunctions.mws) codeBuffer.append("mul_abs"); } else if (function == MathFunction.SQRT) { // Special case: sqrt() -> wurzel() (see cliffordfunctions.mws) codeBuffer.append("wurzel"); } else { codeBuffer.append(function.toString().toLowerCase()); } // additional simplification to remove 1.00000000 which causes Cliffordlib's LC to fail codeBuffer.append("(simplify("); mathFunctionCall.getOperand().accept(this); codeBuffer.append("))"); } @Override public void visit(BaseVector baseVector) { if (!cliffordMode) { throw new IllegalStateException("This visitor cannot process base vectors in non-clifford mode."); } codeBuffer.append("e").append(baseVector.getIndex()); } @Override public void visit(Negation negation) { codeBuffer.append("(-("); negation.getOperand().accept(this); codeBuffer.append("))"); } @Override public void visit(Reverse node) { codeBuffer.append("reversion("); node.getOperand().accept(this); codeBuffer.append(")"); } @Override public void visit(Variable variable) { codeBuffer.append(variable.getName()); } @Override public void visit(MultivectorComponent component) { codeBuffer.append(component.getName()); codeBuffer.append('['); codeBuffer.append(component.getBladeIndex()); codeBuffer.append(']'); } @Override public void visit(Exponentiation exponentiation) { handleInfix(exponentiation, "^"); } @Override public void visit(FloatConstant floatConstant) { // For some obscure reason, the Clifford lib cannot handle // multiplications of the following form: 1.0 &c A, where A is a multivector. // It can handle 1 &c A however. For that reason we convert all // floating point numbers that can be represented as integrals without // data loss as integrals. if (Double.compare(floatConstant.getValue(), Math.floor(floatConstant.getValue())) == 0) { codeBuffer.append((int) floatConstant.getValue()); } else { codeBuffer.append(Double.toString(floatConstant.getValue())); } } @Override public void visit(OuterProduct outerProduct) { if (!cliffordMode) { throw new IllegalStateException("This visitor cannot process the outer product in non-clifford mode."); } handleInfix(outerProduct, "&w"); } @Override public void visit(LogicalOr node) { handleInfix(node, "or"); } @Override public void visit(LogicalAnd node) { handleInfix(node, "and"); } @Override public void visit(LogicalNegation node) { codeBuffer.append("(not("); node.getOperand().accept(this); codeBuffer.append("))"); } @Override public void visit(Equality node) { handleInfix(node, "="); } @Override public void visit(Inequality node) { handleInfix(node, "<>"); } @Override public void visit(Relation relation) { handleInfix(relation, relation.getTypeString()); } @Override public void visit(FunctionArgument node) { throw new IllegalStateException("Macros should have been inlined, so function arguments are not allowed here."); } @Override public void visit(MacroCall node) { throw new IllegalStateException("Macros should have been inlined, so macro calls are not allowed here."); } }