diff options
16 files changed, 409 insertions, 409 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 c52445d..1198ec5 100644 --- a/dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTLanguageTest.java +++ b/dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTLanguageTest.java @@ -45,6 +45,13 @@ public class DiceASTLanguageTest { optimizer.addPass(new ConstantCollapser()); } + private static String getNextCommand(Scanner inputSource, + int commandNumber) { + System.out.print("\ndice-lang-" + commandNumber + "> "); + + return inputSource.nextLine(); + } + private static void handleInlineAction( FunctionalStringTokenizer tokenizer, IFunctionalMap<String, ITree<IDiceASTNode>> enviroment) { @@ -182,11 +189,4 @@ public class DiceASTLanguageTest { return condensedTree; } - - private static String getNextCommand(Scanner inputSource, - int commandNumber) { - System.out.print("\ndice-lang-" + commandNumber + "> "); - - return inputSource.nextLine(); - } } diff --git a/dice-lang/src/examples/java/bjc/dicelang/examples/DiceLanguageTest.java b/dice-lang/src/examples/java/bjc/dicelang/examples/DiceLanguageTest.java index 2a9a492..bd6270e 100644 --- a/dice-lang/src/examples/java/bjc/dicelang/examples/DiceLanguageTest.java +++ b/dice-lang/src/examples/java/bjc/dicelang/examples/DiceLanguageTest.java @@ -25,35 +25,6 @@ public class DiceLanguageTest { } /** - * @param ln - * Unused parameter, kept to comply with expected type sig - */ - private static void printEnv(String ln, DiceLanguageState stat) { - System.out.println("Printing enviroment for debugging purposes."); - - stat.doWith((dep, env) -> env.forEach((key, exp) -> System.out - .println("\tKey: " + key + "\tExp: " + exp.toString()))); - } - - private static void rollReference(String ln, DiceLanguageState stat) { - String[] strangs = ln.split(" "); - - System.out.println("\tRolling dice expression " + strangs[1] + " " - + strangs[2] + " times."); - - int nRolls = Integer.parseInt(strangs[2]); - - IDiceExpression dexp = stat - .merge((dep, env) -> env.get(strangs[1])); - - for (int i = 1; i <= nRolls; i++) { - int roll = dexp.roll(); - - System.out.println("\tRolled " + roll); - } - } - - /** * Main method * * @param args @@ -93,4 +64,33 @@ public class DiceLanguageTest { System.out.println("Bye."); scn.close(); } + + /** + * @param ln + * Unused parameter, kept to comply with expected type sig + */ + private static void printEnv(String ln, DiceLanguageState stat) { + System.out.println("Printing enviroment for debugging purposes."); + + stat.doWith((dep, env) -> env.forEach((key, exp) -> System.out + .println("\tKey: " + key + "\tExp: " + exp.toString()))); + } + + private static void rollReference(String ln, DiceLanguageState stat) { + String[] strangs = ln.split(" "); + + System.out.println("\tRolling dice expression " + strangs[1] + " " + + strangs[2] + " times."); + + int nRolls = Integer.parseInt(strangs[2]); + + IDiceExpression dexp = stat + .merge((dep, env) -> env.get(strangs[1])); + + for (int i = 1; i <= nRolls; i++) { + int roll = dexp.roll(); + + System.out.println("\tRolled " + roll); + } + } } diff --git a/dice-lang/src/main/java/bjc/dicelang/ComplexDice.java b/dice-lang/src/main/java/bjc/dicelang/ComplexDice.java index 7ed4e3b..9450584 100644 --- a/dice-lang/src/main/java/bjc/dicelang/ComplexDice.java +++ b/dice-lang/src/main/java/bjc/dicelang/ComplexDice.java @@ -76,6 +76,25 @@ public class ComplexDice implements IDiceExpression { die = new Die(de); } + @Override + public boolean canOptimize() { + if (nDice.canOptimize() && die.canOptimize()) { + return die.optimize() == 1; + } + + return false; + } + + @Override + public int optimize() { + if (!canOptimize()) { + throw new UnsupportedOperationException( + "This complex dice cannot be optimized"); + } + + return nDice.optimize(); + } + /* * (non-Javadoc) * @@ -117,23 +136,4 @@ public class ComplexDice implements IDiceExpression { return "complex[n=" + nDice.toString() + ", d=" + die.toString() + "]"; } - - @Override - public boolean canOptimize() { - if (nDice.canOptimize() && die.canOptimize()) { - return die.optimize() == 1; - } - - return false; - } - - @Override - public int optimize() { - if (!canOptimize()) { - throw new UnsupportedOperationException( - "This complex dice cannot be optimized"); - } - - return nDice.optimize(); - } }
\ No newline at end of file diff --git a/dice-lang/src/main/java/bjc/dicelang/IDiceExpression.java b/dice-lang/src/main/java/bjc/dicelang/IDiceExpression.java index 474e18c..4585f75 100644 --- a/dice-lang/src/main/java/bjc/dicelang/IDiceExpression.java +++ b/dice-lang/src/main/java/bjc/dicelang/IDiceExpression.java @@ -11,36 +11,6 @@ import bjc.utils.funcutils.StringUtils; @FunctionalInterface public interface IDiceExpression { /** - * Roll the dice once - * - * @return The result of rowing the dice - */ - public int roll(); - - /** - * Optimize this expression to a scalar value - * - * @return This expression, optimized to a scalar value - * - * @throws UnsupportedOperationException - * if this type of expression can't be optimized - */ - public default int optimize() { - throw new UnsupportedOperationException( - "Can't optimize this type of expression"); - } - - /** - * Check if this expression can be optimized to a scalar value - * - * @return Whether or not this expression can be optimized to a scalar - * value - */ - public default boolean canOptimize() { - return false; - } - - /** * Parse this node into an expression * * @param expression @@ -73,4 +43,34 @@ public interface IDiceExpression { } } } + + /** + * Check if this expression can be optimized to a scalar value + * + * @return Whether or not this expression can be optimized to a scalar + * value + */ + public default boolean canOptimize() { + return false; + } + + /** + * Optimize this expression to a scalar value + * + * @return This expression, optimized to a scalar value + * + * @throws UnsupportedOperationException + * if this type of expression can't be optimized + */ + public default int optimize() { + throw new UnsupportedOperationException( + "Can't optimize this type of expression"); + } + + /** + * Roll the dice once + * + * @return The result of rowing the dice + */ + public int roll(); }
\ No newline at end of file diff --git a/dice-lang/src/main/java/bjc/dicelang/ScalarDie.java b/dice-lang/src/main/java/bjc/dicelang/ScalarDie.java index 1d64dc2..8d31d15 100644 --- a/dice-lang/src/main/java/bjc/dicelang/ScalarDie.java +++ b/dice-lang/src/main/java/bjc/dicelang/ScalarDie.java @@ -22,6 +22,16 @@ public class ScalarDie implements IDiceExpression { this.number = num; } + @Override + public boolean canOptimize() { + return true; + } + + @Override + public int optimize() { + return number; + } + /* * (non-Javadoc) * @@ -41,14 +51,4 @@ public class ScalarDie implements IDiceExpression { public String toString() { return Integer.toString(number); } - - @Override - public int optimize() { - return number; - } - - @Override - public boolean canOptimize() { - return true; - } }
\ No newline at end of file diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/ArithmeticCollapser.java b/dice-lang/src/main/java/bjc/dicelang/ast/ArithmeticCollapser.java index 87cbeb1..c97471d 100644 --- a/dice-lang/src/main/java/bjc/dicelang/ast/ArithmeticCollapser.java +++ b/dice-lang/src/main/java/bjc/dicelang/ast/ArithmeticCollapser.java @@ -49,20 +49,40 @@ final class ArithmeticCollapser implements IOperatorCollapser { return reducedState; } - private IPair<IResult, ITree<IDiceASTNode>> reduceStates( - IPair<IResult, ITree<IDiceASTNode>> accumulatedState, - IPair<IResult, ITree<IDiceASTNode>> currentState) { - return accumulatedState - .bind((accumulatedValue, accumulatedTree) -> { - return currentState - .bind((currentValue, currentTree) -> { - accumulatedTree.addChild(currentTree); + private IFunctionalList<IResult> combineArrayResults( + IResult accumulatedValue, IResult currentValue) { + IFunctionalList<IResult> currentList = ((ArrayResult) currentValue) + .getValue(); + IFunctionalList<IResult> accumulatedList = ((ArrayResult) accumulatedValue) + .getValue(); - return doArithmeticCollapse( - accumulatedValue, accumulatedTree, - currentValue); - }); + if (currentList.getSize() != accumulatedList.getSize()) { + throw new UnsupportedOperationException( + "Can only apply operations to equal-length arrays"); + } + + IFunctionalList<IResult> resultList = currentList.combineWith( + accumulatedList, (currentNode, accumulatedNode) -> { + boolean currentNotInt = currentNode + .getType() != ResultType.INTEGER; + boolean accumulatedNotInt = accumulatedNode + .getType() != ResultType.INTEGER; + + if (currentNotInt || accumulatedNotInt) { + throw new UnsupportedOperationException( + "Nesting of array operations isn't allowed"); + } + + int accumulatedInt = ((IntegerResult) accumulatedNode) + .getValue(); + int currentInt = ((IntegerResult) currentNode) + .getValue(); + + IResult combinedValue = new IntegerResult( + valueOp.apply(accumulatedInt, currentInt)); + return combinedValue; }); + return resultList; } private IPair<IResult, ITree<IDiceASTNode>> doArithmeticCollapse( @@ -106,42 +126,6 @@ final class ArithmeticCollapser implements IOperatorCollapser { accumulatedTree); } - private IFunctionalList<IResult> combineArrayResults( - IResult accumulatedValue, IResult currentValue) { - IFunctionalList<IResult> currentList = ((ArrayResult) currentValue) - .getValue(); - IFunctionalList<IResult> accumulatedList = ((ArrayResult) accumulatedValue) - .getValue(); - - if (currentList.getSize() != accumulatedList.getSize()) { - throw new UnsupportedOperationException( - "Can only apply operations to equal-length arrays"); - } - - IFunctionalList<IResult> resultList = currentList.combineWith( - accumulatedList, (currentNode, accumulatedNode) -> { - boolean currentNotInt = currentNode - .getType() != ResultType.INTEGER; - boolean accumulatedNotInt = accumulatedNode - .getType() != ResultType.INTEGER; - - if (currentNotInt || accumulatedNotInt) { - throw new UnsupportedOperationException( - "Nesting of array operations isn't allowed"); - } - - int accumulatedInt = ((IntegerResult) accumulatedNode) - .getValue(); - int currentInt = ((IntegerResult) currentNode) - .getValue(); - - IResult combinedValue = new IntegerResult( - valueOp.apply(accumulatedInt, currentInt)); - return combinedValue; - }); - return resultList; - } - private IFunctionalList<IResult> halfCombineLists( IFunctionalList<IResult> list, IResult scalar, boolean scalarLeft) { @@ -172,4 +156,20 @@ final class ArithmeticCollapser implements IOperatorCollapser { return combinedValue; }); } + + private IPair<IResult, ITree<IDiceASTNode>> reduceStates( + IPair<IResult, ITree<IDiceASTNode>> accumulatedState, + IPair<IResult, ITree<IDiceASTNode>> currentState) { + return accumulatedState + .bind((accumulatedValue, accumulatedTree) -> { + return currentState + .bind((currentValue, currentTree) -> { + accumulatedTree.addChild(currentTree); + + return doArithmeticCollapse( + accumulatedValue, accumulatedTree, + currentValue); + }); + }); + } }
\ No newline at end of file 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 6044602..4e7d6fb 100644 --- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTEvaluator.java +++ b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTEvaluator.java @@ -31,6 +31,21 @@ import bjc.dicelang.ast.nodes.VariableDiceNode; * */ public class DiceASTEvaluator { + private static IResult bindLiteralValue(IDiceASTNode leafNode, + IFunctionalMap<String, ITree<IDiceASTNode>> enviroment) { + String variableName = ((VariableDiceNode) leafNode).getVariable(); + + if (enviroment.containsKey(variableName)) { + IResult result = evaluateAST(enviroment.get(variableName), + enviroment); + + return result; + } + + throw new UnsupportedOperationException( + "Attempted to deref unbound variable " + variableName); + } + /** * Build the map of operations to use when collapsing the AST * @@ -106,29 +121,24 @@ public class DiceASTEvaluator { return operatorCollapsers; } - private static IPair<IResult, ITree<IDiceASTNode>> parseLet( + private static void doArrayAssign( IFunctionalMap<String, ITree<IDiceASTNode>> enviroment, - IFunctionalList<IPair<IResult, ITree<IDiceASTNode>>> nodes) { - if (nodes.getSize() != 2) { + IPair<IResult, ITree<IDiceASTNode>> nameNode, + ITree<IDiceASTNode> nameTree, ITree<IDiceASTNode> valueTree, + IHolder<Integer> childCount, ITree<IDiceASTNode> child) { + if (nameTree.getHead().getType() != DiceASTType.VARIABLE) { throw new UnsupportedOperationException( - "Can only use let with two expressions."); + "Assigning to complex variables isn't supported. Problem node is " + + nameNode.getRight()); } - ITree<IDiceASTNode> bindTree = nodes.getByIndex(0).getRight(); - ITree<IDiceASTNode> expressionTree = nodes.getByIndex(1) - .getRight(); - - IFunctionalMap<String, ITree<IDiceASTNode>> letEnviroment = enviroment - .extend(); - - evaluateAST(bindTree, letEnviroment); - IResult exprResult = evaluateAST(expressionTree, letEnviroment); + String varName = child.transformHead((nameNod) -> { + return ((VariableDiceNode) nameNod).getVariable(); + }); - IFunctionalList<ITree<IDiceASTNode>> childrn = nodes - .map((pair) -> pair.getRight()); + enviroment.put(varName, valueTree.getChild(childCount.getValue())); - return new Pair<>(exprResult, - new Tree<>(OperatorDiceNode.LET, childrn)); + childCount.transform(val -> val + 1); } /** @@ -171,21 +181,6 @@ public class DiceASTEvaluator { } } - private static IResult bindLiteralValue(IDiceASTNode leafNode, - IFunctionalMap<String, ITree<IDiceASTNode>> enviroment) { - String variableName = ((VariableDiceNode) leafNode).getVariable(); - - if (enviroment.containsKey(variableName)) { - IResult result = evaluateAST(enviroment.get(variableName), - enviroment); - - return result; - } - - throw new UnsupportedOperationException( - "Attempted to deref unbound variable " + variableName); - } - private static IResult evaluateLiteral(IDiceASTNode leafNode) { DiceLiteralType literalType = ((ILiteralDiceNode) leafNode) .getLiteralType(); @@ -269,26 +264,6 @@ public class DiceASTEvaluator { }); } - private static void doArrayAssign( - IFunctionalMap<String, ITree<IDiceASTNode>> enviroment, - IPair<IResult, ITree<IDiceASTNode>> nameNode, - ITree<IDiceASTNode> nameTree, ITree<IDiceASTNode> valueTree, - IHolder<Integer> childCount, ITree<IDiceASTNode> child) { - if (nameTree.getHead().getType() != DiceASTType.VARIABLE) { - throw new UnsupportedOperationException( - "Assigning to complex variables isn't supported. Problem node is " - + nameNode.getRight()); - } - - String varName = child.transformHead((nameNod) -> { - return ((VariableDiceNode) nameNod).getVariable(); - }); - - enviroment.put(varName, valueTree.getChild(childCount.getValue())); - - childCount.transform(val -> val + 1); - } - private static IPair<IResult, ITree<IDiceASTNode>> parseGroup( IFunctionalList<IPair<IResult, ITree<IDiceASTNode>>> nodes) { if (nodes.getSize() != 2) { @@ -313,4 +288,29 @@ public class DiceASTEvaluator { }); }); } + + private static IPair<IResult, ITree<IDiceASTNode>> parseLet( + IFunctionalMap<String, ITree<IDiceASTNode>> enviroment, + IFunctionalList<IPair<IResult, 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); + IResult exprResult = evaluateAST(expressionTree, letEnviroment); + + IFunctionalList<ITree<IDiceASTNode>> childrn = nodes + .map((pair) -> pair.getRight()); + + return new Pair<>(exprResult, + new Tree<>(OperatorDiceNode.LET, childrn)); + } } diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTInliner.java b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTInliner.java index 114965e..5032dc4 100644 --- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTInliner.java +++ b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTInliner.java @@ -80,19 +80,9 @@ public class DiceASTInliner { public static ITree<IDiceASTNode> selectiveInline( ITree<IDiceASTNode> ast, IFunctionalMap<String, ITree<IDiceASTNode>> enviroment, - String... variables) { - if (variables != null && variables.length > 0) { - IFunctionalList<String> variableNames = new FunctionalList<>( - variables); - - return ast.flatMapTree((node) -> { - return inlineNode(node, enviroment, true, variableNames); - }); - } - - return ast.flatMapTree((node) -> { - return inlineNode(node, enviroment, false, null); - }); + IFunctionalList<String> variables) { + return selectiveInline(ast, enviroment, + variables.toArray(new String[0])); } /** @@ -109,8 +99,18 @@ public class DiceASTInliner { public static ITree<IDiceASTNode> selectiveInline( ITree<IDiceASTNode> ast, IFunctionalMap<String, ITree<IDiceASTNode>> enviroment, - IFunctionalList<String> variables) { - return selectiveInline(ast, enviroment, - variables.toArray(new String[0])); + String... variables) { + if (variables != null && variables.length > 0) { + IFunctionalList<String> variableNames = new FunctionalList<>( + variables); + + return ast.flatMapTree((node) -> { + return inlineNode(node, enviroment, true, variableNames); + }); + } + + return ast.flatMapTree((node) -> { + return inlineNode(node, enviroment, false, null); + }); } } diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTParser.java b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTParser.java index 3a4bccf..f14df74 100644 --- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTParser.java +++ b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTParser.java @@ -30,6 +30,41 @@ import bjc.dicelang.ast.nodes.VariableDiceNode; * */ public class DiceASTParser { + private static IDiceASTNode convertLeafNode(String leafNode) { + DiceLiteralType literalType = ILiteralDiceNode + .getLiteralType(leafNode); + + if (literalType != null) { + switch (literalType) { + case DICE: + return new DiceLiteralNode( + IDiceExpression.toExpression(leafNode)); + case INTEGER: + return new IntegerLiteralNode( + Integer.parseInt(leafNode)); + default: + throw new InputMismatchException( + "Cannot convert string '" + leafNode + + "' into a literal."); + } + } + + return new VariableDiceNode(leafNode); + } + + private static IDiceASTNode convertOperatorNode(String operatorNode) { + try { + return OperatorDiceNode.fromString(operatorNode); + } catch (IllegalArgumentException iaex) { + InputMismatchException imex = new InputMismatchException( + "Attempted to parse invalid operator " + operatorNode); + + imex.initCause(iaex); + + throw imex; + } + } + /** * Create an AST from a list of tokens * @@ -73,30 +108,6 @@ public class DiceASTParser { return tokenizedTree; } - private static ITree<String> parseCloseArray( - Deque<ITree<String>> queuedTrees) { - IFunctionalList<ITree<String>> children = new FunctionalList<>(); - - while (shouldContinuePopping(queuedTrees)) { - children.add(queuedTrees.pop()); - } - - queuedTrees.pop(); - - children.reverse(); - - ITree<String> arrayTree = new Tree<>("[]", children); - - return arrayTree; - } - - private static boolean shouldContinuePopping( - Deque<ITree<String>> queuedTrees) { - String peekToken = queuedTrees.peek().getHead(); - - return !peekToken.equals("["); - } - private static boolean isOperatorNode(String token) { if (StringUtils.containsOnly(token, "\\[")) { return true; @@ -118,38 +129,27 @@ public class DiceASTParser { } } - private static IDiceASTNode convertLeafNode(String leafNode) { - DiceLiteralType literalType = ILiteralDiceNode - .getLiteralType(leafNode); + private static ITree<String> parseCloseArray( + Deque<ITree<String>> queuedTrees) { + IFunctionalList<ITree<String>> children = new FunctionalList<>(); - if (literalType != null) { - switch (literalType) { - case DICE: - return new DiceLiteralNode( - IDiceExpression.toExpression(leafNode)); - case INTEGER: - return new IntegerLiteralNode( - Integer.parseInt(leafNode)); - default: - throw new InputMismatchException( - "Cannot convert string '" + leafNode - + "' into a literal."); - } + while (shouldContinuePopping(queuedTrees)) { + children.add(queuedTrees.pop()); } - return new VariableDiceNode(leafNode); - } + queuedTrees.pop(); - private static IDiceASTNode convertOperatorNode(String operatorNode) { - try { - return OperatorDiceNode.fromString(operatorNode); - } catch (IllegalArgumentException iaex) { - InputMismatchException imex = new InputMismatchException( - "Attempted to parse invalid operator " + operatorNode); + children.reverse(); - imex.initCause(iaex); + ITree<String> arrayTree = new Tree<>("[]", children); - throw imex; - } + return arrayTree; + } + + private static boolean shouldContinuePopping( + Deque<ITree<String>> queuedTrees) { + String peekToken = queuedTrees.peek().getHead(); + + return !peekToken.equals("["); } } 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 3079bca..082c94a 100644 --- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTReferenceSanitizer.java +++ b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTReferenceSanitizer.java @@ -20,45 +20,6 @@ import bjc.dicelang.ast.nodes.VariableDiceNode; * */ public class DiceASTReferenceSanitizer { - /** - * Sanitize the references in an AST - * - * @param ast - * @param enviroment - * @return The sanitized AST - */ - public static ITree<IDiceASTNode> sanitize(ITree<IDiceASTNode> ast, - IFunctionalMap<String, ITree<IDiceASTNode>> enviroment) { - return ast.topDownTransform( - DiceASTReferenceSanitizer::shouldSanitize, (subTree) -> { - return doSanitize(subTree, enviroment); - }); - } - - private static TopDownTransformResult shouldSanitize( - IDiceASTNode node) { - if (!node.isOperator()) { - return TopDownTransformResult.SKIP; - } - - switch (((OperatorDiceNode) node)) { - case ASSIGN: - return TopDownTransformResult.TRANSFORM; - case ARRAY: - case LET: - return TopDownTransformResult.PASSTHROUGH; - case ADD: - case CALL: - case COMPOUND: - case DIVIDE: - case GROUP: - case MULTIPLY: - case SUBTRACT: - default: - return TopDownTransformResult.SKIP; - } - } - private static ITree<IDiceASTNode> doSanitize(ITree<IDiceASTNode> ast, IFunctionalMap<String, ITree<IDiceASTNode>> enviroment) { if (ast.getChildrenCount() != 2) { @@ -199,4 +160,43 @@ public class DiceASTReferenceSanitizer { return null; } + + /** + * Sanitize the references in an AST + * + * @param ast + * @param enviroment + * @return The sanitized AST + */ + public static ITree<IDiceASTNode> sanitize(ITree<IDiceASTNode> ast, + IFunctionalMap<String, ITree<IDiceASTNode>> enviroment) { + return ast.topDownTransform( + DiceASTReferenceSanitizer::shouldSanitize, (subTree) -> { + return doSanitize(subTree, enviroment); + }); + } + + private static TopDownTransformResult shouldSanitize( + IDiceASTNode node) { + if (!node.isOperator()) { + return TopDownTransformResult.SKIP; + } + + switch (((OperatorDiceNode) node)) { + case ASSIGN: + return TopDownTransformResult.TRANSFORM; + case ARRAY: + case LET: + return TopDownTransformResult.PASSTHROUGH; + case ADD: + case CALL: + case COMPOUND: + case DIVIDE: + case GROUP: + case MULTIPLY: + case SUBTRACT: + default: + return TopDownTransformResult.SKIP; + } + } } diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTUtils.java b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTUtils.java index a70ee00..8d70af8 100644 --- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTUtils.java +++ b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTUtils.java @@ -36,25 +36,6 @@ public class DiceASTUtils { } /** - * Convert an AST tree to an integer, if possible. - * - * @param tree - * The tree to convert - * @return The tree as an integer - * - * @throws ClassCastException - * if the head of the tree is not a literal (implements - * {@link ILiteralDiceNode}) - * @throws UnsupportedOperationException - * if the head of the tree is not optimizable - */ - public static int toInt(ITree<IDiceASTNode> tree) { - return tree.transformHead((node) -> { - return ((ILiteralDiceNode) node).optimize(); - }); - } - - /** * Convert an AST tree to a dice expression, if possible. * * @param tree @@ -81,4 +62,23 @@ public class DiceASTUtils { "This type of literal isn't convertable to an expression"); } } + + /** + * Convert an AST tree to an integer, if possible. + * + * @param tree + * The tree to convert + * @return The tree as an integer + * + * @throws ClassCastException + * if the head of the tree is not a literal (implements + * {@link ILiteralDiceNode}) + * @throws UnsupportedOperationException + * if the head of the tree is not optimizable + */ + public static int toInt(ITree<IDiceASTNode> tree) { + return tree.transformHead((node) -> { + return ((ILiteralDiceNode) node).optimize(); + }); + } } diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/IntegerResult.java b/dice-lang/src/main/java/bjc/dicelang/ast/IntegerResult.java index c8d9a64..ce61d38 100644 --- a/dice-lang/src/main/java/bjc/dicelang/ast/IntegerResult.java +++ b/dice-lang/src/main/java/bjc/dicelang/ast/IntegerResult.java @@ -19,6 +19,11 @@ public class IntegerResult implements IResult { value = val; } + @Override + public ResultType getType() { + return ResultType.INTEGER; + } + /** * Get the value of this result * @@ -29,11 +34,6 @@ public class IntegerResult implements IResult { } @Override - public ResultType getType() { - return ResultType.INTEGER; - } - - @Override public String toString() { return Integer.toString(value); } diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/ILiteralDiceNode.java b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/ILiteralDiceNode.java index 994a680..2105102 100644 --- a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/ILiteralDiceNode.java +++ b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/ILiteralDiceNode.java @@ -9,39 +9,6 @@ import org.apache.commons.lang3.StringUtils; * */ public interface ILiteralDiceNode extends IDiceASTNode { - @Override - default DiceASTType getType() { - return DiceASTType.LITERAL; - } - - @Override - default boolean isOperator() { - return false; - } - - /** - * Get the type of literal this node represents - * - * @return The type of literal this node represents - */ - DiceLiteralType getLiteralType(); - - /** - * Optimize this node to a constant if possible - * - * @return This node in constant form if possible - * @see bjc.dicelang.IDiceExpression#optimize() - */ - int optimize(); - - /** - * Check if this node can be optimized to a constant - * - * @return Whether or not this node can be optimized to a constant - * @see bjc.dicelang.IDiceExpression#canOptimize() - */ - boolean canOptimize(); - /** * Check if a token represents a literal, and if so, what type * @@ -67,4 +34,37 @@ public interface ILiteralDiceNode extends IDiceASTNode { } } } + + /** + * Check if this node can be optimized to a constant + * + * @return Whether or not this node can be optimized to a constant + * @see bjc.dicelang.IDiceExpression#canOptimize() + */ + boolean canOptimize(); + + /** + * Get the type of literal this node represents + * + * @return The type of literal this node represents + */ + DiceLiteralType getLiteralType(); + + @Override + default DiceASTType getType() { + return DiceASTType.LITERAL; + } + + @Override + default boolean isOperator() { + return false; + } + + /** + * Optimize this node to a constant if possible + * + * @return This node in constant form if possible + * @see bjc.dicelang.IDiceExpression#optimize() + */ + int optimize(); } diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/IntegerLiteralNode.java b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/IntegerLiteralNode.java index d25adbc..3d43bb1 100644 --- a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/IntegerLiteralNode.java +++ b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/IntegerLiteralNode.java @@ -20,6 +20,11 @@ public class IntegerLiteralNode implements ILiteralDiceNode { } @Override + public boolean canOptimize() { + return true; + } + + @Override public DiceLiteralType getLiteralType() { return DiceLiteralType.INTEGER; } @@ -34,17 +39,12 @@ public class IntegerLiteralNode implements ILiteralDiceNode { } @Override - public String toString() { - return Integer.toString(value); - } - - @Override public int optimize() { return value; } @Override - public boolean canOptimize() { - return true; + public String toString() { + return Integer.toString(value); } } 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 411548a..4ba3956 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 @@ -53,16 +53,6 @@ public enum OperatorDiceNode implements IDiceASTNode { LET(EXPRESSION); /** - * Represents the group of operator this operator is sorted into. - * - */ - public final DiceOperatorType type; - - private OperatorDiceNode(DiceOperatorType ty) { - type = ty; - } - - /** * Create a operator node from a string * * @param s @@ -99,6 +89,16 @@ public enum OperatorDiceNode implements IDiceASTNode { } } + /** + * Represents the group of operator this operator is sorted into. + * + */ + public final DiceOperatorType type; + + private OperatorDiceNode(DiceOperatorType ty) { + type = ty; + } + @Override public DiceASTType getType() { return DiceASTType.OPERATOR; 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 index bdf7b04..f646a17 100644 --- a/dice-lang/src/main/java/bjc/dicelang/ast/optimization/OperationCondenser.java +++ b/dice-lang/src/main/java/bjc/dicelang/ast/optimization/OperationCondenser.java @@ -29,40 +29,6 @@ public class OperationCondenser { 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 ARRAY: - 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 @@ -104,4 +70,38 @@ public class OperationCondenser { 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); + } + } } |
