diff options
| author | bculkin2442 <bjculkin@mix.wvu.edu> | 2016-10-27 21:56:18 -0400 |
|---|---|---|
| committer | bculkin2442 <bjculkin@mix.wvu.edu> | 2016-10-27 22:12:47 -0400 |
| commit | e7413128ff4e376997de6e94e4bea5eca14811ef (patch) | |
| tree | 0749e270fdb754d04dc223abd95d47436508047f /dice-lang/src/main/java/bjc/dicelang | |
| parent | e13a6981bd278c2cfc3b5ecb2517367b117f7a52 (diff) | |
Moved examples
Diffstat (limited to 'dice-lang/src/main/java/bjc/dicelang')
42 files changed, 0 insertions, 3414 deletions
diff --git a/dice-lang/src/main/java/bjc/dicelang/BindingDiceExpression.java b/dice-lang/src/main/java/bjc/dicelang/BindingDiceExpression.java deleted file mode 100644 index 6a030e3..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/BindingDiceExpression.java +++ /dev/null @@ -1,93 +0,0 @@ -package bjc.dicelang; - -import java.util.Map; - -/** - * A variable expression that represents binding a variable to a name in an - * enviroment - * - * @author ben - * - */ -public class BindingDiceExpression implements IDiceExpression { - /** - * The expression being bound to a name - */ - private IDiceExpression expression; - - /** - * The name to bind the expression to - */ - private String variableName; - - /** - * Create a new dice expression binder from two expressions and an - * enviroment - * - * @param left - * The left side expression to get a name from. Must be a - * ReferenceDiceExpression - * @param right - * The right side to bind to the name - * @param enviroment - * The enviroment to bind into - */ - public BindingDiceExpression(IDiceExpression left, - IDiceExpression right, - Map<String, IDiceExpression> enviroment) { - if (!(left instanceof ReferenceDiceExpression)) { - throw new UnsupportedOperationException( - "Error: Binding an expression to something that is not a variable reference," - + " or array thereof. is unsupported." - + " Problematic expression is " + left); - } - - String varName = ((ReferenceDiceExpression) left).getName(); - - initialize(varName, right, enviroment); - } - - /** - * Create a new dice expression binder - * - * @param name - * The name of the variable to bind - * @param expression - * The expression to bind to the variable - * @param enviroment - * The enviroment to bind it in - */ - public BindingDiceExpression(String name, IDiceExpression expression, - Map<String, IDiceExpression> enviroment) { - initialize(name, expression, enviroment); - } - - private void initialize(String name, IDiceExpression expr, - Map<String, IDiceExpression> enviroment) { - this.variableName = name; - this.expression = expr; - - enviroment.put(name, expr); - } - - /* - * (non-Javadoc) - * - * @see bjc.utils.dice.IDiceExpression#roll() - */ - @Override - public int roll() { - return expression.roll(); - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - return "assign[n=" + variableName + ", exp=" - + expression.toString() + "]"; - } -} diff --git a/dice-lang/src/main/java/bjc/dicelang/ComplexDice.java b/dice-lang/src/main/java/bjc/dicelang/ComplexDice.java deleted file mode 100644 index 9bf191f..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ComplexDice.java +++ /dev/null @@ -1,147 +0,0 @@ -package bjc.dicelang; - -/** - * Implements a collection of one or more of a particular die, where the - * number of dice in the group is variable. - * - * @author ben - * - */ -public class ComplexDice implements IDiceExpression { - /** - * Create a dice from a string expression - * - * @param expression - * The string to parse the dice from - * @return A dice group parsed from the string - */ - public static IDiceExpression fromString(String expression) { - // Handle the case where someone passes us a simple expression - // containing a single die - if (!expression.contains("d")) { - return new Die(Integer.parseInt(expression)); - } - // Split it on the dice type marker - - String[] strangs = expression.split("d"); - - try { - // Create the actual group of dice - return new ComplexDice( - new ScalarDie(Integer.parseInt(strangs[0])), - new Die(Integer.parseInt(strangs[1]))); - } catch (@SuppressWarnings("unused") NumberFormatException nfex) { - // We don't care about details - - // Tell the user the expression is invalid - throw new IllegalArgumentException( - "Attempted to create a set of dice using invalid arguments." - + " They must be integers. " + strangs[0] - + " and " + strangs[1] - + " are likely culprits."); - } - } - - /** - * The die being rolled - */ - private IDiceExpression die; - - /** - * The number of the particular die to roll - */ - private IDiceExpression nDice; - - /** - * Create a new collection of dice - * - * @param nDce - * The number of dice in the collection - * @param de - * The type of dice the collection is composed of - */ - public ComplexDice(IDiceExpression nDce, IDiceExpression de) { - nDice = nDce; - die = de; - } - - /** - * Create a new collection of dice - * - * @param nSides - * The number of dice in the collection - * @param de - * The type of dice the collection is composed of - */ - public ComplexDice(int nSides, int de) { - nDice = new ScalarDie(nSides); - die = new Die(de); - } - - @Override - public boolean canOptimize() { - // Can only optimize this dice group if both components can be - // optimized and the die itself has only one value - 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. " - + "Both the dice to be rolled and the number of" - + " dice must be optimizable."); - } - - return nDice.optimize(); - } - - /* - * (non-Javadoc) - * - * @see bjc.utils.dice.IDiceExpression#roll() - */ - @Override - public int roll() { - int res = 0; - - /* - * Add the results of rolling each die - */ - int nRoll = nDice.roll(); - - if (nRoll < 0) { - throw new UnsupportedOperationException( - "Attempted to roll a negative number of dice. " - + "The problematic expression is " + nDice); - } - - // Roll all the dice and combine them - for (int i = 0; i < nRoll; i++) { - res += die.roll(); - } - - return res; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - // Print simple dice groups in a much clearer manner - if (nDice instanceof ScalarDie && die instanceof Die) { - return nDice.toString() + die.toString(); - } - - return "complex[n=" + nDice.toString() + ", d=" + die.toString() - + "]"; - } -}
\ No newline at end of file diff --git a/dice-lang/src/main/java/bjc/dicelang/CompoundDice.java b/dice-lang/src/main/java/bjc/dicelang/CompoundDice.java deleted file mode 100644 index 704e4cd..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/CompoundDice.java +++ /dev/null @@ -1,100 +0,0 @@ -package bjc.dicelang; - -/** - * Implements a "compound dice" - * - * To explain, a compound dice is something like a d100 composed from two - * d10s instead of a hundred sided die. - * - * @author ben - * - */ -public class CompoundDice implements IDiceExpression { - /** - * The left die of the expression - */ - private IDiceExpression leftDice; - - /** - * The right die of the expression - */ - private IDiceExpression rightDice; - - /** - * Create a new compound dice using the specified dice - * - * @param left - * The die to use on the left - * @param right - * The die to use on the right - */ - public CompoundDice(IDiceExpression left, IDiceExpression right) { - this.leftDice = left; - this.rightDice = right; - } - - /** - * Create a new compound dice from two dice strings - * - * @param leftExp - * The left side dice as a string - * @param rightExp - * The right side dice as a string - */ - public CompoundDice(String leftExp, String rightExp) { - this(ComplexDice.fromString(leftExp), - ComplexDice.fromString(rightExp)); - } - - /** - * Create a new compound dice from an array of dice strings - * - * @param exps - * An array of two dice strings - */ - public CompoundDice(String[] exps) { - this(exps[0], exps[1]); - } - - @Override - public boolean canOptimize() { - return leftDice.canOptimize() && rightDice.canOptimize(); - } - - @Override - public int optimize() { - if (!canOptimize()) { - throw new UnsupportedOperationException( - "Cannot optimize this compound dice. " - + "Both component dice must be optimizable" - + " to optimize a compound dice"); - } - - return Integer - .parseInt(leftDice.optimize() + "" + rightDice.optimize()); - } - - /* - * (non-Javadoc) - * - * @see bjc.utils.dice.IDiceExpression#roll() - */ - @Override - public int roll() { - /* - * Make the combination of the two dice - */ - return Integer.parseInt(leftDice.roll() + "" + rightDice.roll()); - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - return "compound[l=" + leftDice.toString() + ", r=" - + rightDice.toString() + "]"; - } -}
\ No newline at end of file diff --git a/dice-lang/src/main/java/bjc/dicelang/DiceExpressionBuilder.java b/dice-lang/src/main/java/bjc/dicelang/DiceExpressionBuilder.java deleted file mode 100644 index af856a6..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/DiceExpressionBuilder.java +++ /dev/null @@ -1,150 +0,0 @@ -package bjc.dicelang; - -import static bjc.dicelang.DiceExpressionType.ADD; -import static bjc.dicelang.DiceExpressionType.DIVIDE; -import static bjc.dicelang.DiceExpressionType.MULTIPLY; -import static bjc.dicelang.DiceExpressionType.SUBTRACT; - -/** - * Build a dice expression piece by piece - * - * @author ben - * - */ -public class DiceExpressionBuilder { - /** - * The dice expression we are building - */ - private IDiceExpression baking; - - /** - * Build a dice expression from a seed dice expression - * - * @param seed - * The dice expression to use as a seed - */ - public DiceExpressionBuilder(IDiceExpression seed) { - baking = seed; - } - - /** - * Build a dice expression from a seed dice - * - * @param nSides - * The number of sides in the dice - * @param nDice - * The number of dice in the group - */ - public DiceExpressionBuilder(int nSides, int nDice) { - baking = new ComplexDice(nSides, nDice); - } - - /** - * Add a term to this dice expression - * - * @param exp - * The expression to use on the left - * @return A new expression adding the two dice - */ - public DiceExpressionBuilder add(IDiceExpression exp) { - baking = new OperatorDiceExpression(baking, exp, ADD); - return this; - } - - /** - * Add a scalar to this dice - * - * @param num - * The scalar to add to the dice - * @return A dice expression adding a scalar to this - */ - public DiceExpressionBuilder add(int num) { - baking = new OperatorDiceExpression(baking, new ScalarDie(num), - ADD); - return this; - } - - /** - * Bake the expression being built to completion - * - * @return A usable dice expression - */ - public IDiceExpression bake() { - return baking; - } - - /** - * Divide a term from dice expression - * - * @param exp - * The expression to use on the left - * @return A new expression dividing the two dice - */ - public DiceExpressionBuilder divide(IDiceExpression exp) { - baking = new OperatorDiceExpression(baking, exp, DIVIDE); - return this; - } - - /** - * Divide a scalar from this dice - * - * @param num - * The scalar to add to the dice - * @return A dice expression dividing a scalar from this - */ - public DiceExpressionBuilder divide(int num) { - baking = new OperatorDiceExpression(baking, new ScalarDie(num), - DIVIDE); - return this; - } - - /** - * Multiply a term by this dice expression - * - * @param exp - * The expression to use on the left - * @return A new expression multiplying the two dice - */ - public DiceExpressionBuilder multiply(IDiceExpression exp) { - baking = new OperatorDiceExpression(baking, exp, MULTIPLY); - return this; - } - - /** - * Multiply a scalar by this dice - * - * @param num - * The scalar to multiply to the dice - * @return A dice expression multiplying a scalar to this - */ - public DiceExpressionBuilder multiply(int num) { - baking = new OperatorDiceExpression(baking, new ScalarDie(num), - MULTIPLY); - return this; - } - - /** - * Add a term to this dice expression - * - * @param exp - * The expression to use on the left - * @return A new expression adding the two dice - */ - public DiceExpressionBuilder subtract(IDiceExpression exp) { - baking = new OperatorDiceExpression(baking, exp, SUBTRACT); - return this; - } - - /** - * Add a scalar to this dice - * - * @param num - * The scalar to add to the dice - * @return A dice expression adding a scalar to this - */ - public DiceExpressionBuilder subtract(int num) { - baking = new OperatorDiceExpression(baking, new ScalarDie(num), - SUBTRACT); - return this; - } -} diff --git a/dice-lang/src/main/java/bjc/dicelang/DiceExpressionParser.java b/dice-lang/src/main/java/bjc/dicelang/DiceExpressionParser.java deleted file mode 100644 index 8a1552a..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/DiceExpressionParser.java +++ /dev/null @@ -1,173 +0,0 @@ -package bjc.dicelang; - -import java.util.Map; -import java.util.Stack; - -import bjc.utils.funcdata.FunctionalStringTokenizer; -import bjc.utils.funcdata.IList; -import bjc.utils.parserutils.ShuntingYard; - -import org.apache.commons.lang3.StringUtils; - -/** - * Parse a dice expression from a string - * - * @author ben - * - */ -public class DiceExpressionParser { - /** - * Parse a dice expression from a string - * - * @param expression - * The string to parse an expression from - * @param enviroment - * The enviroment to use when parsing expressions - * @return The parsed dice expression - */ - public static IDiceExpression parse(String expression, - Map<String, IDiceExpression> enviroment) { - /* - * Create a tokenizer over the strings - */ - FunctionalStringTokenizer tokenizer = new FunctionalStringTokenizer( - expression); - - /* - * Create a shunter to rewrite the expression - */ - ShuntingYard<String> yard = new ShuntingYard<>(true); - - /* - * Add our custom operators to the yard - */ - 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 - - /* - * Shunt the expression to postfix form - */ - IList<String> list = yard.postfix(tokenizer.toList(), s -> s); - - /* - * Create a stack for building an expression from parts - */ - Stack<IDiceExpression> expressions = new Stack<>(); - - /* - * Create the expression from parts - */ - list.forEach((expressionPart) -> { - /* - * Handle compound dice - */ - if (StringUtils.countMatches(expressionPart, 'c') == 1 - && !expressionPart.equalsIgnoreCase("c")) { - String[] strangs = expressionPart.split("c"); - - expressions.push(new CompoundDice(strangs)); - } else if (StringUtils.countMatches(expressionPart, 'd') == 1 - && !expressionPart.equalsIgnoreCase("d")) { - /* - * Handle dice groups - */ - expressions.push(ComplexDice.fromString(expressionPart)); - } else { - try { - /* - * Handle scalar numbers - */ - expressions.push(new ScalarDie( - Integer.parseInt(expressionPart))); - } catch (@SuppressWarnings("unused") NumberFormatException nfex) { - // We don't care about details, just that it failed - if (expressions.size() >= 2) { - /* - * Apply an operation to two dice - */ - IDiceExpression rightExpression = expressions - .pop(); - IDiceExpression leftExpression = expressions.pop(); - - switch (expressionPart) { - case ":=": - expressions.push(new BindingDiceExpression( - leftExpression, rightExpression, - enviroment)); - break; - case "+": - expressions - .push(new OperatorDiceExpression( - rightExpression, - leftExpression, - DiceExpressionType.ADD)); - break; - case "-": - expressions - .push(new OperatorDiceExpression( - rightExpression, - leftExpression, - DiceExpressionType.SUBTRACT)); - break; - case "*": - expressions - .push(new OperatorDiceExpression( - rightExpression, - leftExpression, - DiceExpressionType.MULTIPLY)); - break; - case "/": - expressions - .push(new OperatorDiceExpression( - rightExpression, - leftExpression, - DiceExpressionType.DIVIDE)); - break; - case "c": - expressions.push(new CompoundDice( - leftExpression, rightExpression)); - break; - case "d": - expressions.push(new ComplexDice( - leftExpression, rightExpression)); - break; - default: - /* - * Parse it as a variable reference - * - * Make sure to restore popped variables - */ - expressions.push(leftExpression); - expressions.push(rightExpression); - - expressions - .push(new ReferenceDiceExpression( - expressionPart, - enviroment)); - } - } else { - /* - * Parse it as a variable reference - */ - expressions.push(new ReferenceDiceExpression( - expressionPart, enviroment)); - } - } - } - }); - - if (expressions.size() != 1) { - System.err.println( - "WARNING: Leftovers found on dice expression stack. Remember, := is assignment."); - } - - /* - * Return the built expression - */ - return expressions.pop(); - } -} diff --git a/dice-lang/src/main/java/bjc/dicelang/DiceExpressionType.java b/dice-lang/src/main/java/bjc/dicelang/DiceExpressionType.java deleted file mode 100644 index 296d751..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/DiceExpressionType.java +++ /dev/null @@ -1,49 +0,0 @@ -package bjc.dicelang; - -/** - * Enumeration for basic dice expression operators - */ -public enum DiceExpressionType { - /** - * Add two expressions - */ - ADD, - - /** - * Divide two expressions - */ - DIVIDE, - - /** - * Multiply two expressions - */ - MULTIPLY, - - /** - * Subtract two expressions - */ - SUBTRACT; - - /* - * (non-Javadoc) - * - * @see java.lang.Enum#toString() - */ - @Override - public String toString() { - switch (this) { - case ADD: - return "+"; - case DIVIDE: - return "/"; - case MULTIPLY: - return "*"; - case SUBTRACT: - return "-"; - default: - throw new IllegalArgumentException( - "Got passed a invalid ScalarExpressionType " - + this + ". WAT"); - } - }; -}
\ No newline at end of file diff --git a/dice-lang/src/main/java/bjc/dicelang/Die.java b/dice-lang/src/main/java/bjc/dicelang/Die.java deleted file mode 100644 index 192daaa..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/Die.java +++ /dev/null @@ -1,71 +0,0 @@ -package bjc.dicelang; - -import java.util.Random; - -/** - * A single polyhedral dice - * - * @author ben - * - */ -public class Die implements IDiceExpression { - /** - * Random # gen to use for dice - */ - private static Random rng = new Random(); - - /** - * Number of sides this die has - */ - private int nSides; - - /** - * Create a die with the specified number of sides - * - * @param nSides - * The number of sides this dice has - */ - public Die(int nSides) { - if (nSides < 1) { - throw new UnsupportedOperationException( - "Dice with less than 1 side are not supported"); - } - - this.nSides = nSides; - } - - @Override - public boolean canOptimize() { - return nSides == 1; - } - - @Override - public int optimize() { - if (nSides != 1) { - throw new UnsupportedOperationException( - "Can't optimize " + nSides + "-sided dice"); - } - - return 1; - } - - /* - * (non-Javadoc) - * - * @see bjc.utils.dice.IDiceExpression#roll() - */ - @Override - public int roll() { - return rng.nextInt(nSides) + 1; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - return "d" + nSides; - } -} diff --git a/dice-lang/src/main/java/bjc/dicelang/IDiceExpression.java b/dice-lang/src/main/java/bjc/dicelang/IDiceExpression.java deleted file mode 100644 index acb1d4d..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/IDiceExpression.java +++ /dev/null @@ -1,91 +0,0 @@ -package bjc.dicelang; - -import bjc.utils.funcutils.StringUtils; - -/** - * An expression for something that can be rolled like a polyhedral die - * - * @author ben - * - */ -@FunctionalInterface -public interface IDiceExpression { - /** - * Parse a string into an expression. - * - * It can accept the following types of expressions - * <ul> - * <li>Simple integers - '2'</li> - * <li>Simple dice - 'd6'</li> - * <li>Groups of simple dice - '2d6'</li> - * <li>Number concatenation - '2c6'</li> - * <li>Dice concatenation - '1d10c1d10</li> - * </ul> - * - * Dice concatenation is like using 2 d10s to emulate a d100, so - * instead of adding them, it reads them side by side. - * - * @param expression - * The string to convert to an expression - * - * @return The string, converted into expression form - */ - static IDiceExpression toExpression(String expression) { - String literalData = expression; - - if (StringUtils.containsInfixOperator(literalData, "c")) { - // Parse a compound die - String[] strangs = literalData.split("c"); - - return new CompoundDice(strangs); - } else if (StringUtils.containsInfixOperator(literalData, "d")) { - // Handle groups of similiar dice - return ComplexDice.fromString(literalData); - } else if (literalData.matches("\\Ad\\d+\\Z")) { - // Handle people who put 'd6' instead of '1d6' - return new Die(Integer.parseInt(literalData.substring(1))); - } else { - // Parse a scalar number - try { - return new ScalarDie(Integer.parseInt(literalData)); - } catch (NumberFormatException nfex) { - UnsupportedOperationException usex = new UnsupportedOperationException( - "Found malformed leaf token " + expression); - - usex.initCause(nfex); - - throw usex; - } - } - } - - /** - * 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/OperatorDiceExpression.java b/dice-lang/src/main/java/bjc/dicelang/OperatorDiceExpression.java deleted file mode 100644 index f86773d..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/OperatorDiceExpression.java +++ /dev/null @@ -1,96 +0,0 @@ -package bjc.dicelang; - -/** - * Implements a class for combining two dice with an operator - * - * @author ben - * - */ -public class OperatorDiceExpression implements IDiceExpression { - /** - * The operator to use for combining the dice - */ - private DiceExpressionType expressionType; - - /** - * The dice on the left side of the expression - */ - private IDiceExpression leftExpression; - - /** - * The dice on the right side of the expression - */ - private IDiceExpression rightExpression; - - /** - * Create a new compound expression using the specified parameters - * - * @param right - * The die on the right side of the expression - * @param left - * The die on the left side of the expression - * @param type - * The operator to use for combining the dices - */ - public OperatorDiceExpression(IDiceExpression right, - IDiceExpression left, DiceExpressionType type) { - this.rightExpression = right; - this.leftExpression = left; - this.expressionType = type; - } - - /* - * (non-Javadoc) - * - * @see bjc.utils.dice.IDiceExpression#roll() - */ - @Override - public int roll() { - /* - * Handle each operator - */ - switch (expressionType) { - case ADD: - return rightExpression.roll() + leftExpression.roll(); - case SUBTRACT: - return rightExpression.roll() - leftExpression.roll(); - case MULTIPLY: - return rightExpression.roll() * leftExpression.roll(); - case DIVIDE: - /* - * Round to keep results as integers. We don't really have - * any need for floating-point dice, and continuous - * probability is a pain - */ - try { - return rightExpression.roll() / leftExpression.roll(); - } catch (ArithmeticException aex) { - UnsupportedOperationException usex = new UnsupportedOperationException( - "Attempted to divide by zero." - + " Problematic expression is " - + leftExpression); - - usex.initCause(aex); - - throw usex; - } - default: - throw new IllegalArgumentException( - "Got passed a invalid ScalarExpressionType (" - + expressionType + "). WAT"); - - } - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - return "dice-exp[type=" + expressionType + ", l=" - + leftExpression.toString() + ", r=" - + rightExpression.toString() + "]"; - } -}
\ No newline at end of file diff --git a/dice-lang/src/main/java/bjc/dicelang/PolyhedralDice.java b/dice-lang/src/main/java/bjc/dicelang/PolyhedralDice.java deleted file mode 100644 index 3ac9420..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/PolyhedralDice.java +++ /dev/null @@ -1,149 +0,0 @@ -package bjc.dicelang; - -/** - * Utility class that produces common polyhedral dice - * - * @author ben - * - */ -public class PolyhedralDice { - /** - * Produce a single d10 - * - * @return A single d10 - */ - public static IDiceExpression d10() { - return d10(1); - } - - /** - * Produce the specified number of 10-sided dice - * - * @param nDice - * The number of ten-sided dice to produce - * @return A group of ten-sided dice of the specified size - */ - public static IDiceExpression d10(int nDice) { - return new ComplexDice(nDice, 10); - } - - /** - * Produce a single d100 - * - * @return A single d100 - */ - public static IDiceExpression d100() { - return d100(1); - } - - /** - * Produce the specified number of 100-sided dice - * - * @param nDice - * The number of hundred-sided dice to produce - * @return A group of hundred-sided dice of the specified size - */ - public static IDiceExpression d100(int nDice) { - return new ComplexDice(nDice, 100); - } - - /** - * Produce a single d12 - * - * @return A single d12 - */ - public static IDiceExpression d12() { - return d12(1); - } - - /** - * Produce the specified number of 12-sided dice - * - * @param nDice - * The number of twelve-sided dice to produce - * @return A group of twelve-sided dice of the specified size - */ - public static IDiceExpression d12(int nDice) { - return new ComplexDice(nDice, 12); - } - - /** - * Produce a single d20 - * - * @return A single d20 - */ - public static IDiceExpression d20() { - return d20(1); - } - - /** - * Produce the specified number of 20-sided dice - * - * @param nDice - * The number of twenty-sided dice to produce - * @return A group of twenty-sided dice of the specified size - */ - public static IDiceExpression d20(int nDice) { - return new ComplexDice(nDice, 20); - } - - /** - * Produce a single d4 - * - * @return A single d4 - */ - public static IDiceExpression d4() { - return d4(1); - } - - /** - * Produce the specified number of 4-sided dice - * - * @param nDice - * The number of four-sided dice to produce - * @return A group of four-sided dice of the specified size - */ - public static IDiceExpression d4(int nDice) { - return new ComplexDice(nDice, 4); - } - - /** - * Produce a single d6 - * - * @return A single d6 - */ - public static IDiceExpression d6() { - return d6(1); - } - - /** - * Produce the specified number of 6-sided dice - * - * @param nDice - * The number of six-sided dice to produce - * @return A group of six-sided dice of the specified size - */ - public static IDiceExpression d6(int nDice) { - return new ComplexDice(nDice, 6); - } - - /** - * Produce a single d8 - * - * @return A single d8 - */ - public static IDiceExpression d8() { - return d8(1); - } - - /** - * Produce the specified number of 8-sided dice - * - * @param nDice - * The number of eight-sided dice to produce - * @return A group of eight-sided dice of the specified size - */ - public static IDiceExpression d8(int nDice) { - return new ComplexDice(nDice, 8); - } -} diff --git a/dice-lang/src/main/java/bjc/dicelang/ReferenceDiceExpression.java b/dice-lang/src/main/java/bjc/dicelang/ReferenceDiceExpression.java deleted file mode 100644 index 483545b..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ReferenceDiceExpression.java +++ /dev/null @@ -1,76 +0,0 @@ -package bjc.dicelang; - -import java.util.Map; - -/** - * A dice expression that refers to a variable bound in a mutable - * enviroment - * - * @author ben - * - */ -public class ReferenceDiceExpression implements IDiceExpression { - /** - * The enviroment to do variable dereferencing against - */ - private Map<String, IDiceExpression> enviroment; - - /** - * The name of the bound variable - */ - private String variableName; - - /** - * Create a new reference dice expression referring to the given name - * in an enviroment - * - * @param name - * The name of the bound variable - * @param env - * The enviroment to resolve the variable against - */ - public ReferenceDiceExpression(String name, - Map<String, IDiceExpression> env) { - this.variableName = name; - this.enviroment = env; - } - - /** - * Get the name of the referenced variable - * - * @return the name of the referenced variable - */ - public String getName() { - return variableName; - } - - /* - * (non-Javadoc) - * - * @see bjc.utils.dice.IDiceExpression#roll() - */ - @Override - public int roll() { - if (!enviroment.containsKey(variableName)) { - throw new UnsupportedOperationException( - "Attempted to reference undefined variable " - + variableName); - } - - return enviroment.get(variableName).roll(); - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - if (enviroment.containsKey(variableName)) { - return enviroment.get(variableName).toString(); - } - - return variableName; - } -}
\ 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 deleted file mode 100644 index 8d31d15..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ScalarDie.java +++ /dev/null @@ -1,54 +0,0 @@ -package bjc.dicelang; - -/** - * A die that represents a static number - * - * @author ben - * - */ -public class ScalarDie implements IDiceExpression { - /** - * The represented number - */ - private int number; - - /** - * Create a dice with the specified number - * - * @param num - * The number used for the dice - */ - public ScalarDie(int num) { - this.number = num; - } - - @Override - public boolean canOptimize() { - return true; - } - - @Override - public int optimize() { - return number; - } - - /* - * (non-Javadoc) - * - * @see bjc.utils.dice.IDiceExpression#roll() - */ - @Override - public int roll() { - return number; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - return Integer.toString(number); - } -}
\ 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 deleted file mode 100644 index 2b9eaa4..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ast/ArithmeticCollapser.java +++ /dev/null @@ -1,192 +0,0 @@ -package bjc.dicelang.ast; - -import java.util.function.BinaryOperator; - -import bjc.utils.data.IPair; -import bjc.utils.data.Pair; -import bjc.utils.funcdata.IList; -import bjc.utils.funcdata.ITree; -import bjc.utils.funcdata.Tree; - -import bjc.dicelang.ast.nodes.IDiceASTNode; -import bjc.dicelang.ast.nodes.OperatorDiceNode; - -/** - * Responsible for collapsing arithmetic operators - * - * @author ben - * - */ -final class ArithmeticCollapser implements IOperatorCollapser { - // The type of operator we're collapsing - private OperatorDiceNode type; - - // The operator to use to collapse operators - private BinaryOperator<Integer> valueOp; - - private int initialValue; - - public ArithmeticCollapser(OperatorDiceNode type, - BinaryOperator<Integer> valueOp, int initVal) { - this.type = type; - this.valueOp = valueOp; - this.initialValue = initVal; - } - - @Override - public IPair<IResult, ITree<IDiceASTNode>> apply( - IList<IPair<IResult, ITree<IDiceASTNode>>> nodes) { - IPair<IResult, ITree<IDiceASTNode>> initialState = new Pair<>( - new IntegerResult(initialValue), new Tree<>(type)); - - BinaryOperator<IPair<IResult, ITree<IDiceASTNode>>> reducer = ( - currentState, accumulatedState) -> { - // Force evaluation of accumulated state to prevent - // certain bugs from occuring - // accumulatedState.merge((l, r) -> null); - - return reduceStates(accumulatedState, currentState); - }; - - IPair<IResult, ITree<IDiceASTNode>> reducedState = nodes - .reduceAux(initialState, reducer, (state) -> state); - - return reducedState; - } - - private IList<IResult> combineArrayResults(IResult accumulatedValue, - IResult currentValue) { - IList<IResult> currentList = ((ArrayResult) currentValue) - .getValue(); - IList<IResult> accumulatedList = ((ArrayResult) accumulatedValue) - .getValue(); - - if (currentList.getSize() != accumulatedList.getSize()) { - throw new UnsupportedOperationException( - "Can only apply operations to equal-length arrays"); - } - - IList<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( - IResult accumulatedValue, ITree<IDiceASTNode> accumulatedTree, - IResult currentValue) { - if (accumulatedValue.getType() == ResultType.DUMMY - || currentValue.getType() == ResultType.DUMMY) { - DummyResult result = new DummyResult( - "Found dummy result with either accumulated dummy (" - + ((DummyResult) accumulatedValue).getData() - + ") or current dummy (" - + ((DummyResult) currentValue).getData() - + ")."); - - return new Pair<>(result, accumulatedTree); - } - - boolean currentIsInt = currentValue - .getType() == ResultType.INTEGER; - boolean accumulatedIsInt = accumulatedValue - .getType() == ResultType.INTEGER; - - if (!currentIsInt) { - if (!accumulatedIsInt) { - IList<IResult> resultList = combineArrayResults( - accumulatedValue, currentValue); - - return new Pair<>(new ArrayResult(resultList), - accumulatedTree); - } - - IList<IResult> resultList = halfCombineLists( - ((ArrayResult) currentValue).getValue(), - accumulatedValue, true); - - return new Pair<>(new ArrayResult(resultList), - accumulatedTree); - } else if (!accumulatedIsInt) { - IList<IResult> resultList = halfCombineLists( - ((ArrayResult) accumulatedValue).getValue(), - currentValue, false); - - return new Pair<>(new ArrayResult(resultList), - accumulatedTree); - } - - int accumulatedInt = ((IntegerResult) accumulatedValue).getValue(); - int currentInt = ((IntegerResult) currentValue).getValue(); - - int combinedValue = valueOp.apply(accumulatedInt, currentInt); - - return new Pair<>(new IntegerResult(combinedValue), - accumulatedTree); - } - - private IList<IResult> halfCombineLists(IList<IResult> list, - IResult scalar, boolean scalarLeft) { - if (scalar.getType() != ResultType.INTEGER) { - throw new UnsupportedOperationException( - "Nested array operations not supported"); - } - - int scalarInt = ((IntegerResult) scalar).getValue(); - - return list.map((element) -> { - if (element.getType() != ResultType.INTEGER) { - throw new UnsupportedOperationException( - "Nested array operations not supported"); - } - - int elementInt = ((IntegerResult) element).getValue(); - - IResult combinedValue; - - if (scalarLeft) { - combinedValue = new IntegerResult( - valueOp.apply(scalarInt, elementInt)); - } else { - combinedValue = new IntegerResult( - valueOp.apply(elementInt, scalarInt)); - } - - 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/ArrayResult.java b/dice-lang/src/main/java/bjc/dicelang/ast/ArrayResult.java deleted file mode 100644 index ac78287..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ast/ArrayResult.java +++ /dev/null @@ -1,43 +0,0 @@ -package bjc.dicelang.ast; - -import bjc.utils.funcdata.IList; - -/** - * Represents a result that is an array of other results - * - * @author ben - * - * TODO finish implementing me - */ -public class ArrayResult implements IResult { - private IList<IResult> arrayContents; - - /** - * Create a new array-valued result - * - * @param results - * The results in the array - */ - public ArrayResult(IList<IResult> results) { - this.arrayContents = results; - } - - @Override - public ResultType getType() { - return ResultType.ARRAY; - } - - /** - * Get the value of this result - * - * @return The value of this result - */ - public IList<IResult> getValue() { - return arrayContents; - } - - @Override - public String toString() { - return arrayContents.toString(); - } -} diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTEvaluator.java b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTEvaluator.java deleted file mode 100644 index cef2e19..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTEvaluator.java +++ /dev/null @@ -1,321 +0,0 @@ -package bjc.dicelang.ast; - -import java.util.function.Supplier; - -import bjc.utils.data.IHolder; -import bjc.utils.data.IPair; -import bjc.utils.data.Identity; -import bjc.utils.data.LazyPair; -import bjc.utils.data.Pair; -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.FunctionalMap; -import bjc.utils.funcdata.IList; -import bjc.utils.funcdata.IMap; -import bjc.utils.funcdata.ITree; -import bjc.utils.funcdata.Tree; - -import bjc.dicelang.ComplexDice; -import bjc.dicelang.ast.nodes.DiceASTType; -import bjc.dicelang.ast.nodes.DiceLiteralNode; -import bjc.dicelang.ast.nodes.DiceLiteralType; -import bjc.dicelang.ast.nodes.IDiceASTNode; -import bjc.dicelang.ast.nodes.ILiteralDiceNode; -import bjc.dicelang.ast.nodes.IntegerLiteralNode; -import bjc.dicelang.ast.nodes.OperatorDiceNode; -import bjc.dicelang.ast.nodes.VariableDiceNode; - -/** - * Evaluate a dice AST to an integer value - * - * @author ben - * - */ -public class DiceASTEvaluator { - private static IResult bindLiteralValue(IDiceASTNode leafNode, - IMap<String, ITree<IDiceASTNode>> enviroment) { - String variableName = ((VariableDiceNode) leafNode).getVariable(); - - if (enviroment.containsKey(variableName)) { - IResult result = evaluateAST(enviroment.get(variableName), - enviroment); - - return result; - } - - // Return a DummyResult to handle lets properly - return new DummyResult( - "Attempted to deref unbound variable " + variableName); - } - - /** - * 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 IMap<IDiceASTNode, IOperatorCollapser> buildOperations( - IMap<String, ITree<IDiceASTNode>> enviroment) { - IMap<IDiceASTNode, IOperatorCollapser> operatorCollapsers = new FunctionalMap<>(); - - operatorCollapsers.put(OperatorDiceNode.ADD, - new ArithmeticCollapser(OperatorDiceNode.ADD, - (left, right) -> left + right, 0)); - - operatorCollapsers.put(OperatorDiceNode.SUBTRACT, - new ArithmeticCollapser(OperatorDiceNode.SUBTRACT, - (left, right) -> left - right, 0)); - - operatorCollapsers.put(OperatorDiceNode.MULTIPLY, - new ArithmeticCollapser(OperatorDiceNode.MULTIPLY, - (left, right) -> left * right, 1)); - - operatorCollapsers.put(OperatorDiceNode.DIVIDE, - new ArithmeticCollapser(OperatorDiceNode.DIVIDE, - (left, right) -> left / right, 1)); - - operatorCollapsers.put(OperatorDiceNode.ASSIGN, (nodes) -> { - return parseBinding(enviroment, nodes); - }); - - operatorCollapsers.put(OperatorDiceNode.COMPOUND, - new ArithmeticCollapser(OperatorDiceNode.COMPOUND, - (left, right) -> { - return Integer.parseInt(Integer.toString(left) - + Integer.toString(right)); - }, 0)); - - operatorCollapsers.put(OperatorDiceNode.GROUP, - DiceASTEvaluator::parseGroup); - - operatorCollapsers.put(OperatorDiceNode.LET, (nodes) -> { - // @TODO Fix lets prematurely evaluating things - return parseLet(enviroment, nodes); - }); - - operatorCollapsers.put(OperatorDiceNode.ARRAY, (nodes) -> { - - // This is so that arrays respect lazy results properly - Supplier<IResult> resultSupplier = () -> { - IList<IResult> resultList = new FunctionalList<>(); - - nodes.forEach((node) -> { - resultList.add(node.getLeft()); - }); - - return new ArrayResult(resultList); - }; - - Supplier<ITree<IDiceASTNode>> treeSupplier = () -> { - ITree<IDiceASTNode> returnedTree = new Tree<>( - OperatorDiceNode.ARRAY); - - nodes.forEach((element) -> { - returnedTree.addChild(element.getRight()); - }); - - return returnedTree; - }; - - return new LazyPair<>(resultSupplier, treeSupplier); - }); - - return operatorCollapsers; - } - - private static void doArrayAssign( - IMap<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); - } - - /** - * Evaluate the provided AST to a numeric value - * - * @param expression - * The expression to evaluate - * @param enviroment - * The enviroment to look up variables in - * @return The integer value of the expression - */ - public static IResult evaluateAST(ITree<IDiceASTNode> expression, - IMap<String, ITree<IDiceASTNode>> enviroment) { - IMap<IDiceASTNode, IOperatorCollapser> collapsers = buildOperations( - enviroment); - - return expression.collapse( - (node) -> evaluateLeaf(node, enviroment), collapsers::get, - (pair) -> pair.getLeft()); - } - - private static IPair<IResult, ITree<IDiceASTNode>> evaluateLeaf( - IDiceASTNode leafNode, - IMap<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<>(() -> { - return bindLiteralValue(leafNode, enviroment); - }, () -> returnedAST); - - case OPERATOR: - default: - throw new UnsupportedOperationException( - "Node '" + leafNode + "' cannot be a leaf."); - } - } - - private static IResult evaluateLiteral(IDiceASTNode leafNode) { - DiceLiteralType literalType = ((ILiteralDiceNode) leafNode) - .getLiteralType(); - - switch (literalType) { - case DICE: - int diceRoll = ((DiceLiteralNode) leafNode).getValue() - .roll(); - - return new IntegerResult(diceRoll); - case INTEGER: - int val = ((IntegerLiteralNode) leafNode).getValue(); - - return new IntegerResult(val); - default: - throw new UnsupportedOperationException("Literal value '" - + leafNode + "' is of a type (" + literalType - + ") not currently supported."); - } - } - - private static IPair<IResult, ITree<IDiceASTNode>> parseBinding( - IMap<String, ITree<IDiceASTNode>> enviroment, - IList<IPair<IResult, ITree<IDiceASTNode>>> nodes) { - if (nodes.getSize() != 2) { - throw new UnsupportedOperationException( - "Can only bind nodes with two children. Problem children are " - + nodes); - } - - IPair<IResult, ITree<IDiceASTNode>> nameNode = nodes.getByIndex(0); - IPair<IResult, ITree<IDiceASTNode>> valueNode = nodes - .getByIndex(1); - - return nameNode.bindRight((nameTree) -> { - return valueNode.bind((valueValue, valueTree) -> { - if (DiceASTUtils.containsSimpleVariable(nameTree)) { - String varName = nameTree.transformHead((nameNod) -> { - return ((VariableDiceNode) nameNod).getVariable(); - }); - - enviroment.put(varName, valueTree); - - return new Pair<>(valueValue, nameTree); - } else if (nameTree.getHead() == OperatorDiceNode.ARRAY) { - if (valueTree.getHead() == OperatorDiceNode.ARRAY) { - if (nameTree.getChildrenCount() != valueTree - .getChildrenCount()) { - throw new UnsupportedOperationException( - "Array assignment must be between two equal length arrays"); - } - - IHolder<Integer> childCount = new Identity<>(0); - - nameTree.doForChildren((child) -> { - doArrayAssign(enviroment, nameNode, nameTree, - valueTree, childCount, child); - - childCount.transform(val -> val + 1); - }); - - return new Pair<>(valueValue, nameTree); - } - - nameTree.doForChildren((child) -> { - String varName = child.transformHead((nameNod) -> { - return ((VariableDiceNode) nameNod) - .getVariable(); - }); - - enviroment.put(varName, valueTree); - }); - - return new Pair<>(valueValue, nameTree); - } - - throw new UnsupportedOperationException( - "Assigning to complex variables isn't supported. Problem node is " - + nameNode.getRight()); - }); - }); - } - - private static IPair<IResult, ITree<IDiceASTNode>> parseGroup( - IList<IPair<IResult, ITree<IDiceASTNode>>> nodes) { - if (nodes.getSize() != 2) { - throw new UnsupportedOperationException( - "Can only form a group from two dice"); - } - - IPair<IResult, ITree<IDiceASTNode>> numberDiceNode = nodes - .getByIndex(0); - IPair<IResult, ITree<IDiceASTNode>> diceTypeNode = nodes - .getByIndex(1); - - return numberDiceNode.bind((numberDiceValue, numberDiceTree) -> { - return diceTypeNode.bind((diceTypeValue, diceTypeTree) -> { - ComplexDice cDice = new ComplexDice( - ((IntegerResult) numberDiceValue).getValue(), - ((IntegerResult) diceTypeValue).getValue()); - - return new Pair<>(new IntegerResult(cDice.roll()), - new Tree<>(OperatorDiceNode.GROUP, numberDiceTree, - diceTypeTree)); - }); - }); - } - - private static IPair<IResult, ITree<IDiceASTNode>> parseLet( - IMap<String, ITree<IDiceASTNode>> enviroment, - IList<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(); - - IMap<String, ITree<IDiceASTNode>> letEnviroment = enviroment - .extend(); - - System.out.println("Evaluating tree for bound values"); - - evaluateAST(bindTree, letEnviroment); - - IResult exprResult = evaluateAST(expressionTree, letEnviroment); - - IList<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 deleted file mode 100644 index 305c9af..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTInliner.java +++ /dev/null @@ -1,125 +0,0 @@ -package bjc.dicelang.ast; - -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.IList; -import bjc.utils.funcdata.IMap; -import bjc.utils.funcdata.ITree; -import bjc.utils.funcdata.Tree; - -import bjc.dicelang.ast.nodes.DiceASTType; -import bjc.dicelang.ast.nodes.IDiceASTNode; -import bjc.dicelang.ast.nodes.VariableDiceNode; - -/** - * Inline variables in a dice AST - * - * @author ben - * - */ -public class DiceASTInliner { - /** - * Inline all the variables in the AST - * - * @param ast - * The AST to inline variables into - * @param enviroment - * The enviroment to inline from - * @return The inlined AST - */ - public static ITree<IDiceASTNode> inlineAll(ITree<IDiceASTNode> ast, - IMap<String, ITree<IDiceASTNode>> enviroment) { - // Tell the compiler that the null is for the entire varargs - // parameter, not a single one with a null value - return selectiveInline(ast, enviroment, (String[]) null); - } - - private static ITree<IDiceASTNode> inlineNode(IDiceASTNode node, - IMap<String, ITree<IDiceASTNode>> enviroment, - boolean specificInline, IList<String> variableNames) { - // Only variables get inlined - if (node.getType() != DiceASTType.VARIABLE) { - return new Tree<>(node); - } - - // Get the name of what we're inlining - String variableName = ((VariableDiceNode) node).getVariable(); - - // If we're inlining only certain variables, do so - if (specificInline) { - // Only inline the variable if we're supposed to - if (variableNames.contains(variableName)) { - // You can't inline non-existent variables - if (!enviroment.containsKey(variableName)) { - throw new UnsupportedOperationException( - "Attempted to inline non-existant variable " - + variableName); - } - - // Return the tree for the variable - return enviroment.get(variableName); - } - } else { - // You can't inline non-existent variables - if (!enviroment.containsKey(variableName)) { - throw new UnsupportedOperationException( - "Attempted to inline non-existant variable " - + variableName); - } - - // Return the tree for the variable - return enviroment.get(variableName); - } - - // return new Tree<>(node); - } - - /** - * Inline the specified variables in the AST - * - * @param ast - * The AST to inline variables into - * @param enviroment - * The enviroment to inline from - * @param variables - * The variables to inline - * @return The inlined AST - */ - public static ITree<IDiceASTNode> selectiveInline( - ITree<IDiceASTNode> ast, - IMap<String, ITree<IDiceASTNode>> enviroment, - IList<String> variables) { - return selectiveInline(ast, enviroment, - variables.toArray(new String[0])); - } - - /** - * Inline the specified variables in the AST - * - * @param ast - * The AST to inline variables into - * @param enviroment - * The enviroment to inline from - * @param variables - * The variables to inline - * @return The inlined AST - */ - public static ITree<IDiceASTNode> selectiveInline( - ITree<IDiceASTNode> ast, - IMap<String, ITree<IDiceASTNode>> enviroment, - String... variables) { - // If we're selectively inlining, do so - if (variables != null && variables.length > 0) { - IList<String> variableNames = new FunctionalList<>(variables); - - // Selectively inline each tree node - return ast.flatMapTree((node) -> { - return inlineNode(node, enviroment, true, variableNames); - }); - } - - // Inline everything in each node - return ast.flatMapTree((node) -> { - return inlineNode(node, enviroment, false, null); - }); - } -} diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTOptimizer.java b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTOptimizer.java deleted file mode 100644 index d7fc23c..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTOptimizer.java +++ /dev/null @@ -1,60 +0,0 @@ -package bjc.dicelang.ast; - -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.IList; -import bjc.utils.funcdata.IMap; -import bjc.utils.funcdata.ITree; - -import bjc.dicelang.ast.nodes.IDiceASTNode; -import bjc.dicelang.ast.optimization.IOptimizationPass; - -/** - * Contains optimizations appliable to a dice AST - * - * @author ben - * - */ -public class DiceASTOptimizer { - private IList<IOptimizationPass> passes; - - /** - * Create a new optimizer - */ - public DiceASTOptimizer() { - passes = new FunctionalList<>(); - } - - /** - * Add a pass to the list of optimization passes - * - * @param pass - * The pass to add - */ - public void addPass(IOptimizationPass pass) { - passes.add(pass); - } - - /** - * Optimize the passed in tree - * - * @param ast - * The tree to optimize - * @param enviroment - * The enviroment for variable references - * @return The optimized tree - */ - public ITree<IDiceASTNode> optimizeTree(ITree<IDiceASTNode> ast, - IMap<String, ITree<IDiceASTNode>> enviroment) { - 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/DiceASTParser.java b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTParser.java deleted file mode 100644 index 9a36951..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTParser.java +++ /dev/null @@ -1,160 +0,0 @@ -package bjc.dicelang.ast; - -import java.util.Deque; -import java.util.InputMismatchException; -import java.util.function.Function; -import java.util.function.Predicate; - -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.FunctionalMap; -import bjc.utils.funcdata.IList; -import bjc.utils.funcdata.IMap; -import bjc.utils.funcdata.ITree; -import bjc.utils.funcdata.Tree; -import bjc.utils.funcutils.StringUtils; -import bjc.utils.parserutils.TreeConstructor; - -import bjc.dicelang.IDiceExpression; -import bjc.dicelang.ast.nodes.DiceLiteralNode; -import bjc.dicelang.ast.nodes.DiceLiteralType; -import bjc.dicelang.ast.nodes.IDiceASTNode; -import bjc.dicelang.ast.nodes.ILiteralDiceNode; -import bjc.dicelang.ast.nodes.IntegerLiteralNode; -import bjc.dicelang.ast.nodes.OperatorDiceNode; -import bjc.dicelang.ast.nodes.VariableDiceNode; - -/** - * Parse a string expression into AST form. Doesn't do anything else - * - * @author ben - * - */ -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."); - } - } - - if (leafNode.matches("[+-]?\\d*\\.\\d+")) { - throw new InputMismatchException( - "Floating point literals are not supported"); - } - - 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 - * - * @param tokens - * The list of tokens to convert - * @return An AST built from the tokens - */ - public static ITree<IDiceASTNode> createFromString( - IList<String> tokens) { - Predicate<String> specialPicker = (operator) -> { - if (StringUtils.containsOnly(operator, "\\[")) { - return true; - } else if (StringUtils.containsOnly(operator, "\\]")) { - return true; - } - - return false; - }; - - IMap<String, Function<Deque<ITree<String>>, ITree<String>>> operators = new FunctionalMap<>(); - - operators.put("[", (queuedTrees) -> { - Tree<String> openArray = new Tree<>("["); - - return openArray; - }); - - operators.put("]", (queuedTrees) -> { - return parseCloseArray(queuedTrees); - }); - - ITree<String> rawTokens = TreeConstructor.constructTree(tokens, - (token) -> { - return isOperatorNode(token); - }, specialPicker, operators::get); - - ITree<IDiceASTNode> tokenizedTree = rawTokens.rebuildTree( - DiceASTParser::convertLeafNode, - DiceASTParser::convertOperatorNode); - - return tokenizedTree; - } - - private static boolean isOperatorNode(String token) { - if (StringUtils.containsOnly(token, "\\[")) { - return true; - } else if (StringUtils.containsOnly(token, "\\]")) { - return true; - } - - if (token.equals("[]")) { - // This is a synthetic operator, constructed by [ and ] - return true; - } - - try { - OperatorDiceNode.fromString(token); - return true; - } catch (@SuppressWarnings("unused") IllegalArgumentException iaex) { - // We don't care about details - return false; - } - } - - private static ITree<String> parseCloseArray( - Deque<ITree<String>> queuedTrees) { - IList<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("["); - } -} diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTReferenceChecker.java b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTReferenceChecker.java deleted file mode 100644 index 34414c5..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTReferenceChecker.java +++ /dev/null @@ -1,61 +0,0 @@ -package bjc.dicelang.ast; - -import java.util.function.Consumer; - -import bjc.utils.data.IHolder; - -import bjc.dicelang.ast.nodes.DiceASTType; -import bjc.dicelang.ast.nodes.IDiceASTNode; -import bjc.dicelang.ast.nodes.VariableDiceNode; - -/** - * Check if the specified node references a particular variable - * - * @author ben - * - */ -public final class DiceASTReferenceChecker - implements Consumer<IDiceASTNode> { - /** - * This is true if the specified node references the set variable - */ - private IHolder<Boolean> referencesVariable; - - private String varName; - - /** - * Create a new reference checker - * - * @param referencesVar - * The holder of whether the variable is referenced or not - * @param varName - * The variable to check for references in - */ - public DiceASTReferenceChecker(IHolder<Boolean> referencesVar, - String varName) { - this.referencesVariable = referencesVar; - this.varName = varName; - } - - @Override - public void accept(IDiceASTNode astNode) { - referencesVariable.transform((bool) -> isDirectReference(astNode)); - } - - /** - * Check if a given AST node directly references the specified variable - * - * @param astNode - * The node to check - * @return Whether or not the node directly the variable - */ - private boolean isDirectReference(IDiceASTNode astNode) { - if (astNode.getType() == DiceASTType.VARIABLE) { - VariableDiceNode node = (VariableDiceNode) astNode; - - return node.getVariable().equals(varName); - } - - return false; - } -}
\ No newline at end of file diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTReferenceSanitizer.java b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTReferenceSanitizer.java deleted file mode 100644 index d8f658e..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTReferenceSanitizer.java +++ /dev/null @@ -1,201 +0,0 @@ -package bjc.dicelang.ast; - -import bjc.utils.data.IHolder; -import bjc.utils.data.Identity; -import bjc.utils.funcdata.IMap; -import bjc.utils.funcdata.ITree; -import bjc.utils.funcdata.TopDownTransformResult; -import bjc.utils.funcdata.Tree; - -import bjc.dicelang.ast.nodes.IDiceASTNode; -import bjc.dicelang.ast.nodes.OperatorDiceNode; -import bjc.dicelang.ast.nodes.VariableDiceNode; - -/** - * Sanitize the references in an AST so that a variable that refers to - * itself in its definition has the occurance of it replaced with its - * previous definition - * - * @author ben - * - */ -public class DiceASTReferenceSanitizer { - private static ITree<IDiceASTNode> doSanitize(ITree<IDiceASTNode> ast, - IMap<String, ITree<IDiceASTNode>> enviroment) { - if (ast.getChildrenCount() != 2) { - throw new UnsupportedOperationException( - "Assignment must have two arguments."); - } - - ITree<IDiceASTNode> nameTree = ast.getChild(0); - ITree<IDiceASTNode> valueTree = ast.getChild(1); - - if (!DiceASTUtils.containsSimpleVariable(nameTree)) { - if (nameTree.getHead() == OperatorDiceNode.ARRAY) { - IHolder<Boolean> allSimpleVariables = new Identity<>(true); - - nameTree.doForChildren((child) -> { - if (allSimpleVariables.getValue()) { - boolean isSimple = DiceASTUtils - .containsSimpleVariable(child); - - allSimpleVariables.replace(isSimple); - } - }); - - if (!allSimpleVariables.getValue()) { - throw new UnsupportedOperationException( - "Array assignment must be between variables and" - + " a expression/array of expressions"); - } - - if (valueTree.getHead() == OperatorDiceNode.ARRAY) { - if (nameTree.getChildrenCount() != valueTree - .getChildrenCount()) { - throw new UnsupportedOperationException( - "Array assignment between arrays must be" - + " between two arrays of equal length"); - } - } - } else { - throw new UnsupportedOperationException( - "Assignment must be between a variable and a expression"); - } - } - - if (nameTree.getHead() == OperatorDiceNode.ARRAY) { - if (valueTree.getHead() == OperatorDiceNode.ARRAY) { - IHolder<Integer> childCounter = new Identity<>(0); - - ITree<IDiceASTNode> returnTree = new Tree<>( - OperatorDiceNode.ARRAY); - - nameTree.doForChildren((child) -> { - String variableName = child.transformHead((node) -> { - return ((VariableDiceNode) node).getVariable(); - }); - - ITree<IDiceASTNode> currentValue = valueTree - .getChild(childCounter.getValue()); - - ITree<IDiceASTNode> sanitizedSubtree = doSingleSanitize( - ast, enviroment, child, currentValue, - variableName); - - if (sanitizedSubtree == null) { - ITree<IDiceASTNode> oldTree = new Tree<>( - ast.getHead(), child, currentValue); - - returnTree.addChild(oldTree); - } else { - returnTree.addChild(sanitizedSubtree); - } - - childCounter.transform((count) -> count + 1); - }); - - return returnTree; - } - - ITree<IDiceASTNode> returnTree = new Tree<>( - OperatorDiceNode.ARRAY); - - nameTree.doForChildren((child) -> { - String variableName = child.transformHead( - (node) -> ((VariableDiceNode) node).getVariable()); - - ITree<IDiceASTNode> sanitizedChild = doSingleSanitize(ast, - enviroment, child, valueTree, variableName); - if (sanitizedChild == null) { - ITree<IDiceASTNode> oldTree = new Tree<>(ast.getHead(), - child, valueTree); - - returnTree.addChild(oldTree); - } else { - returnTree.addChild(sanitizedChild); - } - }); - - return returnTree; - } - - String variableName = nameTree.transformHead( - (node) -> ((VariableDiceNode) node).getVariable()); - - ITree<IDiceASTNode> sanitizedTree = doSingleSanitize(ast, - enviroment, nameTree, valueTree, variableName); - - if (sanitizedTree == null) { - return ast; - } - - return sanitizedTree; - } - - private static ITree<IDiceASTNode> doSingleSanitize( - ITree<IDiceASTNode> ast, - IMap<String, ITree<IDiceASTNode>> enviroment, - ITree<IDiceASTNode> nameTree, ITree<IDiceASTNode> valueTree, - String variableName) { - if (enviroment.containsKey(variableName)) { - // @ is a meta-variable standing for the left side of an - // assignment - ITree<IDiceASTNode> oldVal = enviroment.put("@", - enviroment.get(variableName)); - - // We should always inline out references to last, because it - // will always change - ITree<IDiceASTNode> inlinedValue = DiceASTInliner - .selectiveInline(valueTree, enviroment, variableName, - "last", "@"); - - if (oldVal != null) { - enviroment.put("@", oldVal); - } else { - enviroment.remove("@"); - } - - return new Tree<>(ast.getHead(), nameTree, inlinedValue); - } - - return null; - } - - /** - * Sanitize the references in an AST - * - * @param ast - * @param enviroment - * @return The sanitized AST - */ - public static ITree<IDiceASTNode> sanitize(ITree<IDiceASTNode> ast, - IMap<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 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 deleted file mode 100644 index d98c8fe..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTUtils.java +++ /dev/null @@ -1,86 +0,0 @@ -package bjc.dicelang.ast; - -import bjc.utils.funcdata.ITree; - -import bjc.dicelang.IDiceExpression; -import bjc.dicelang.ScalarDie; -import bjc.dicelang.ast.nodes.DiceASTType; -import bjc.dicelang.ast.nodes.DiceLiteralNode; -import bjc.dicelang.ast.nodes.IDiceASTNode; -import bjc.dicelang.ast.nodes.ILiteralDiceNode; -import bjc.dicelang.ast.nodes.IntegerLiteralNode; - -/** - * Functions that are useful when dealing with dice ASTs - * - * @author ben - * - */ -public class DiceASTUtils { - /** - * Check if a dice AST contains a simple variable reference - * - * @param nameTree - * The tree to check for a reference in - * @return Whether or not a dice AST contains a simple variable - * reference - */ - public static boolean containsSimpleVariable( - ITree<IDiceASTNode> nameTree) { - return nameTree.transformHead((nameNode) -> { - if (nameNode.getType() != DiceASTType.VARIABLE) { - return false; - } - - return true; - }); - } - - /** - * Convert an literal AST node to a dice expression, if possible. - * - * @param tree - * The node to convert in tree form - * @return The tree as a dice expression - * - * @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 IDiceExpression literalToExpression( - ITree<IDiceASTNode> tree) { - ILiteralDiceNode literalNode = (ILiteralDiceNode) tree.getHead(); - - switch (literalNode.getLiteralType()) { - case DICE: - return ((DiceLiteralNode) literalNode).getValue(); - case INTEGER: - return new ScalarDie( - ((IntegerLiteralNode) literalNode).getValue()); - default: - throw new UnsupportedOperationException( - "This type of literal isn't convertable to an expression"); - } - } - - /** - * Convert an literal AST node to an integer, if possible. - * - * @param tree - * The literal node to convert, as a tree - * @return The node 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 literalToInteger(ITree<IDiceASTNode> tree) { - return tree.transformHead((node) -> { - return ((ILiteralDiceNode) node).optimize(); - }); - } -} diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/DummyResult.java b/dice-lang/src/main/java/bjc/dicelang/ast/DummyResult.java deleted file mode 100644 index a84bb7c..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ast/DummyResult.java +++ /dev/null @@ -1,31 +0,0 @@ -package bjc.dicelang.ast; - -public class DummyResult implements IResult { - /* - * The reason why this result is a dummy - */ - private String dummyData; - - public DummyResult(String data) { - dummyData = data; - } - - /** - * Get the data in this dummy - * - * @return The reason why this result is a dummy - */ - public String getData() { - return dummyData; - } - - @Override - public ResultType getType() { - return ResultType.DUMMY; - } - - @Override - public String toString() { - return "Dummy with reason " + dummyData; - } -} diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/IOperatorCollapser.java b/dice-lang/src/main/java/bjc/dicelang/ast/IOperatorCollapser.java deleted file mode 100644 index 0efaca9..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ast/IOperatorCollapser.java +++ /dev/null @@ -1,20 +0,0 @@ -package bjc.dicelang.ast; - -import java.util.function.Function; - -import bjc.utils.data.IPair; -import bjc.utils.funcdata.IList; -import bjc.utils.funcdata.ITree; - -import bjc.dicelang.ast.nodes.IDiceASTNode; - -/** - * Alias for operator collapsers. Because 68-char types are too long - * - * @author ben - * - */ -public interface IOperatorCollapser extends - Function<IList<IPair<IResult, ITree<IDiceASTNode>>>, IPair<IResult, ITree<IDiceASTNode>>> { - // Just an alias -} diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/IResult.java b/dice-lang/src/main/java/bjc/dicelang/ast/IResult.java deleted file mode 100644 index 9a3f325..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ast/IResult.java +++ /dev/null @@ -1,16 +0,0 @@ -package bjc.dicelang.ast; - -/** - * Represents a result from an expression evaluation - * - * @author ben - * - */ -public interface IResult { - /** - * Get the type of this result - * - * @return The type of this result - */ - public ResultType getType(); -} diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/IntegerResult.java b/dice-lang/src/main/java/bjc/dicelang/ast/IntegerResult.java deleted file mode 100644 index ce61d38..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ast/IntegerResult.java +++ /dev/null @@ -1,40 +0,0 @@ -package bjc.dicelang.ast; - -/** - * Represents a integer-valued result - * - * @author ben - * - */ -public class IntegerResult implements IResult { - private int value; - - /** - * Create a new integer valued result - * - * @param val - * The value of the result - */ - public IntegerResult(int val) { - value = val; - } - - @Override - public ResultType getType() { - return ResultType.INTEGER; - } - - /** - * Get the value of this result - * - * @return The value of this result - */ - public int getValue() { - return value; - } - - @Override - public String toString() { - return Integer.toString(value); - } -} diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/ResultType.java b/dice-lang/src/main/java/bjc/dicelang/ast/ResultType.java deleted file mode 100644 index 9e3b129..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ast/ResultType.java +++ /dev/null @@ -1,22 +0,0 @@ -package bjc.dicelang.ast; - -/** - * Represents the result of a computation - * - * @author ben - * - */ -public enum ResultType { - /** - * Represents a result that is equivalent to a single integer - */ - INTEGER, - /** - * Represents a result that is an array - */ - ARRAY, - /** - * Represents something not to poke at - */ - DUMMY -} diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/DiceASTType.java b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/DiceASTType.java deleted file mode 100644 index 9feb461..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/DiceASTType.java +++ /dev/null @@ -1,27 +0,0 @@ -package bjc.dicelang.ast.nodes; - -/** - * An enum to represent the type of node an AST node is - * - * @author ben - * - */ -public enum DiceASTType { - /** - * A node that contains a literal value - */ - LITERAL, - /** - * A node that contains an operator expression - */ - OPERATOR, - /** - * A node that contains a variable reference - */ - VARIABLE; - - @Override - public String toString() { - return this.name().toLowerCase(); - } -}
\ No newline at end of file diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/DiceLiteralNode.java b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/DiceLiteralNode.java deleted file mode 100644 index b398ac6..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/DiceLiteralNode.java +++ /dev/null @@ -1,52 +0,0 @@ -package bjc.dicelang.ast.nodes; - -import bjc.dicelang.IDiceExpression; - -/** - * Represents a literal backed by a dice expression - * - * @author ben - * - */ -public class DiceLiteralNode implements ILiteralDiceNode { - private IDiceExpression expression; - - /** - * Create a new literal from an expression - * - * @param exp - * The expression to attempt to create a literal from - */ - public DiceLiteralNode(IDiceExpression exp) { - expression = exp; - } - - @Override - public boolean canOptimize() { - return expression.canOptimize(); - } - - @Override - public DiceLiteralType getLiteralType() { - return DiceLiteralType.DICE; - } - - /** - * Return the expression being represented - * - * @return The expression being represented - */ - public IDiceExpression getValue() { - return expression; - } - - @Override - public int optimize() { - return expression.optimize(); - } - - @Override - public String toString() { - return expression.toString(); - } -} diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/DiceLiteralType.java b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/DiceLiteralType.java deleted file mode 100644 index 41c6b05..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/DiceLiteralType.java +++ /dev/null @@ -1,18 +0,0 @@ -package bjc.dicelang.ast.nodes; - -/** - * Represents the type of literals that can be in an AST - * - * @author ben - * - */ -public enum DiceLiteralType { - /** - * Represents a integral constant - */ - INTEGER, - /** - * Represents a dice literal - */ - DICE; -} diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/DiceOperatorType.java b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/DiceOperatorType.java deleted file mode 100644 index 7cc1e42..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/DiceOperatorType.java +++ /dev/null @@ -1,29 +0,0 @@ -package bjc.dicelang.ast.nodes; - -/** - * Represents the different type of operators. - * - * Mostly, what distinguishes groups is that all the operators in a group - * have similiar precedence, and operate on similiar things - * - * @author ben - * - */ -public enum DiceOperatorType { - /** - * Represents operators that do math operations - */ - MATH, - /** - * Represents operators that do things with arrays - */ - ARRAY, - /** - * Represents operators that do things with dice - */ - DICE, - /** - * Represents operators that do things with expressions - */ - EXPRESSION; -} diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/IDiceASTNode.java b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/IDiceASTNode.java deleted file mode 100644 index b7bf9a6..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/IDiceASTNode.java +++ /dev/null @@ -1,23 +0,0 @@ -package bjc.dicelang.ast.nodes; - -/** - * The interface for a node in a dice AST - * - * @author ben - * - */ -public interface IDiceASTNode { - /** - * Get the type of AST node this node is - * - * @return The type of AST node this AST node is - */ - public DiceASTType getType(); - - /** - * Check if this node represents an operator or not - * - * @return Whether or not this node represents an operator - */ - public boolean isOperator(); -}
\ No newline at end of file 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 deleted file mode 100644 index b94bcc8..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/ILiteralDiceNode.java +++ /dev/null @@ -1,73 +0,0 @@ -package bjc.dicelang.ast.nodes; - -/** - * Represents a literal of some type in the AST - * - * @author ben - * - */ -public interface ILiteralDiceNode extends IDiceASTNode { - /** - * Check if a token represents a literal, and if so, what type - * - * @param tok - * The token to check - * @return The type the literal would be if it is one, or null - * otherwise - */ - static DiceLiteralType getLiteralType(String tok) { - String diceGroupOrNumber = "[(?:\\d*d\\d+)(?:\\d+)]"; - - if (tok.matches("\\A" + diceGroupOrNumber + "?" + "c" - + diceGroupOrNumber + "\\Z")) { - return DiceLiteralType.DICE; - } - - String diceGroup = "\\d*d\\d+\\"; - - if (tok.matches("\\A" + diceGroup + "Z")) { - return DiceLiteralType.DICE; - } - - try { - Integer.parseInt(tok); - return DiceLiteralType.INTEGER; - } catch (@SuppressWarnings("unused") NumberFormatException nfex) { - // We don't care about details - return null; - } - } - - /** - * 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 deleted file mode 100644 index 3d43bb1..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/IntegerLiteralNode.java +++ /dev/null @@ -1,50 +0,0 @@ -package bjc.dicelang.ast.nodes; - -/** - * Represents an integer literal of some kind - * - * @author ben - * - */ -public class IntegerLiteralNode implements ILiteralDiceNode { - private int value; - - /** - * Create a new integer literal from the given number - * - * @param val - * The value this node represents - */ - public IntegerLiteralNode(int val) { - value = val; - } - - @Override - public boolean canOptimize() { - return true; - } - - @Override - public DiceLiteralType getLiteralType() { - return DiceLiteralType.INTEGER; - } - - /** - * Get the value this node represents - * - * @return The integer value of this node - */ - public int getValue() { - return value; - } - - @Override - public int optimize() { - return value; - } - - @Override - 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 deleted file mode 100644 index 7c0a29d..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/OperatorDiceNode.java +++ /dev/null @@ -1,110 +0,0 @@ -package bjc.dicelang.ast.nodes; - -import static bjc.dicelang.ast.nodes.DiceOperatorType.DICE; -import static bjc.dicelang.ast.nodes.DiceOperatorType.EXPRESSION; -import static bjc.dicelang.ast.nodes.DiceOperatorType.MATH; - -/** - * A node that represents an operator - * - * @author ben - * - */ -public enum OperatorDiceNode implements IDiceASTNode { - /** - * Represents adding two nodes - */ - ADD(MATH), - /** - * Represents dividing two nodes - */ - DIVIDE(MATH), - /** - * Represents multiplying two nodes - */ - MULTIPLY(MATH), - /** - * Represents subtracting two nodes - */ - SUBTRACT(MATH), - /** - * Representings combining two node values together - */ - COMPOUND(DICE), - /** - * Represents using one node a variable number of times - */ - GROUP(DICE), - /** - * Represents constructing an array from a sequence of expressions - */ - ARRAY(DiceOperatorType.ARRAY), - /** - * Represents assigning one node to another - */ - ASSIGN(EXPRESSION), - /** - * Represents evaluating one expression in the context of another - */ - LET(EXPRESSION); - - /** - * Create a operator node from a string - * - * @param s - * The string to convert to a node - * @return The operator corresponding to the node - */ - public static OperatorDiceNode fromString(String s) { - switch (s) { - case ":=": - return ASSIGN; - case "+": - return ADD; - case "-": - return SUBTRACT; - case "*": - return MULTIPLY; - case "/": - return DIVIDE; - case "d": - case "group": - return GROUP; - case "c": - case "compound": - return COMPOUND; - case "=>": - return LET; - case "[]": - return ARRAY; - default: - throw new IllegalArgumentException( - s + " is not a valid operator node"); - } - } - - /** - * 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; - } - - /* - * (non-Javadoc) - * - * @see bjc.utils.dice.ast.IDiceASTNode#isOperator() - */ - @Override - public boolean isOperator() { - return true; - } -} diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/VariableDiceNode.java b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/VariableDiceNode.java deleted file mode 100644 index da66608..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/VariableDiceNode.java +++ /dev/null @@ -1,101 +0,0 @@ -package bjc.dicelang.ast.nodes; - -/** - * A node that represents a reference to a variable - * - * @author ben - * - */ -public class VariableDiceNode implements IDiceASTNode { - /** - * The variable referenced by this node - */ - private String variableName; - - /** - * Create a new node representing the specified variable - * - * @param varName - * The name of the variable being referenced - */ - public VariableDiceNode(String varName) { - this.variableName = varName; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(Object obj) { - // Handle special cases - if (this == obj) { - return true; - } else if (obj == null) { - return false; - } else if (getClass() != obj.getClass()) { - return false; - } else { - VariableDiceNode other = (VariableDiceNode) obj; - - if (variableName == null) { - if (other.variableName != null) { - return false; - } - } else if (!variableName.equals(other.variableName)) { - return false; - } - - return true; - } - } - - @Override - public DiceASTType getType() { - return DiceASTType.VARIABLE; - } - - /** - * Get the variable referenced by this AST node - * - * @return the variable referenced by this AST node - */ - public String getVariable() { - return variableName; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result - + ((variableName == null) ? 0 : variableName.hashCode()); - return result; - } - - /* - * (non-Javadoc) - * - * @see bjc.utils.dice.ast.IDiceASTNode#isOperator() - */ - @Override - public boolean isOperator() { - return false; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - return variableName; - } -}
\ No newline at end of file diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/package-info.java b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/package-info.java deleted file mode 100644 index f0f7366..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/package-info.java +++ /dev/null @@ -1,7 +0,0 @@ -/** - * Classes for nodes in the dice-lang AST - * - * @author ben - * - */ -package bjc.dicelang.ast.nodes;
\ No newline at end of file diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/optimization/ArithmeticCollapser.java b/dice-lang/src/main/java/bjc/dicelang/ast/optimization/ArithmeticCollapser.java deleted file mode 100644 index 960fbf7..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ast/optimization/ArithmeticCollapser.java +++ /dev/null @@ -1,50 +0,0 @@ -package bjc.dicelang.ast.optimization; - -import java.util.function.BinaryOperator; - -import bjc.utils.funcdata.IList; -import bjc.utils.funcdata.ITree; -import bjc.utils.funcdata.Tree; - -import bjc.dicelang.ast.DiceASTUtils; -import bjc.dicelang.ast.nodes.DiceASTType; -import bjc.dicelang.ast.nodes.IDiceASTNode; -import bjc.dicelang.ast.nodes.ILiteralDiceNode; -import bjc.dicelang.ast.nodes.IntegerLiteralNode; -import bjc.dicelang.ast.nodes.OperatorDiceNode; - -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/main/java/bjc/dicelang/ast/optimization/ConstantCollapser.java b/dice-lang/src/main/java/bjc/dicelang/ast/optimization/ConstantCollapser.java deleted file mode 100644 index 95badd2..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ast/optimization/ConstantCollapser.java +++ /dev/null @@ -1,91 +0,0 @@ -package bjc.dicelang.ast.optimization; - -import bjc.utils.funcdata.IList; -import bjc.utils.funcdata.ITree; -import bjc.utils.funcdata.Tree; - -import bjc.dicelang.ComplexDice; -import bjc.dicelang.ast.DiceASTUtils; -import bjc.dicelang.ast.nodes.IDiceASTNode; -import bjc.dicelang.ast.nodes.IntegerLiteralNode; -import bjc.dicelang.ast.nodes.OperatorDiceNode; - -/** - * 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/main/java/bjc/dicelang/ast/optimization/IOptimizationPass.java b/dice-lang/src/main/java/bjc/dicelang/ast/optimization/IOptimizationPass.java deleted file mode 100644 index 36b03f1..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ast/optimization/IOptimizationPass.java +++ /dev/null @@ -1,35 +0,0 @@ -package bjc.dicelang.ast.optimization; - -import bjc.utils.funcdata.IList; -import bjc.utils.funcdata.ITree; - -import bjc.dicelang.ast.nodes.IDiceASTNode; - -/** - * 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/main/java/bjc/dicelang/ast/optimization/OperationCondenser.java b/dice-lang/src/main/java/bjc/dicelang/ast/optimization/OperationCondenser.java deleted file mode 100644 index f646a17..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ast/optimization/OperationCondenser.java +++ /dev/null @@ -1,107 +0,0 @@ -package bjc.dicelang.ast.optimization; - -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; - -import bjc.dicelang.ast.nodes.DiceASTType; -import bjc.dicelang.ast.nodes.IDiceASTNode; -import bjc.dicelang.ast.nodes.OperatorDiceNode; - -/** - * 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/main/java/bjc/dicelang/ast/optimization/package-info.java b/dice-lang/src/main/java/bjc/dicelang/ast/optimization/package-info.java deleted file mode 100644 index 6f75bf9..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ast/optimization/package-info.java +++ /dev/null @@ -1,7 +0,0 @@ -/** - * Contains optimizations on dice ASTs - * - * @author ben - * - */ -package bjc.dicelang.ast.optimization;
\ No newline at end of file diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/package-info.java b/dice-lang/src/main/java/bjc/dicelang/ast/package-info.java deleted file mode 100644 index f6352aa..0000000 --- a/dice-lang/src/main/java/bjc/dicelang/ast/package-info.java +++ /dev/null @@ -1,7 +0,0 @@ -/** - * New implementation of AST for dice-lang - * - * @author ben - * - */ -package bjc.dicelang.ast;
\ No newline at end of file |
