diff options
| author | bculkin2442 <bjculkin@mix.wvu.edu> | 2016-04-17 15:02:01 -0400 |
|---|---|---|
| committer | bculkin2442 <bjculkin@mix.wvu.edu> | 2016-04-17 15:02:01 -0400 |
| commit | 4fcefd106eb23295592e9cc23a0c5d63a28f9e76 (patch) | |
| tree | e262854fc899c1bba65a4029bd9a500291f77e9e /dice-lang/src | |
| parent | 9a5aac3995cd92afbab0a4b29d42e61078ea0bb0 (diff) | |
Code maintenance and changes
Diffstat (limited to 'dice-lang/src')
5 files changed, 188 insertions, 151 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 94186dd..18f0562 100644 --- a/dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTLanguageTest.java +++ b/dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTLanguageTest.java @@ -9,7 +9,7 @@ import bjc.dicelang.ast.nodes.IDiceASTNode; import bjc.utils.funcdata.FunctionalMap; import bjc.utils.funcdata.IFunctionalList; import bjc.utils.funcdata.IFunctionalMap; -import bjc.utils.parserutils.AST; +import bjc.utils.funcdata.ITree; /** * Test interface for AST-based dice language @@ -32,12 +32,12 @@ public class DiceASTLanguageTest { String currentLine = inputSource.nextLine(); // The enviroment for variables - IFunctionalMap<String, AST<IDiceASTNode>> enviroment = + IFunctionalMap<String, ITree<IDiceASTNode>> enviroment = new FunctionalMap<>(); while (!currentLine.equalsIgnoreCase("quit")) { // Build an AST from the string expression - AST<IDiceASTNode> builtAST; + ITree<IDiceASTNode> builtAST; IFunctionalList<String> preparedTokens = DiceExpressionPreparer.prepareCommand(currentLine); diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/ArithmeticCollapser.java b/dice-lang/src/main/java/bjc/dicelang/ast/ArithmeticCollapser.java new file mode 100644 index 0000000..5ad0a0f --- /dev/null +++ b/dice-lang/src/main/java/bjc/dicelang/ast/ArithmeticCollapser.java @@ -0,0 +1,64 @@ +package bjc.dicelang.ast; + +import java.util.function.BinaryOperator; + +import bjc.dicelang.ast.nodes.IDiceASTNode; +import bjc.dicelang.ast.nodes.OperatorDiceNode; +import bjc.utils.data.IPair; +import bjc.utils.data.Pair; +import bjc.utils.funcdata.IFunctionalList; +import bjc.utils.funcdata.ITree; +import bjc.utils.funcdata.Tree; + +/** + * Responsible for collapsing arithmetic operators + * + * @author ben + * + */ +final class ArithmeticCollapser + implements IOperatorCollapser { + private OperatorDiceNode type; + + private BinaryOperator<Integer> valueOp; + + public ArithmeticCollapser(OperatorDiceNode type, + BinaryOperator<Integer> valueOp) { + this.type = type; + this.valueOp = valueOp; + } + + @Override + public IPair<Integer, ITree<IDiceASTNode>> apply( + IFunctionalList<IPair<Integer, ITree<IDiceASTNode>>> nodes) { + IPair<Integer, ITree<IDiceASTNode>> initState = + new Pair<>(0, new Tree<>(type)); + + BinaryOperator<IPair<Integer, ITree<IDiceASTNode>>> reducer = + (accumulatedState, currentState) -> { + return reduceStates(accumulatedState, + currentState); + }; + + return nodes.reduceAux(initState, reducer, (state) -> state); + } + + private IPair<Integer, ITree<IDiceASTNode>> reduceStates( + IPair<Integer, ITree<IDiceASTNode>> accumulatedState, + IPair<Integer, ITree<IDiceASTNode>> currentState) { + return accumulatedState + .bind((accumulatedValue, accumulatedTree) -> { + return currentState + .bind((currentValue, currentTree) -> { + accumulatedTree.addChild(currentTree); + + Integer combinedValue = + valueOp.apply(accumulatedValue, + currentValue); + + return new Pair<>(combinedValue, + accumulatedTree); + }); + }); + } +}
\ 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 454850c..e934b9f 100644 --- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTEvaluator.java +++ b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTEvaluator.java @@ -1,9 +1,6 @@ package bjc.dicelang.ast; -import java.util.function.BinaryOperator; - import bjc.dicelang.ComplexDice; - import bjc.dicelang.ast.nodes.DiceASTType; import bjc.dicelang.ast.nodes.DiceLiteralNode; import bjc.dicelang.ast.nodes.DiceLiteralType; @@ -12,15 +9,14 @@ import bjc.dicelang.ast.nodes.ILiteralDiceNode; import bjc.dicelang.ast.nodes.IntegerLiteralNode; import bjc.dicelang.ast.nodes.OperatorDiceNode; import bjc.dicelang.ast.nodes.VariableDiceNode; - -import bjc.utils.data.GenHolder; import bjc.utils.data.IPair; +import bjc.utils.data.LazyPair; import bjc.utils.data.Pair; -import bjc.utils.data.lazy.LazyPair; import bjc.utils.funcdata.FunctionalMap; +import bjc.utils.funcdata.IFunctionalList; import bjc.utils.funcdata.IFunctionalMap; -import bjc.utils.funcdata.bst.ITreePart.TreeLinearizationMethod; -import bjc.utils.parserutils.AST; +import bjc.utils.funcdata.ITree; +import bjc.utils.funcdata.Tree; /** * Evaluate a dice AST to an integer value @@ -30,53 +26,17 @@ import bjc.utils.parserutils.AST; */ public class DiceASTEvaluator { /** - * Responsible for collapsing arithmetic operators - * - * @author ben - * - */ - private static final class ArithmeticCollapser - implements IOperatorCollapser { - private OperatorDiceNode type; - - private BinaryOperator<Integer> valueOp; - - public ArithmeticCollapser(OperatorDiceNode type, - BinaryOperator<Integer> valueOp) { - this.type = type; - this.valueOp = valueOp; - } - - @Override - public IPair<Integer, AST<IDiceASTNode>> apply( - IPair<Integer, AST<IDiceASTNode>> leftNode, - IPair<Integer, AST<IDiceASTNode>> rightNode) { - return leftNode.bind((leftValue, leftAST) -> { - return rightNode.bind((rightValue, rightAST) -> { - if (type == OperatorDiceNode.DIVIDE - && rightValue == 0) { - throw new ArithmeticException( - "Attempted to divide by zero. The AST of the problem expression is " - + rightAST); - } - - return new Pair<>(valueOp.apply(leftValue, rightValue), - new AST<>(type, leftAST, rightAST)); - }); - }); - } - } - - /** * Build the map of operations to use when collapsing the AST * * @param enviroment * The enviroment to evaluate bindings and such against * @return The operations to use when collapsing the AST */ - private static IFunctionalMap<IDiceASTNode, IOperatorCollapser> buildOperations( - IFunctionalMap<String, AST<IDiceASTNode>> enviroment) { - IFunctionalMap<IDiceASTNode, IOperatorCollapser> operatorCollapsers = new FunctionalMap<>(); + private static IFunctionalMap<IDiceASTNode, IOperatorCollapser> + buildOperations( + IFunctionalMap<String, ITree<IDiceASTNode>> enviroment) { + IFunctionalMap<IDiceASTNode, IOperatorCollapser> operatorCollapsers = + new FunctionalMap<>(); operatorCollapsers.put(OperatorDiceNode.ADD, new ArithmeticCollapser(OperatorDiceNode.ADD, @@ -94,8 +54,8 @@ public class DiceASTEvaluator { new ArithmeticCollapser(OperatorDiceNode.DIVIDE, (left, right) -> left / right)); - operatorCollapsers.put(OperatorDiceNode.ASSIGN, (left, right) -> { - return parseBinding(enviroment, left, right); + operatorCollapsers.put(OperatorDiceNode.ASSIGN, (nodes) -> { + return parseBinding(enviroment, nodes); }); operatorCollapsers.put(OperatorDiceNode.COMPOUND, @@ -116,38 +76,30 @@ public class DiceASTEvaluator { * The enviroment to look up variables in * @return The integer value of the expression */ - public static int evaluateAST(AST<IDiceASTNode> expression, - IFunctionalMap<String, AST<IDiceASTNode>> enviroment) { - IFunctionalMap<IDiceASTNode, IOperatorCollapser> collapsers = buildOperations( - enviroment); + public static int evaluateAST(ITree<IDiceASTNode> expression, + IFunctionalMap<String, ITree<IDiceASTNode>> enviroment) { + IFunctionalMap<IDiceASTNode, IOperatorCollapser> collapsers = + buildOperations(enviroment); return expression.collapse( (node) -> evaluateLeaf(node, enviroment), collapsers::get, - (pair) -> pair.merge((left, right) -> left)); + (pair) -> pair.getLeft()); } - private static IPair<Integer, AST<IDiceASTNode>> evaluateLeaf( + private static IPair<Integer, ITree<IDiceASTNode>> evaluateLeaf( IDiceASTNode leafNode, - IFunctionalMap<String, AST<IDiceASTNode>> enviroment) { - AST<IDiceASTNode> returnedAST = new AST<>(leafNode); + IFunctionalMap<String, ITree<IDiceASTNode>> enviroment) { + ITree<IDiceASTNode> returnedAST = new Tree<>(leafNode); switch (leafNode.getType()) { case LITERAL: - return new Pair<>(evaluateLiteral(leafNode), returnedAST); + case VARIABLE: return new LazyPair<>(() -> { - String variableName = ((VariableDiceNode) leafNode) - .getVariable(); - - if (enviroment.containsKey(variableName)) { - return evaluateAST(enviroment.get(variableName), - enviroment); - } - - // Value to allow for assignments - return 0; + return bindLiteralValue(leafNode, enviroment); }, () -> returnedAST); + case OPERATOR: default: throw new UnsupportedOperationException( @@ -155,9 +107,21 @@ public class DiceASTEvaluator { } } + private static Integer bindLiteralValue(IDiceASTNode leafNode, + IFunctionalMap<String, ITree<IDiceASTNode>> enviroment) { + String variableName = ((VariableDiceNode) leafNode).getVariable(); + + if (enviroment.containsKey(variableName)) { + return evaluateAST(enviroment.get(variableName), enviroment); + } + + // Value to allow for assignments + return 0; + } + private static int evaluateLiteral(IDiceASTNode leafNode) { - DiceLiteralType literalType = ((ILiteralDiceNode) leafNode) - .getLiteralType(); + DiceLiteralType literalType = + ((ILiteralDiceNode) leafNode).getLiteralType(); switch (literalType) { case DICE: @@ -171,88 +135,95 @@ public class DiceASTEvaluator { } } - private static IPair<Integer, AST<IDiceASTNode>> parseBinding( - IFunctionalMap<String, AST<IDiceASTNode>> enviroment, - IPair<Integer, AST<IDiceASTNode>> left, - IPair<Integer, AST<IDiceASTNode>> right) { - return left.bind((leftValue, leftAST) -> { - return right.bind((rightValue, rightAST) -> { - String variableName = leftAST.applyToHead((node) -> { - if (node.getType() != DiceASTType.VARIABLE) { - throw new UnsupportedOperationException( - "Attempted to assign to '" + node - + "' which is not a variable"); - } - - return ((VariableDiceNode) node).getVariable(); - }); - - GenHolder<Boolean> selfReference = new GenHolder<>(false); - - DiceASTReferenceChecker refChecker = new DiceASTReferenceChecker( - selfReference, variableName); - - rightAST.traverse(TreeLinearizationMethod.PREORDER, - refChecker); - - // Ignore meta-variable - if (selfReference.unwrap((bool) -> bool) - && !variableName.equals("last")) { - throw new UnsupportedOperationException( - "Variable '" + variableName - + "' references itself. Problematic definition: \n\t" - + rightAST); - } + private static IPair<Integer, ITree<IDiceASTNode>> parseBinding( + IFunctionalMap<String, ITree<IDiceASTNode>> enviroment, + IFunctionalList<IPair<Integer, ITree<IDiceASTNode>>> nodes) { + if (nodes.getSize() != 2) { + throw new UnsupportedOperationException( + "Can only bind nodes with two children. Problem children are " + + nodes); + } - if (!variableName.equals("last")) { - enviroment.put(variableName, rightAST); - } else { - // Do nothing, last is an auto-handled meta-variable + IPair<Integer, ITree<IDiceASTNode>> nameNode = nodes.getByIndex(0); + IPair<Integer, ITree<IDiceASTNode>> valueNode = + nodes.getByIndex(1); + + return nameNode.bindRight((nameTree) -> { + return valueNode.bind((valueValue, valueTree) -> { + if (containsSimpleVariable(nameTree)) { + String varName = nameTree.transformHead((nameNod) -> { + return ((VariableDiceNode) nameNod).getVariable(); + }); + + enviroment.put(varName, valueTree); + + return new Pair<>(valueValue, nameTree); } - return new Pair<>(rightValue, new AST<>( - OperatorDiceNode.ASSIGN, leftAST, rightAST)); + throw new IllegalStateException( + "Statement that shouldn't be hit was hit."); }); }); } - private static IPair<Integer, AST<IDiceASTNode>> parseCompound( - IPair<Integer, AST<IDiceASTNode>> leftNode, - IPair<Integer, AST<IDiceASTNode>> rightNode) { - return leftNode.bind((leftValue, leftAST) -> { - return rightNode.bind((rightValue, rightAST) -> { - int compoundValue = Integer - .parseInt(Integer.toString(leftValue) - + Integer.toString(rightValue)); - - return new Pair<>(compoundValue, new AST<>( - OperatorDiceNode.COMPOUND, leftAST, rightAST)); + private static boolean + containsSimpleVariable(ITree<IDiceASTNode> nameTree) { + return nameTree.transformHead((nameNod) -> { + if (nameNod.getType() != DiceASTType.VARIABLE) { + throw new UnsupportedOperationException( + "Assigning to complex variables isn't supported. Problem node is " + + nameNod); + } + + return true; + }); + } + + private static IPair<Integer, ITree<IDiceASTNode>> parseCompound( + IFunctionalList<IPair<Integer, ITree<IDiceASTNode>>> nodes) { + if (nodes.getSize() != 2) { + throw new UnsupportedOperationException( + "Can only form a group from two dice"); + } + + IPair<Integer, ITree<IDiceASTNode>> leftDiceNode = + nodes.getByIndex(0); + IPair<Integer, ITree<IDiceASTNode>> rightDiceNode = + nodes.getByIndex(1); + + return leftDiceNode.bind((leftDiceValue, leftDiceTree) -> { + return rightDiceNode.bind((rightDiceValue, rightDiceTree) -> { + Integer result = + Integer.parseInt(Integer.toString(leftDiceValue) + + Integer.toString(rightDiceValue)); + + return new Pair<>(result, + new Tree<>(OperatorDiceNode.GROUP, leftDiceTree, + rightDiceTree)); }); }); } - private static IPair<Integer, AST<IDiceASTNode>> parseGroup( - IPair<Integer, AST<IDiceASTNode>> leftNode, - IPair<Integer, AST<IDiceASTNode>> rightNode) { - return leftNode.bind((leftValue, leftAST) -> { - return rightNode.bind((rightValue, rightAST) -> { - if (leftValue < 0) { - throw new UnsupportedOperationException( - "Can't attempt to roll a negative number of dice." - + " The problematic AST is " - + leftAST); - } else if (rightValue < 1) { - throw new UnsupportedOperationException( - "Can't roll dice with less than one side." - + " The problematic AST is " - + rightAST); - } + private static IPair<Integer, ITree<IDiceASTNode>> parseGroup( + IFunctionalList<IPair<Integer, ITree<IDiceASTNode>>> nodes) { + if (nodes.getSize() != 2) { + throw new UnsupportedOperationException( + "Can only form a group from two dice"); + } + + IPair<Integer, ITree<IDiceASTNode>> numberDiceNode = + nodes.getByIndex(0); + IPair<Integer, ITree<IDiceASTNode>> diceTypeNode = + nodes.getByIndex(1); - int rolledValue = new ComplexDice(leftValue, rightValue) - .roll(); + return numberDiceNode.bind((numberDiceValue, numberDiceTree) -> { + return diceTypeNode.bind((diceTypeValue, diceTypeTree) -> { + ComplexDice cDice = + new ComplexDice(numberDiceValue, diceTypeValue); - return new Pair<>(rolledValue, new AST<>( - OperatorDiceNode.GROUP, leftAST, rightAST)); + return new Pair<>(cDice.roll(), + new Tree<>(OperatorDiceNode.GROUP, numberDiceTree, + diceTypeTree)); }); }); } 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 f6500e3..95495bd 100644 --- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTParser.java +++ b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTParser.java @@ -11,7 +11,7 @@ import bjc.dicelang.ast.nodes.IntegerLiteralNode; import bjc.dicelang.ast.nodes.OperatorDiceNode; import bjc.dicelang.ast.nodes.VariableDiceNode; import bjc.utils.funcdata.IFunctionalList; -import bjc.utils.parserutils.AST; +import bjc.utils.funcdata.ITree; import bjc.utils.parserutils.TreeConstructor; /** @@ -28,9 +28,9 @@ public class DiceASTParser { * The list of tokens to convert * @return An AST built from the tokens */ - public static AST<IDiceASTNode> createFromString( + public static ITree<IDiceASTNode> createFromString( IFunctionalList<String> tokens) { - AST<String> rawTokens = TreeConstructor.constructTree(tokens, + ITree<String> rawTokens = TreeConstructor.constructTree(tokens, (token) -> { return isOperatorNode(token); }, (operator) -> false, null); diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/IOperatorCollapser.java b/dice-lang/src/main/java/bjc/dicelang/ast/IOperatorCollapser.java index ed818d4..10df77b 100644 --- a/dice-lang/src/main/java/bjc/dicelang/ast/IOperatorCollapser.java +++ b/dice-lang/src/main/java/bjc/dicelang/ast/IOperatorCollapser.java @@ -1,10 +1,11 @@ package bjc.dicelang.ast; -import java.util.function.BinaryOperator; +import java.util.function.Function; import bjc.dicelang.ast.nodes.IDiceASTNode; import bjc.utils.data.IPair; -import bjc.utils.parserutils.AST; +import bjc.utils.funcdata.IFunctionalList; +import bjc.utils.funcdata.ITree; /** * Alias for operator collapsers. Because 68-char types are too long @@ -12,7 +13,8 @@ import bjc.utils.parserutils.AST; * @author ben * */ -public interface IOperatorCollapser - extends BinaryOperator<IPair<Integer, AST<IDiceASTNode>>> { +public interface IOperatorCollapser extends + Function<IFunctionalList<IPair<Integer, ITree<IDiceASTNode>>>, + IPair<Integer, ITree<IDiceASTNode>>> { // Just an alias } |
