summaryrefslogtreecommitdiff
path: root/dice-lang/src
diff options
context:
space:
mode:
authorbculkin2442 <bjculkin@mix.wvu.edu>2016-04-18 13:04:01 -0400
committerbculkin2442 <bjculkin@mix.wvu.edu>2016-04-18 13:04:01 -0400
commit24f3ce54983348e1aa0229d5c08b3fe99d739d40 (patch)
tree948277e2519e2dffcb3fa2b2bf2ee649c21c2e3c /dice-lang/src
parent9ce39956fa1702f157c347dc4b8807d9b5dd2185 (diff)
Added operation condensing
Diffstat (limited to 'dice-lang/src')
-rw-r--r--dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTLanguageTest.java6
-rw-r--r--dice-lang/src/examples/java/bjc/dicelang/examples/DiceExpressionPreparer.java38
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/DiceExpressionParser.java2
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/DiceASTEvaluator.java34
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/DiceASTOptimizer.java20
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/DiceASTReferenceSanitizer.java2
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/nodes/OperatorDiceNode.java26
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/optimization/ConstantCollapser.java1
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/optimization/OperationCondenser.java105
9 files changed, 197 insertions, 37 deletions
diff --git a/dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTLanguageTest.java b/dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTLanguageTest.java
index 8d87aee..a6d5c75 100644
--- a/dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTLanguageTest.java
+++ b/dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTLanguageTest.java
@@ -9,6 +9,7 @@ import bjc.dicelang.ast.DiceASTParser;
import bjc.dicelang.ast.DiceASTReferenceSanitizer;
import bjc.dicelang.ast.nodes.IDiceASTNode;
import bjc.dicelang.ast.optimization.ConstantCollapser;
+import bjc.dicelang.ast.optimization.OperationCondenser;
import bjc.utils.funcdata.FunctionalMap;
import bjc.utils.funcdata.FunctionalStringTokenizer;
import bjc.utils.funcdata.IFunctionalList;
@@ -166,8 +167,11 @@ public class DiceASTLanguageTest {
ITree<IDiceASTNode> optimizedTree =
optimizer.optimizeTree(builtAST, enviroment);
+ ITree<IDiceASTNode> condensedTree =
+ OperationCondenser.condense(optimizedTree);
+
ITree<IDiceASTNode> sanitizedTree = DiceASTReferenceSanitizer
- .sanitize(optimizedTree, enviroment);
+ .sanitize(condensedTree, enviroment);
return sanitizedTree;
}
diff --git a/dice-lang/src/examples/java/bjc/dicelang/examples/DiceExpressionPreparer.java b/dice-lang/src/examples/java/bjc/dicelang/examples/DiceExpressionPreparer.java
index 91abf7d..caf7f37 100644
--- a/dice-lang/src/examples/java/bjc/dicelang/examples/DiceExpressionPreparer.java
+++ b/dice-lang/src/examples/java/bjc/dicelang/examples/DiceExpressionPreparer.java
@@ -20,17 +20,31 @@ public class DiceExpressionPreparer {
/**
* The yard to use for shunting expressions
*/
- private static ShuntingYard<String> yard;
+ private static ShuntingYard<String> yard;
+
+ private static final int MATH_PREC = 20;
+ private static final int DICE_PREC = 10;
+ private static final int EXPR_PREC = 0;
static {
- yard = new ShuntingYard<>();
-
- yard.addOp("d", 5); // dice operator: use for creating variable
- // size dice groups
- yard.addOp("c", 6); // compound operator: use for creating compound
- // dice from expressions
- yard.addOp(":=", 0); // binding operator: Bind a name to a variable
- // expression
+ yard = new ShuntingYard<>(false);
+
+ // Basic mathematical operators
+ yard.addOp("+", 0 + MATH_PREC);
+ yard.addOp("-", 0 + MATH_PREC);
+
+ yard.addOp("*", 1 + MATH_PREC);
+ yard.addOp("/", 1 + MATH_PREC);
+
+ yard.addOp("d", 0 + DICE_PREC); // dice operator: use for creating
+ // variable size dice groups
+ yard.addOp("c", 1 + DICE_PREC); // compound operator: use for
+ // creating compound dice from expressions
+
+ yard.addOp("=>", 0 + EXPR_PREC); // let operator: evaluate an
+ // expression in the context of another
+ yard.addOp(":=", 1 + EXPR_PREC); // binding operator: Bind a name
+ // to a variable expression
}
static IFunctionalList<String> prepareCommand(String currentLine) {
@@ -44,6 +58,7 @@ public class DiceExpressionPreparer {
ops.add(new Pair<>("*", "\\*"));
ops.add(new Pair<>("/", "/"));
ops.add(new Pair<>(":=", ":="));
+ ops.add(new Pair<>("=>", "=>"));
IFunctionalList<String> semiExpandedTokens =
ListUtils.splitTokens(tokens, ops);
@@ -52,11 +67,6 @@ public class DiceExpressionPreparer {
ops.add(new Pair<>("(", "\\("));
ops.add(new Pair<>(")", "\\)"));
- ops.add(new Pair<>("+", "\\+"));
- ops.add(new Pair<>("-", "-"));
- ops.add(new Pair<>("*", "\\*"));
- ops.add(new Pair<>("/", "/"));
- ops.add(new Pair<>(":=", ":="));
IFunctionalList<String> fullyExpandedTokens =
ListUtils.deAffixTokens(semiExpandedTokens, ops);
diff --git a/dice-lang/src/main/java/bjc/dicelang/DiceExpressionParser.java b/dice-lang/src/main/java/bjc/dicelang/DiceExpressionParser.java
index 76ccdd4..d0e013a 100644
--- a/dice-lang/src/main/java/bjc/dicelang/DiceExpressionParser.java
+++ b/dice-lang/src/main/java/bjc/dicelang/DiceExpressionParser.java
@@ -36,7 +36,7 @@ public class DiceExpressionParser {
/*
* Create a shunter to rewrite the expression
*/
- ShuntingYard<String> yard = new ShuntingYard<>();
+ ShuntingYard<String> yard = new ShuntingYard<>(true);
/*
* Add our custom operators to the yard
diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTEvaluator.java b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTEvaluator.java
index 411212e..aeecb38 100644
--- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTEvaluator.java
+++ b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTEvaluator.java
@@ -67,9 +67,38 @@ public class DiceASTEvaluator {
operatorCollapsers.put(OperatorDiceNode.GROUP,
DiceASTEvaluator::parseGroup);
+ operatorCollapsers.put(OperatorDiceNode.LET, (nodes) -> {
+ return parseLet(enviroment, nodes);
+ });
+
return operatorCollapsers;
}
+ private static IPair<Integer, ITree<IDiceASTNode>> parseLet(
+ IFunctionalMap<String, ITree<IDiceASTNode>> enviroment,
+ IFunctionalList<IPair<Integer, ITree<IDiceASTNode>>> nodes) {
+ if (nodes.getSize() != 2) {
+ throw new UnsupportedOperationException(
+ "Can only use let with two expressions.");
+ }
+
+ ITree<IDiceASTNode> bindTree = nodes.getByIndex(0).getRight();
+ ITree<IDiceASTNode> expressionTree =
+ nodes.getByIndex(1).getRight();
+
+ IFunctionalMap<String, ITree<IDiceASTNode>> letEnviroment =
+ enviroment.extend();
+
+ evaluateAST(bindTree, letEnviroment);
+ int exprResult = evaluateAST(expressionTree, letEnviroment);
+
+ IFunctionalList<ITree<IDiceASTNode>> childrn =
+ nodes.map((pair) -> pair.getRight());
+
+ return new Pair<>(exprResult,
+ new Tree<>(OperatorDiceNode.LET, childrn));
+ }
+
/**
* Evaluate the provided AST to a numeric value
*
@@ -121,8 +150,9 @@ public class DiceASTEvaluator {
return result;
}
- // Value to allow for assignments
- return 0;
+ throw new UnsupportedOperationException(
+ "Attempted to dereference unbound variable "
+ + variableName);
}
private static int evaluateLiteral(IDiceASTNode leafNode) {
diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTOptimizer.java b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTOptimizer.java
index 00ac871..7676fac 100644
--- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTOptimizer.java
+++ b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTOptimizer.java
@@ -44,14 +44,16 @@ public class DiceASTOptimizer {
*/
public ITree<IDiceASTNode> optimizeTree(ITree<IDiceASTNode> ast,
IFunctionalMap<String, ITree<IDiceASTNode>> enviroment) {
- return passes.reduceAux(ast, (currentPass, currentTree) -> {
- return currentTree.collapse(currentPass::optimizeLeaf,
- (operator) -> {
- return (nodes) -> {
- return currentPass.optimizeOperator(operator,
- nodes);
- };
- }, (tree) -> tree);
- }, (tree) -> tree);
+ ITree<IDiceASTNode> optimizedTree =
+ passes.reduceAux(ast, (currentPass, currentTree) -> {
+ return currentTree.collapse(currentPass::optimizeLeaf,
+ (operator) -> {
+ return (nodes) -> {
+ return currentPass.optimizeOperator(
+ operator, nodes);
+ };
+ }, (tree) -> tree);
+ }, (tree) -> tree);
+ return optimizedTree;
}
}
diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTReferenceSanitizer.java b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTReferenceSanitizer.java
index 08f84e3..05fddf6 100644
--- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTReferenceSanitizer.java
+++ b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTReferenceSanitizer.java
@@ -41,6 +41,8 @@ public class DiceASTReferenceSanitizer {
switch (((OperatorDiceNode) node)) {
case ASSIGN:
return TopDownTransformResult.TRANSFORM;
+ case LET:
+ return TopDownTransformResult.PASSTHROUGH;
case ADD:
case COMPOUND:
case DIVIDE:
diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/OperatorDiceNode.java b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/OperatorDiceNode.java
index ab47b56..c0f7bd3 100644
--- a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/OperatorDiceNode.java
+++ b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/OperatorDiceNode.java
@@ -14,29 +14,33 @@ public enum OperatorDiceNode implements IDiceASTNode {
*/
ADD(MATH),
/**
- * Represents assigning one node to another
+ * Represents dividing two nodes
*/
- ASSIGN(EXPRESSION),
+ DIVIDE(MATH),
/**
- * Representings combining two node values together
+ * Represents multiplying two nodes
*/
- COMPOUND(DICE),
+ MULTIPLY(MATH),
/**
- * Represents dividing two nodes
+ * Represents subtracting two nodes
*/
- DIVIDE(MATH),
+ SUBTRACT(MATH),
+ /**
+ * Representings combining two node values together
+ */
+ COMPOUND(DICE),
/**
* Represents using one node a variable number of times
*/
GROUP(DICE),
/**
- * Represents multiplying two nodes
+ * Represents assigning one node to another
*/
- MULTIPLY(MATH),
+ ASSIGN(EXPRESSION),
/**
- * Represents subtracting two nodes
+ * Represents evaluating one expression in the context of another
*/
- SUBTRACT(MATH);
+ LET(EXPRESSION);
/**
* Represents the group of operator this operator is sorted into.
@@ -73,6 +77,8 @@ public enum OperatorDiceNode implements IDiceASTNode {
case "c":
case "compound":
return COMPOUND;
+ case "=>":
+ return LET;
default:
throw new IllegalArgumentException(
s + " is not a valid operator node");
diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/optimization/ConstantCollapser.java b/dice-lang/src/main/java/bjc/dicelang/ast/optimization/ConstantCollapser.java
index 5062170..e476d74 100644
--- a/dice-lang/src/main/java/bjc/dicelang/ast/optimization/ConstantCollapser.java
+++ b/dice-lang/src/main/java/bjc/dicelang/ast/optimization/ConstantCollapser.java
@@ -78,6 +78,7 @@ public class ConstantCollapser implements IOptimizationPass {
return new Tree<>(operator, children);
case ASSIGN:
+ case LET:
default:
// We don't optimize these operators
return new Tree<>(operator, children);
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;
+ }
+}