summaryrefslogtreecommitdiff
path: root/dice-lang/src/bjc/dicelang/v1/ast/optimization
diff options
context:
space:
mode:
authorbjculkin <bjculkin@WIT-136XG42.wvu-ad.wvu.edu>2017-02-27 10:08:50 -0500
committerbjculkin <bjculkin@WIT-136XG42.wvu-ad.wvu.edu>2017-02-27 10:08:50 -0500
commit79ee129fc0d36ad10bceb942262f2842419c030c (patch)
treed1298fdb8b81726f4b9012d7a29c3029a55a3aa7 /dice-lang/src/bjc/dicelang/v1/ast/optimization
parentc50a0744269ce22604c0604cc69e6d5e5ce8a3fc (diff)
Pacakge reorganization
Diffstat (limited to 'dice-lang/src/bjc/dicelang/v1/ast/optimization')
-rw-r--r--dice-lang/src/bjc/dicelang/v1/ast/optimization/ArithmeticCollapser.java49
-rw-r--r--dice-lang/src/bjc/dicelang/v1/ast/optimization/ConstantCollapser.java90
-rw-r--r--dice-lang/src/bjc/dicelang/v1/ast/optimization/IOptimizationPass.java34
-rw-r--r--dice-lang/src/bjc/dicelang/v1/ast/optimization/OperationCondenser.java106
-rw-r--r--dice-lang/src/bjc/dicelang/v1/ast/optimization/package-info.java7
5 files changed, 286 insertions, 0 deletions
diff --git a/dice-lang/src/bjc/dicelang/v1/ast/optimization/ArithmeticCollapser.java b/dice-lang/src/bjc/dicelang/v1/ast/optimization/ArithmeticCollapser.java
new file mode 100644
index 0000000..0d10a07
--- /dev/null
+++ b/dice-lang/src/bjc/dicelang/v1/ast/optimization/ArithmeticCollapser.java
@@ -0,0 +1,49 @@
+package bjc.dicelang.v1.ast.optimization;
+
+import java.util.function.BinaryOperator;
+
+import bjc.dicelang.v1.ast.DiceASTUtils;
+import bjc.dicelang.v1.ast.nodes.DiceASTType;
+import bjc.dicelang.v1.ast.nodes.IDiceASTNode;
+import bjc.dicelang.v1.ast.nodes.ILiteralDiceNode;
+import bjc.dicelang.v1.ast.nodes.IntegerLiteralNode;
+import bjc.dicelang.v1.ast.nodes.OperatorDiceNode;
+import bjc.utils.data.ITree;
+import bjc.utils.funcdata.IList;
+import bjc.utils.data.Tree;
+
+class ArithmeticCollapser {
+ private BinaryOperator<Integer> reducer;
+ private OperatorDiceNode type;
+
+ public ArithmeticCollapser(BinaryOperator<Integer> reducr,
+ OperatorDiceNode typ) {
+ reducer = reducr;
+ this.type = typ;
+ }
+
+ public ITree<IDiceASTNode> collapse(
+ IList<ITree<IDiceASTNode>> children) {
+ boolean allConstant = children.allMatch((subtree) -> {
+ return subtree.transformHead((node) -> {
+ if (node.getType() == DiceASTType.LITERAL) {
+ return ((ILiteralDiceNode) node).canOptimize();
+ }
+
+ return false;
+ });
+ });
+
+ if (!allConstant) {
+ return new Tree<>(type, children);
+ }
+
+ int initState = DiceASTUtils.literalToInteger(children.first());
+
+ return children.tail().reduceAux(initState,
+ (currentNode, state) -> {
+ return reducer.apply(state,
+ DiceASTUtils.literalToInteger(currentNode));
+ }, (state) -> new Tree<>(new IntegerLiteralNode(state)));
+ }
+}
diff --git a/dice-lang/src/bjc/dicelang/v1/ast/optimization/ConstantCollapser.java b/dice-lang/src/bjc/dicelang/v1/ast/optimization/ConstantCollapser.java
new file mode 100644
index 0000000..89f17db
--- /dev/null
+++ b/dice-lang/src/bjc/dicelang/v1/ast/optimization/ConstantCollapser.java
@@ -0,0 +1,90 @@
+package bjc.dicelang.v1.ast.optimization;
+
+import bjc.dicelang.v1.ComplexDice;
+import bjc.dicelang.v1.ast.DiceASTUtils;
+import bjc.dicelang.v1.ast.nodes.IDiceASTNode;
+import bjc.dicelang.v1.ast.nodes.IntegerLiteralNode;
+import bjc.dicelang.v1.ast.nodes.OperatorDiceNode;
+import bjc.utils.data.ITree;
+import bjc.utils.funcdata.IList;
+import bjc.utils.data.Tree;
+
+/**
+ * Collapses operations with constants to constants
+ *
+ * @author ben
+ *
+ */
+public class ConstantCollapser implements IOptimizationPass {
+ private static final ArithmeticCollapser additionCollapser = new ArithmeticCollapser(
+ (left, right) -> left + right, OperatorDiceNode.ADD);
+
+ private static final ArithmeticCollapser divideCollapser = new ArithmeticCollapser(
+ (left, right) -> left / right, OperatorDiceNode.DIVIDE);
+
+ private static final ArithmeticCollapser multiplyCollapser = new ArithmeticCollapser(
+ (left, right) -> left * right, OperatorDiceNode.MULTIPLY);
+
+ private static final ArithmeticCollapser subtractCollapser = new ArithmeticCollapser(
+ (left, right) -> left - right, OperatorDiceNode.SUBTRACT);
+
+ private static final ArithmeticCollapser compoundCollapser = new ArithmeticCollapser(
+ (left, right) -> Integer.parseInt(
+ Integer.toString(left) + Integer.toString(left)),
+ OperatorDiceNode.COMPOUND);
+
+ @Override
+ public ITree<IDiceASTNode> optimizeLeaf(IDiceASTNode leafNode) {
+ // We don't do anything special here
+ return new Tree<>(leafNode);
+ }
+
+ @Override
+ public ITree<IDiceASTNode> optimizeOperator(IDiceASTNode operator,
+ IList<ITree<IDiceASTNode>> children) {
+ if (!operator.isOperator()) {
+ return new Tree<>(operator, children);
+ }
+
+ switch ((OperatorDiceNode) operator) {
+ case ADD:
+ return additionCollapser.collapse(children);
+ case DIVIDE:
+ return divideCollapser.collapse(children);
+ case MULTIPLY:
+ return multiplyCollapser.collapse(children);
+ case SUBTRACT:
+ return subtractCollapser.collapse(children);
+ case COMPOUND:
+ return compoundCollapser.collapse(children);
+ case GROUP:
+ if (children.getSize() != 2) {
+ return new Tree<>(operator, children);
+ }
+
+ ComplexDice dice = new ComplexDice(
+ DiceASTUtils.literalToExpression(
+ children.getByIndex(0)),
+ DiceASTUtils.literalToExpression(
+ children.getByIndex(1)));
+
+ if (dice.canOptimize()) {
+ return new Tree<>(
+ new IntegerLiteralNode(dice.optimize()));
+ }
+
+ return new Tree<>(operator, children);
+ case ARRAY:
+ if (children.getSize() != 1) {
+ return new Tree<>(operator, children);
+ }
+
+ return children.first();
+ case ASSIGN:
+ case LET:
+ default:
+ // We don't optimize these operators
+ return new Tree<>(operator, children);
+ }
+ }
+}
diff --git a/dice-lang/src/bjc/dicelang/v1/ast/optimization/IOptimizationPass.java b/dice-lang/src/bjc/dicelang/v1/ast/optimization/IOptimizationPass.java
new file mode 100644
index 0000000..58943fa
--- /dev/null
+++ b/dice-lang/src/bjc/dicelang/v1/ast/optimization/IOptimizationPass.java
@@ -0,0 +1,34 @@
+package bjc.dicelang.v1.ast.optimization;
+
+import bjc.dicelang.v1.ast.nodes.IDiceASTNode;
+import bjc.utils.data.ITree;
+import bjc.utils.funcdata.IList;
+
+/**
+ * Represents a pass of optimizations over a dice AST
+ *
+ * @author ben
+ *
+ */
+public interface IOptimizationPass {
+ /**
+ * Optimize a leaf in the tree
+ *
+ * @param leafNode
+ * The node to optimize
+ * @return The optimized node
+ */
+ public ITree<IDiceASTNode> optimizeLeaf(IDiceASTNode leafNode);
+
+ /**
+ * Optimize an operator in an AST node
+ *
+ * @param operator
+ * The operator being optimized
+ * @param children
+ * The children of the operator being optimized
+ * @return The optimized node
+ */
+ public ITree<IDiceASTNode> optimizeOperator(IDiceASTNode operator,
+ IList<ITree<IDiceASTNode>> children);
+}
diff --git a/dice-lang/src/bjc/dicelang/v1/ast/optimization/OperationCondenser.java b/dice-lang/src/bjc/dicelang/v1/ast/optimization/OperationCondenser.java
new file mode 100644
index 0000000..4a34167
--- /dev/null
+++ b/dice-lang/src/bjc/dicelang/v1/ast/optimization/OperationCondenser.java
@@ -0,0 +1,106 @@
+package bjc.dicelang.v1.ast.optimization;
+
+import bjc.dicelang.v1.ast.nodes.DiceASTType;
+import bjc.dicelang.v1.ast.nodes.IDiceASTNode;
+import bjc.dicelang.v1.ast.nodes.OperatorDiceNode;
+import bjc.utils.data.IHolder;
+import bjc.utils.data.ITree;
+import bjc.utils.data.Identity;
+import bjc.utils.data.TopDownTransformResult;
+import bjc.utils.data.Tree;
+
+/**
+ * Condenses chained operations into a single level
+ *
+ * @author ben
+ *
+ */
+public class OperationCondenser {
+ /**
+ * Condense chained similiar operations into a single level
+ *
+ * @param ast
+ * The AST to condense
+ * @return The condensed AST
+ */
+ public static ITree<IDiceASTNode> condense(ITree<IDiceASTNode> ast) {
+ return ast.topDownTransform(OperationCondenser::pickNode,
+ OperationCondenser::doCondense);
+ }
+
+ private static ITree<IDiceASTNode> doCondense(
+ ITree<IDiceASTNode> ast) {
+ OperatorDiceNode operation = ast
+ .transformHead((node) -> (OperatorDiceNode) node);
+
+ IHolder<Boolean> canCondense = new Identity<>(true);
+
+ ast.doForChildren((child) -> {
+ if (canCondense.getValue()) {
+ canCondense.replace(child.transformHead((node) -> {
+ if (node.getType() == DiceASTType.OPERATOR) {
+ if (operation.equals(node)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ return true;
+ }));
+ }
+ });
+
+ if (!canCondense.getValue()) {
+ return ast;
+ }
+
+ ITree<IDiceASTNode> condensedAST = new Tree<>(operation);
+
+ ast.doForChildren((child) -> {
+ if (child.getHead().getType() == DiceASTType.OPERATOR) {
+ child.doForChildren((subChild) -> {
+ condensedAST.addChild(subChild);
+ });
+ } else {
+ condensedAST.addChild(child);
+ }
+ });
+
+ return condensedAST;
+ }
+
+ private static TopDownTransformResult pickNode(IDiceASTNode node) {
+ switch (node.getType()) {
+ case LITERAL:
+ return TopDownTransformResult.SKIP;
+ case OPERATOR:
+ return pickOperator((OperatorDiceNode) node);
+ case VARIABLE:
+ return TopDownTransformResult.SKIP;
+ default:
+ throw new UnsupportedOperationException(
+ "Attempted to traverse unknown node type " + node);
+ }
+ }
+
+ private static TopDownTransformResult pickOperator(
+ OperatorDiceNode node) {
+ switch (node) {
+ case ADD:
+ case MULTIPLY:
+ case SUBTRACT:
+ case DIVIDE:
+ case COMPOUND:
+ return TopDownTransformResult.PUSHDOWN;
+ case ARRAY:
+ case ASSIGN:
+ case GROUP:
+ case LET:
+ return TopDownTransformResult.PASSTHROUGH;
+ default:
+ throw new UnsupportedOperationException(
+ "Attempted to traverse unknown operator " + node);
+ }
+ }
+}
diff --git a/dice-lang/src/bjc/dicelang/v1/ast/optimization/package-info.java b/dice-lang/src/bjc/dicelang/v1/ast/optimization/package-info.java
new file mode 100644
index 0000000..04727d7
--- /dev/null
+++ b/dice-lang/src/bjc/dicelang/v1/ast/optimization/package-info.java
@@ -0,0 +1,7 @@
+/**
+ * Contains optimizations on dice ASTs
+ *
+ * @author ben
+ *
+ */
+package bjc.dicelang.v1.ast.optimization; \ No newline at end of file