-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
455 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<parent> | ||
<artifactId>gaalop</artifactId> | ||
<groupId>de.gaalop</groupId> | ||
<version>1.0.0</version> | ||
</parent> | ||
<name>Gaalop Julia Plugin</name> | ||
<modelVersion>4.0.0</modelVersion> | ||
<groupId>de.gaalop</groupId> | ||
<artifactId>codegen-julia</artifactId> | ||
<version>1.0.0</version> | ||
<dependencies> | ||
<dependency> | ||
<groupId>de.gaalop</groupId> | ||
<artifactId>api</artifactId> | ||
<version>1.0.0</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>de.gaalop</groupId> | ||
<artifactId>codegen-cpp</artifactId> | ||
<version>1.0.0</version> | ||
<scope>compile</scope> | ||
</dependency> | ||
</dependencies> | ||
</project> |
50 changes: 50 additions & 0 deletions
50
codegen-julia/src/main/java/de/gaalop/julia/JuliaCodeGenerator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package de.gaalop.julia; | ||
|
||
import de.gaalop.CodeGenerator; | ||
import de.gaalop.OutputFile; | ||
import de.gaalop.cfg.ControlFlowGraph; | ||
|
||
import java.nio.charset.StandardCharsets; | ||
import java.util.Set; | ||
import java.util.Collections; | ||
|
||
public enum JuliaCodeGenerator implements CodeGenerator { | ||
|
||
INSTANCE; | ||
|
||
@Override | ||
public Set<OutputFile> generate(ControlFlowGraph in) { | ||
String code = generateCode(in); | ||
|
||
String filename = generateFilename(in); | ||
|
||
OutputFile sourceFile = new OutputFile(filename, code, StandardCharsets.UTF_8); | ||
return Collections.singleton(sourceFile); | ||
} | ||
|
||
private String generateFilename(ControlFlowGraph in) { | ||
String filename = "gaalop.txt"; | ||
if (in.getSource() != null) { | ||
filename = in.getSource().getName(); | ||
int lastDotIndex = filename.lastIndexOf('.'); | ||
if (lastDotIndex != -1) { | ||
filename = filename.substring(0, lastDotIndex); | ||
} | ||
filename += ".txt"; | ||
} | ||
return filename; | ||
} | ||
|
||
/** | ||
* Generates source code for a control dataflow graph. | ||
* | ||
* @param in | ||
* @return | ||
*/ | ||
private String generateCode(ControlFlowGraph in) { | ||
JuliaVisitor visitor = new JuliaVisitor(); | ||
in.accept(visitor); | ||
return visitor.getCode(); | ||
} | ||
|
||
} |
307 changes: 307 additions & 0 deletions
307
codegen-julia/src/main/java/de/gaalop/julia/JuliaVisitor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,307 @@ | ||
package de.gaalop.julia; | ||
|
||
import de.gaalop.cfg.*; | ||
import de.gaalop.cpp.OperatorPriority; | ||
import de.gaalop.dfg.*; | ||
import org.apache.commons.logging.Log; | ||
import org.apache.commons.logging.LogFactory; | ||
|
||
import java.util.*; | ||
|
||
|
||
/** | ||
* This class implements the CFG and DFG visitor that generate Julia code. | ||
* Heavily inspired by CppVisitor.java | ||
*/ | ||
|
||
public class JuliaVisitor implements ControlFlowVisitor, ExpressionVisitor { | ||
|
||
protected Log log = LogFactory.getLog(JuliaVisitor.class); | ||
|
||
protected StringBuilder code; | ||
private ControlFlowGraph graph; | ||
|
||
public JuliaVisitor() { | ||
code = new StringBuilder(); | ||
} | ||
|
||
// Stolen from CppVisitor.java. Keeping the order of the variables deterministic is a good idea. | ||
private List<Variable> sortVariables(Set<Variable> inputVariables) { | ||
List<Variable> variables = new ArrayList<Variable>(inputVariables); | ||
Comparator<Variable> comparator = new Comparator<Variable>() { | ||
|
||
@Override | ||
public int compare(Variable o1, Variable o2) { | ||
return o1.getName().compareToIgnoreCase(o2.getName()); | ||
} | ||
}; | ||
|
||
Collections.sort(variables, comparator); | ||
return variables; | ||
} | ||
|
||
private void not_implemented(String nodeType) { | ||
throw new UnsupportedOperationException("The Julia backend does not support \"" + nodeType + "\"!"); | ||
} | ||
|
||
private void macro_error() { | ||
throw new UnsupportedOperationException("Macros should have been removed already!"); | ||
} | ||
|
||
protected void addBinaryInfix(BinaryOperation op, String operator) { | ||
addChild(op, op.getLeft()); | ||
code.append(operator); | ||
addChild(op, op.getRight()); | ||
} | ||
|
||
protected 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(StartNode node) { | ||
graph = node.getGraph(); | ||
int bladeCount = graph.getAlgebraDefinitionFile().getBladeCount(); | ||
|
||
List<Variable> localVariables = sortVariables(graph.getLocalVariables()); | ||
List<Variable> inputParameters = sortVariables(graph.getInputVariables()); | ||
|
||
code.append("function calculate("); | ||
|
||
for (Variable var : inputParameters) { | ||
code.append(var.getName()); | ||
code.append(", "); | ||
} | ||
|
||
for (Variable var : localVariables) { | ||
code.append(var.getName()); | ||
code.append(", "); | ||
} | ||
|
||
// Remove the last ", " if we have any local variables. | ||
if (graph.getLocalVariables().size() > 0) { | ||
code.setLength(code.length() - 2); | ||
} | ||
|
||
code.append(")\n"); | ||
|
||
node.getSuccessor().accept(this); | ||
} | ||
|
||
@Override | ||
public void visit(AssignmentNode node) { | ||
code.append("\t"); | ||
node.getVariable().accept(this); | ||
code.append(" = "); | ||
node.getValue().accept(this); | ||
code.append(";"); | ||
|
||
if (node.getVariable() instanceof MultivectorComponent) { | ||
code.append(" # "); | ||
MultivectorComponent component = (MultivectorComponent) node.getVariable(); | ||
code.append(node.getGraph().getAlgebraDefinitionFile().getBladeString(component.getBladeIndex())); | ||
} | ||
|
||
code.append("\n"); | ||
node.getSuccessor().accept(this); | ||
} | ||
|
||
@Override | ||
public void visit(StoreResultNode node) { | ||
node.getSuccessor().accept(this); | ||
} | ||
|
||
@Override | ||
public void visit(IfThenElseNode node) { | ||
not_implemented("IfThenElseNode"); | ||
} | ||
|
||
@Override | ||
public void visit(BlockEndNode node) { | ||
not_implemented("BlockEndNode"); | ||
} | ||
|
||
@Override | ||
public void visit(LoopNode node) { | ||
not_implemented("LoopNode"); | ||
} | ||
|
||
@Override | ||
public void visit(BreakNode node) { | ||
not_implemented("BreakNode"); | ||
} | ||
|
||
@Override | ||
public void visit(Macro node) { | ||
macro_error(); | ||
} | ||
|
||
@Override | ||
public void visit(ExpressionStatement node) { | ||
not_implemented("ExpressionStatement"); | ||
} | ||
|
||
@Override | ||
public void visit(EndNode node) { | ||
code.append("end\n"); | ||
} | ||
|
||
@Override | ||
public void visit(ColorNode node) { | ||
node.getSuccessor().accept(this); | ||
} | ||
|
||
@Override | ||
public void visit(Subtraction node) { | ||
addBinaryInfix(node, " - "); | ||
} | ||
|
||
@Override | ||
public void visit(Addition node) { | ||
addBinaryInfix(node, " + "); | ||
} | ||
|
||
@Override | ||
public void visit(Division node) { | ||
addBinaryInfix(node, " / "); | ||
} | ||
|
||
@Override | ||
public void visit(InnerProduct node) { | ||
not_implemented("InnerProduct"); | ||
} | ||
|
||
@Override | ||
public void visit(Multiplication node) { | ||
addBinaryInfix(node, " * "); | ||
} | ||
|
||
@Override | ||
public void visit(MathFunctionCall node) { | ||
String functionName = ""; | ||
switch (node.getFunction()) { | ||
case SQRT: | ||
functionName = "sqrt"; | ||
break; | ||
case ABS: | ||
functionName = "abs"; | ||
break; | ||
case COS: | ||
functionName = "cos"; | ||
break; | ||
case SIN: | ||
functionName = "sin"; | ||
break; | ||
case EXP: | ||
functionName = "exp"; | ||
break; | ||
default: | ||
not_implemented("specific MathFunctionCall"); | ||
} | ||
code.append(functionName); | ||
code.append("("); | ||
node.getOperand().accept(this); | ||
code.append(")"); | ||
} | ||
|
||
@Override | ||
public void visit(Variable node) { | ||
code.append(node.getName()); | ||
} | ||
|
||
@Override | ||
public void visit(MultivectorComponent node) { | ||
//code.append(node.getName().replace(suffix, "")); | ||
code.append(node.getName()); | ||
code.append("["); | ||
code.append(node.getBladeIndex() + 1); // Indices start at 1 in Julia | ||
code.append("]"); | ||
} | ||
|
||
@Override | ||
public void visit(Exponentiation node) { | ||
code.append("("); | ||
node.getLeft().accept(this); | ||
code.append(") ^ ("); | ||
node.getRight().accept(this); | ||
code.append(")"); | ||
} | ||
|
||
@Override | ||
public void visit(FloatConstant node) { | ||
code.append(Double.toString(node.getValue())); | ||
code.append("f0"); | ||
} | ||
|
||
@Override | ||
public void visit(OuterProduct node) { | ||
not_implemented("OuterProduct"); | ||
} | ||
|
||
@Override | ||
public void visit(BaseVector node) { | ||
not_implemented("BaseVector"); | ||
} | ||
|
||
@Override | ||
public void visit(Negation node) { | ||
code.append("(-"); | ||
node.getOperand().accept(this); | ||
code.append(")"); | ||
} | ||
|
||
@Override | ||
public void visit(Reverse node) { | ||
not_implemented("Reverse"); | ||
} | ||
|
||
@Override | ||
public void visit(LogicalOr node) { | ||
not_implemented("LogicalOr"); | ||
} | ||
|
||
@Override | ||
public void visit(LogicalAnd node) { | ||
not_implemented("LogicalAnd"); | ||
} | ||
|
||
@Override | ||
public void visit(LogicalNegation node) { | ||
not_implemented("LogicalNegation"); | ||
} | ||
|
||
@Override | ||
public void visit(Equality node) { | ||
not_implemented("Equality"); | ||
} | ||
|
||
@Override | ||
public void visit(Inequality node) { | ||
not_implemented("Inequality"); | ||
} | ||
|
||
@Override | ||
public void visit(Relation relation) { | ||
not_implemented("Relation"); | ||
} | ||
|
||
@Override | ||
public void visit(FunctionArgument node) { | ||
macro_error(); | ||
} | ||
|
||
@Override | ||
public void visit(MacroCall node) { | ||
macro_error(); | ||
} | ||
|
||
public String getCode() { | ||
return code.toString(); | ||
} | ||
} |
Oops, something went wrong.