diff options
| author | bculkin2442 <bjculkin@mix.wvu.edu> | 2016-04-18 13:04:01 -0400 |
|---|---|---|
| committer | bculkin2442 <bjculkin@mix.wvu.edu> | 2016-04-18 13:04:01 -0400 |
| commit | 24f3ce54983348e1aa0229d5c08b3fe99d739d40 (patch) | |
| tree | 948277e2519e2dffcb3fa2b2bf2ee649c21c2e3c /dice-lang/src/main/java/bjc/dicelang/ast/optimization/OperationCondenser.java | |
| parent | 9ce39956fa1702f157c347dc4b8807d9b5dd2185 (diff) | |
Added operation condensing
Diffstat (limited to 'dice-lang/src/main/java/bjc/dicelang/ast/optimization/OperationCondenser.java')
| -rw-r--r-- | dice-lang/src/main/java/bjc/dicelang/ast/optimization/OperationCondenser.java | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/optimization/OperationCondenser.java b/dice-lang/src/main/java/bjc/dicelang/ast/optimization/OperationCondenser.java new file mode 100644 index 0000000..f41a3ef --- /dev/null +++ b/dice-lang/src/main/java/bjc/dicelang/ast/optimization/OperationCondenser.java @@ -0,0 +1,105 @@ +package bjc.dicelang.ast.optimization; + +import bjc.dicelang.ast.nodes.DiceASTType; +import bjc.dicelang.ast.nodes.IDiceASTNode; +import bjc.dicelang.ast.nodes.OperatorDiceNode; +import bjc.utils.data.IHolder; +import bjc.utils.data.Identity; +import bjc.utils.funcdata.ITree; +import bjc.utils.funcdata.TopDownTransformResult; +import bjc.utils.funcdata.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 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 ASSIGN: + case GROUP: + case LET: + return TopDownTransformResult.PASSTHROUGH; + default: + throw new UnsupportedOperationException( + "Attempted to traverse unknown operator " + node); + } + } + + 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; + } +} |
