diff options
Diffstat (limited to 'dice-lang/src')
50 files changed, 0 insertions, 3638 deletions
diff --git a/dice-lang/src/bjc/dicelang/v1/BindingDiceExpression.java b/dice-lang/src/bjc/dicelang/v1/BindingDiceExpression.java deleted file mode 100644 index 14dbc42..0000000 --- a/dice-lang/src/bjc/dicelang/v1/BindingDiceExpression.java +++ /dev/null @@ -1,87 +0,0 @@ -package bjc.dicelang.v1; - -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 name; - - /** - * 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.name = 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=" + name + ", exp=" + expression.toString() + "]"; - } -} diff --git a/dice-lang/src/bjc/dicelang/v1/ComplexDice.java b/dice-lang/src/bjc/dicelang/v1/ComplexDice.java deleted file mode 100644 index 76a34ba..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ComplexDice.java +++ /dev/null @@ -1,121 +0,0 @@ -package bjc.dicelang.v1; - -/** - * 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(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(); - } - - @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; - } - - @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() + "]"; - } -} diff --git a/dice-lang/src/bjc/dicelang/v1/CompoundDice.java b/dice-lang/src/bjc/dicelang/v1/CompoundDice.java deleted file mode 100644 index 43d64e8..0000000 --- a/dice-lang/src/bjc/dicelang/v1/CompoundDice.java +++ /dev/null @@ -1,83 +0,0 @@ -package bjc.dicelang.v1; - -/** - * 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 left; - - /* - * The right die of the expression - */ - private IDiceExpression right; - - /** - * Create a new compound dice using the specified dice - * - * @param lft - * The die to use on the left - * @param rght - * The die to use on the right - */ - public CompoundDice(IDiceExpression lft, IDiceExpression rght) { - this.left = lft; - this.right = rght; - } - - /** - * Create a new compound dice from two dice strings - * - * @param lft - * The left side dice as a string - * @param rght - * The right side dice as a string - */ - public CompoundDice(String lft, String rght) { - this(ComplexDice.fromString(lft), ComplexDice.fromString(rght)); - } - - /** - * 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 left.canOptimize() && right.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(left.optimize() + "" + right.optimize()); - } - - @Override - public int roll() { - /* - * Make the combination of the two dice - */ - return Integer.parseInt(left.roll() + "" + right.roll()); - } - - @Override - public String toString() { - return "compound[l=" + left.toString() + ", r=" + right.toString() + "]"; - } -} diff --git a/dice-lang/src/bjc/dicelang/v1/DiceExpressionBuilder.java b/dice-lang/src/bjc/dicelang/v1/DiceExpressionBuilder.java deleted file mode 100644 index 3b20d03..0000000 --- a/dice-lang/src/bjc/dicelang/v1/DiceExpressionBuilder.java +++ /dev/null @@ -1,146 +0,0 @@ -package bjc.dicelang.v1; - -import static bjc.dicelang.v1.DiceExpressionType.ADD; -import static bjc.dicelang.v1.DiceExpressionType.DIVIDE; -import static bjc.dicelang.v1.DiceExpressionType.MULTIPLY; -import static bjc.dicelang.v1.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/bjc/dicelang/v1/DiceExpressionParser.java b/dice-lang/src/bjc/dicelang/v1/DiceExpressionParser.java deleted file mode 100644 index ff2e800..0000000 --- a/dice-lang/src/bjc/dicelang/v1/DiceExpressionParser.java +++ /dev/null @@ -1,159 +0,0 @@ -package bjc.dicelang.v1; - -import bjc.utils.funcdata.FunctionalStringTokenizer; -import bjc.utils.funcdata.IList; -import bjc.utils.parserutils.ShuntingYard; - -import java.util.Map; -import java.util.Stack; - -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(NumberFormatException nfex) { - // We don't care about details, just - // that it failed - if(expressions.size() >= 2) { - /* - * Apply an operation to two - * dice - */ - IDiceExpression right = expressions.pop(); - IDiceExpression left = expressions.pop(); - - switch(expressionPart) { - case ":=": - expressions.push(new BindingDiceExpression(left, right, - enviroment)); - break; - case "+": - expressions.push(new OperatorDiceExpression(right, left, - DiceExpressionType.ADD)); - break; - case "-": - expressions.push(new OperatorDiceExpression(right, left, - DiceExpressionType.SUBTRACT)); - break; - case "*": - expressions.push(new OperatorDiceExpression(right, left, - DiceExpressionType.MULTIPLY)); - break; - case "/": - expressions.push(new OperatorDiceExpression(right, left, - DiceExpressionType.DIVIDE)); - break; - case "c": - expressions.push(new CompoundDice(left, right)); - break; - case "d": - expressions.push(new ComplexDice(left, right)); - break; - default: - /* - * Parse it as a - * variable reference - * - * Make sure to restore - * popped variables - */ - expressions.push(left); - expressions.push(right); - - 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/bjc/dicelang/v1/DiceExpressionType.java b/dice-lang/src/bjc/dicelang/v1/DiceExpressionType.java deleted file mode 100644 index 7c0510f..0000000 --- a/dice-lang/src/bjc/dicelang/v1/DiceExpressionType.java +++ /dev/null @@ -1,43 +0,0 @@ -package bjc.dicelang.v1; - -/** - * 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; - - @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"); - } - }; -} diff --git a/dice-lang/src/bjc/dicelang/v1/Die.java b/dice-lang/src/bjc/dicelang/v1/Die.java deleted file mode 100644 index 667e18c..0000000 --- a/dice-lang/src/bjc/dicelang/v1/Die.java +++ /dev/null @@ -1,55 +0,0 @@ -package bjc.dicelang.v1; - -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; - } - - @Override - public int roll() { - return rng.nextInt(nSides) + 1; - } - - @Override - public String toString() { - return "d" + nSides; - } -} diff --git a/dice-lang/src/bjc/dicelang/v1/IDiceExpression.java b/dice-lang/src/bjc/dicelang/v1/IDiceExpression.java deleted file mode 100644 index 9de7553..0000000 --- a/dice-lang/src/bjc/dicelang/v1/IDiceExpression.java +++ /dev/null @@ -1,93 +0,0 @@ -package bjc.dicelang.v1; - -import bjc.utils.parserutils.TokenUtils; - -/** - * 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; - - String diceMatcher = "\\Ad\\d+\\Z"; - - if(TokenUtils.containsInfixOperator(literalData, "c")) { - // Parse a compound die - String[] strangs = literalData.split("c"); - - return new CompoundDice(strangs); - } else if(TokenUtils.containsInfixOperator(literalData, "d")) - // Handle groups of similiar dice - return ComplexDice.fromString(literalData); - else if(literalData.matches(diceMatcher)) - // 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 + ". Floating point numbers " - + "are not supported."); - - 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(); -} diff --git a/dice-lang/src/bjc/dicelang/v1/OperatorDiceExpression.java b/dice-lang/src/bjc/dicelang/v1/OperatorDiceExpression.java deleted file mode 100644 index a5d37e2..0000000 --- a/dice-lang/src/bjc/dicelang/v1/OperatorDiceExpression.java +++ /dev/null @@ -1,80 +0,0 @@ -package bjc.dicelang.v1; - -/** - * 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 type; - - /* - * The dice on the left side of the expression - */ - private IDiceExpression left; - - /* - * The dice on the right side of the expression - */ - private IDiceExpression right; - - /** - * Create a new compound expression using the specified parameters - * - * @param rght - * The die on the right side of the expression - * @param lft - * The die on the left side of the expression - * @param type - * The operator to use for combining the dices - */ - public OperatorDiceExpression(IDiceExpression rght, IDiceExpression lft, DiceExpressionType type) { - this.right = rght; - this.left = lft; - this.type = type; - } - - @Override - public int roll() { - /* - * Handle each operator - */ - switch(type) { - case ADD: - return right.roll() + left.roll(); - case SUBTRACT: - return right.roll() - left.roll(); - case MULTIPLY: - return right.roll() * left.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 right.roll() / left.roll(); - } catch(ArithmeticException aex) { - UnsupportedOperationException usex = new UnsupportedOperationException( - "Attempted to divide by zero." + " Problematic expression is " + left); - - usex.initCause(aex); - - throw usex; - } - default: - throw new IllegalArgumentException( - "Got passed a invalid ScalarExpressionType (" + type + "). WAT"); - - } - } - - @Override - public String toString() { - return "dice-exp[type=" + type + ", l=" + left.toString() + ", r=" + right.toString() + "]"; - } -} diff --git a/dice-lang/src/bjc/dicelang/v1/PolyhedralDice.java b/dice-lang/src/bjc/dicelang/v1/PolyhedralDice.java deleted file mode 100644 index 402de18..0000000 --- a/dice-lang/src/bjc/dicelang/v1/PolyhedralDice.java +++ /dev/null @@ -1,149 +0,0 @@ -package bjc.dicelang.v1; - -/** - * 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/bjc/dicelang/v1/ReferenceDiceExpression.java b/dice-lang/src/bjc/dicelang/v1/ReferenceDiceExpression.java deleted file mode 100644 index 11f466e..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ReferenceDiceExpression.java +++ /dev/null @@ -1,59 +0,0 @@ -package bjc.dicelang.v1; - -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 name; - - /** - * Create a new reference dice expression referring to the given name in - * an enviroment - * - * @param nme - * The name of the bound variable - * @param env - * The enviroment to resolve the variable against - */ - public ReferenceDiceExpression(String nme, Map<String, IDiceExpression> env) { - this.name = nme; - this.enviroment = env; - } - - /** - * Get the name of the referenced variable - * - * @return the name of the referenced variable - */ - public String getName() { - return name; - } - - @Override - public int roll() { - if(!enviroment.containsKey(name)) - throw new UnsupportedOperationException("Attempted to reference undefined variable " + name); - - return enviroment.get(name).roll(); - } - - @Override - public String toString() { - if(enviroment.containsKey(name)) return enviroment.get(name).toString() + "(bound to " + name + ")"; - - return name + "(unbound)"; - } -} diff --git a/dice-lang/src/bjc/dicelang/v1/ScalarDie.java b/dice-lang/src/bjc/dicelang/v1/ScalarDie.java deleted file mode 100644 index 62ca151..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ScalarDie.java +++ /dev/null @@ -1,44 +0,0 @@ -package bjc.dicelang.v1; - -/** - * 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; - } - - @Override - public int roll() { - return number; - } - - @Override - public String toString() { - return Integer.toString(number); - } -} diff --git a/dice-lang/src/bjc/dicelang/v1/ast/.gitignore b/dice-lang/src/bjc/dicelang/v1/ast/.gitignore deleted file mode 100644 index 67877fe..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ast/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/.DiceASTParser.java.swp diff --git a/dice-lang/src/bjc/dicelang/v1/ast/ArithmeticCollapser.java b/dice-lang/src/bjc/dicelang/v1/ast/ArithmeticCollapser.java deleted file mode 100644 index 28f29f0..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ast/ArithmeticCollapser.java +++ /dev/null @@ -1,149 +0,0 @@ -package bjc.dicelang.v1.ast; - -import bjc.dicelang.v1.ast.nodes.IDiceASTNode; -import bjc.dicelang.v1.ast.nodes.OperatorDiceNode; -import bjc.utils.data.IPair; -import bjc.utils.data.ITree; -import bjc.utils.data.Pair; -import bjc.utils.data.Tree; -import bjc.utils.funcdata.IList; - -import java.util.function.BinaryOperator; - -/** - * 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/bjc/dicelang/v1/ast/ArrayResult.java b/dice-lang/src/bjc/dicelang/v1/ast/ArrayResult.java deleted file mode 100644 index 1053360..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ast/ArrayResult.java +++ /dev/null @@ -1,43 +0,0 @@ -package bjc.dicelang.v1.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/bjc/dicelang/v1/ast/DiceASTEvaluator.java b/dice-lang/src/bjc/dicelang/v1/ast/DiceASTEvaluator.java deleted file mode 100644 index 8273525..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ast/DiceASTEvaluator.java +++ /dev/null @@ -1,276 +0,0 @@ -package bjc.dicelang.v1.ast; - -import bjc.dicelang.v1.ComplexDice; -import bjc.dicelang.v1.ast.nodes.DiceASTType; -import bjc.dicelang.v1.ast.nodes.DiceLiteralNode; -import bjc.dicelang.v1.ast.nodes.DiceLiteralType; -import bjc.dicelang.v1.ast.nodes.IDiceASTNode; -import bjc.dicelang.v1.ast.nodes.ILiteralDiceNode; -import bjc.dicelang.v1.ast.nodes.IntegerLiteralNode; -import bjc.dicelang.v1.ast.nodes.OperatorDiceNode; -import bjc.dicelang.v1.ast.nodes.VariableDiceNode; -import bjc.utils.data.IHolder; -import bjc.utils.data.IPair; -import bjc.utils.data.ITree; -import bjc.utils.data.Identity; -import bjc.utils.data.LazyPair; -import bjc.utils.data.Pair; -import bjc.utils.data.Tree; -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.FunctionalMap; -import bjc.utils.funcdata.IList; -import bjc.utils.funcdata.IMap; - -import java.util.function.Supplier; - -/** - * 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/bjc/dicelang/v1/ast/DiceASTInliner.java b/dice-lang/src/bjc/dicelang/v1/ast/DiceASTInliner.java deleted file mode 100644 index 74e59c6..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ast/DiceASTInliner.java +++ /dev/null @@ -1,112 +0,0 @@ -package bjc.dicelang.v1.ast; - -import bjc.dicelang.v1.ast.nodes.DiceASTType; -import bjc.dicelang.v1.ast.nodes.IDiceASTNode; -import bjc.dicelang.v1.ast.nodes.VariableDiceNode; -import bjc.utils.data.ITree; -import bjc.utils.data.Tree; -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.IList; -import bjc.utils.funcdata.IMap; - -/** - * 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); - } - - // We're not inlining this particular variable - return new Tree<>(node); - } - - // 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); - } - - /** - * 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) { - // Inline the specified 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/bjc/dicelang/v1/ast/DiceASTOptimizer.java b/dice-lang/src/bjc/dicelang/v1/ast/DiceASTOptimizer.java deleted file mode 100644 index fa4f0ca..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ast/DiceASTOptimizer.java +++ /dev/null @@ -1,55 +0,0 @@ -package bjc.dicelang.v1.ast; - -import bjc.dicelang.v1.ast.nodes.IDiceASTNode; -import bjc.dicelang.v1.ast.optimization.IOptimizationPass; -import bjc.utils.data.ITree; -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.IList; -import bjc.utils.funcdata.IMap; - -/** - * 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/bjc/dicelang/v1/ast/DiceASTParser.java b/dice-lang/src/bjc/dicelang/v1/ast/DiceASTParser.java deleted file mode 100644 index 4a2822c..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ast/DiceASTParser.java +++ /dev/null @@ -1,147 +0,0 @@ -package bjc.dicelang.v1.ast; - -import bjc.dicelang.v1.IDiceExpression; -import bjc.dicelang.v1.ast.nodes.DiceLiteralNode; -import bjc.dicelang.v1.ast.nodes.DiceLiteralType; -import bjc.dicelang.v1.ast.nodes.IDiceASTNode; -import bjc.dicelang.v1.ast.nodes.ILiteralDiceNode; -import bjc.dicelang.v1.ast.nodes.IntegerLiteralNode; -import bjc.dicelang.v1.ast.nodes.OperatorDiceNode; -import bjc.dicelang.v1.ast.nodes.VariableDiceNode; -import bjc.utils.data.ITree; -import bjc.utils.data.Tree; -import bjc.utils.funcdata.FunctionalList; -import bjc.utils.funcdata.FunctionalMap; -import bjc.utils.funcdata.IList; -import bjc.utils.funcdata.IMap; -import bjc.utils.funcutils.StringUtils; -import bjc.utils.parserutils.TreeConstructor; - -import java.util.Deque; -import java.util.InputMismatchException; -import java.util.function.Function; -import java.util.function.Predicate; - -/** - * 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) { - // Mark arrays as special operators - Predicate<String> specialPicker = (operator) -> { - if(StringUtils.containsOnly(operator, "\\[") || StringUtils.containsOnly(operator, "\\]")) - return true; - - return false; - }; - - // Here is the map for holding special operators - IMap<String, Function<Deque<ITree<String>>, ITree<String>>> operators = new FunctionalMap<>(); - - // Handle open [ - operators.put("[", (queuedTrees) -> { - // Just put in a [ - Tree<String> openArray = new Tree<>("["); - - return openArray; - }); - - operators.put("]", (queuedTrees) -> { - // Parse closing an array - 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(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/bjc/dicelang/v1/ast/DiceASTReferenceChecker.java b/dice-lang/src/bjc/dicelang/v1/ast/DiceASTReferenceChecker.java deleted file mode 100644 index f668c72..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ast/DiceASTReferenceChecker.java +++ /dev/null @@ -1,59 +0,0 @@ -package bjc.dicelang.v1.ast; - -import bjc.dicelang.v1.ast.nodes.DiceASTType; -import bjc.dicelang.v1.ast.nodes.IDiceASTNode; -import bjc.dicelang.v1.ast.nodes.VariableDiceNode; -import bjc.utils.data.IHolder; - -import java.util.function.Consumer; - -/** - * 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/bjc/dicelang/v1/ast/DiceASTReferenceSanitizer.java b/dice-lang/src/bjc/dicelang/v1/ast/DiceASTReferenceSanitizer.java deleted file mode 100644 index ec595ea..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ast/DiceASTReferenceSanitizer.java +++ /dev/null @@ -1,176 +0,0 @@ -package bjc.dicelang.v1.ast; - -import bjc.dicelang.v1.ast.nodes.IDiceASTNode; -import bjc.dicelang.v1.ast.nodes.OperatorDiceNode; -import bjc.dicelang.v1.ast.nodes.VariableDiceNode; -import bjc.utils.data.IHolder; -import bjc.utils.data.ITree; -import bjc.utils.data.Identity; -import bjc.utils.data.TopDownTransformResult; -import bjc.utils.data.Tree; -import bjc.utils.funcdata.IMap; - -/** - * 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/bjc/dicelang/v1/ast/DiceASTUtils.java b/dice-lang/src/bjc/dicelang/v1/ast/DiceASTUtils.java deleted file mode 100644 index e37d3c3..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ast/DiceASTUtils.java +++ /dev/null @@ -1,80 +0,0 @@ -package bjc.dicelang.v1.ast; - -import bjc.dicelang.v1.IDiceExpression; -import bjc.dicelang.v1.ScalarDie; -import bjc.dicelang.v1.ast.nodes.DiceASTType; -import bjc.dicelang.v1.ast.nodes.DiceLiteralNode; -import bjc.dicelang.v1.ast.nodes.IDiceASTNode; -import bjc.dicelang.v1.ast.nodes.ILiteralDiceNode; -import bjc.dicelang.v1.ast.nodes.IntegerLiteralNode; -import bjc.utils.data.ITree; - -/** - * 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/bjc/dicelang/v1/ast/DummyResult.java b/dice-lang/src/bjc/dicelang/v1/ast/DummyResult.java deleted file mode 100644 index 2328d3c..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ast/DummyResult.java +++ /dev/null @@ -1,43 +0,0 @@ -package bjc.dicelang.v1.ast; - -/** - * A dummy result - * - * @author ben - * - */ -public class DummyResult implements IResult { - /* - * The reason why this result is a dummy - */ - private String dummyData; - - /** - * Create a new dummy result with a reason - * - * @param data - * The reason why the result is a dummy - */ - 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/bjc/dicelang/v1/ast/IOperatorCollapser.java b/dice-lang/src/bjc/dicelang/v1/ast/IOperatorCollapser.java deleted file mode 100644 index ab097db..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ast/IOperatorCollapser.java +++ /dev/null @@ -1,19 +0,0 @@ -package bjc.dicelang.v1.ast; - -import bjc.dicelang.v1.ast.nodes.IDiceASTNode; -import bjc.utils.data.IPair; -import bjc.utils.data.ITree; -import bjc.utils.funcdata.IList; - -import java.util.function.Function; - -/** - * 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/bjc/dicelang/v1/ast/IResult.java b/dice-lang/src/bjc/dicelang/v1/ast/IResult.java deleted file mode 100644 index df67061..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ast/IResult.java +++ /dev/null @@ -1,16 +0,0 @@ -package bjc.dicelang.v1.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/bjc/dicelang/v1/ast/IntegerResult.java b/dice-lang/src/bjc/dicelang/v1/ast/IntegerResult.java deleted file mode 100644 index 61d57b7..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ast/IntegerResult.java +++ /dev/null @@ -1,40 +0,0 @@ -package bjc.dicelang.v1.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/bjc/dicelang/v1/ast/ResultType.java b/dice-lang/src/bjc/dicelang/v1/ast/ResultType.java deleted file mode 100644 index c5afee8..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ast/ResultType.java +++ /dev/null @@ -1,22 +0,0 @@ -package bjc.dicelang.v1.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/bjc/dicelang/v1/ast/nodes/DiceASTType.java b/dice-lang/src/bjc/dicelang/v1/ast/nodes/DiceASTType.java deleted file mode 100644 index 47e8b39..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ast/nodes/DiceASTType.java +++ /dev/null @@ -1,27 +0,0 @@ -package bjc.dicelang.v1.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/bjc/dicelang/v1/ast/nodes/DiceLiteralNode.java b/dice-lang/src/bjc/dicelang/v1/ast/nodes/DiceLiteralNode.java deleted file mode 100644 index 4241463..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ast/nodes/DiceLiteralNode.java +++ /dev/null @@ -1,52 +0,0 @@ -package bjc.dicelang.v1.ast.nodes; - -import bjc.dicelang.v1.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/bjc/dicelang/v1/ast/nodes/DiceLiteralType.java b/dice-lang/src/bjc/dicelang/v1/ast/nodes/DiceLiteralType.java deleted file mode 100644 index d48104c..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ast/nodes/DiceLiteralType.java +++ /dev/null @@ -1,18 +0,0 @@ -package bjc.dicelang.v1.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/bjc/dicelang/v1/ast/nodes/DiceOperatorType.java b/dice-lang/src/bjc/dicelang/v1/ast/nodes/DiceOperatorType.java deleted file mode 100644 index b842604..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ast/nodes/DiceOperatorType.java +++ /dev/null @@ -1,29 +0,0 @@ -package bjc.dicelang.v1.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/bjc/dicelang/v1/ast/nodes/IDiceASTNode.java b/dice-lang/src/bjc/dicelang/v1/ast/nodes/IDiceASTNode.java deleted file mode 100644 index 7e8bb81..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ast/nodes/IDiceASTNode.java +++ /dev/null @@ -1,23 +0,0 @@ -package bjc.dicelang.v1.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/bjc/dicelang/v1/ast/nodes/ILiteralDiceNode.java b/dice-lang/src/bjc/dicelang/v1/ast/nodes/ILiteralDiceNode.java deleted file mode 100644 index 5a3f5b3..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ast/nodes/ILiteralDiceNode.java +++ /dev/null @@ -1,71 +0,0 @@ -package bjc.dicelang.v1.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 diceGroup = "\\d*d\\d+\\"; - - String diceGroupOrNumber = "[(?:" + diceGroup + ")(?:\\d+)]"; - - if(tok.matches("\\A" + diceGroupOrNumber + "?" + "c" + diceGroupOrNumber + "\\Z")) - return DiceLiteralType.DICE; - - if(tok.matches("\\A" + diceGroup + "Z")) return DiceLiteralType.DICE; - - try { - Integer.parseInt(tok); - return DiceLiteralType.INTEGER; - } catch(NumberFormatException nfex) { - // We don't care about details - // This probably shouldn't return null, but I believe it - // does so - // because where its called checks that. @FIXME - 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.v1.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.v1.IDiceExpression#optimize() - */ - int optimize(); -} diff --git a/dice-lang/src/bjc/dicelang/v1/ast/nodes/IntegerLiteralNode.java b/dice-lang/src/bjc/dicelang/v1/ast/nodes/IntegerLiteralNode.java deleted file mode 100644 index fd1a1e6..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ast/nodes/IntegerLiteralNode.java +++ /dev/null @@ -1,50 +0,0 @@ -package bjc.dicelang.v1.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/bjc/dicelang/v1/ast/nodes/OperatorDiceNode.java b/dice-lang/src/bjc/dicelang/v1/ast/nodes/OperatorDiceNode.java deleted file mode 100644 index 0181314..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ast/nodes/OperatorDiceNode.java +++ /dev/null @@ -1,104 +0,0 @@ -package bjc.dicelang.v1.ast.nodes; - -import static bjc.dicelang.v1.ast.nodes.DiceOperatorType.DICE; -import static bjc.dicelang.v1.ast.nodes.DiceOperatorType.EXPRESSION; -import static bjc.dicelang.v1.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; - } - - @Override - public boolean isOperator() { - return true; - } -} diff --git a/dice-lang/src/bjc/dicelang/v1/ast/nodes/VariableDiceNode.java b/dice-lang/src/bjc/dicelang/v1/ast/nodes/VariableDiceNode.java deleted file mode 100644 index e44f2ab..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ast/nodes/VariableDiceNode.java +++ /dev/null @@ -1,96 +0,0 @@ -package bjc.dicelang.v1.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/bjc/dicelang/v1/ast/nodes/package-info.java b/dice-lang/src/bjc/dicelang/v1/ast/nodes/package-info.java deleted file mode 100644 index cdd63e9..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ast/nodes/package-info.java +++ /dev/null @@ -1,7 +0,0 @@ -/** - * Classes for nodes in the dice-lang AST - * - * @author ben - * - */ -package bjc.dicelang.v1.ast.nodes;
\ No newline at end of file diff --git a/dice-lang/src/bjc/dicelang/v1/ast/optimization/ArithmeticCollapser.java b/dice-lang/src/bjc/dicelang/v1/ast/optimization/ArithmeticCollapser.java deleted file mode 100644 index acc1afa..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ast/optimization/ArithmeticCollapser.java +++ /dev/null @@ -1,42 +0,0 @@ -package bjc.dicelang.v1.ast.optimization; - -import bjc.dicelang.v1.ast.DiceASTUtils; -import bjc.dicelang.v1.ast.nodes.DiceASTType; -import bjc.dicelang.v1.ast.nodes.IDiceASTNode; -import bjc.dicelang.v1.ast.nodes.ILiteralDiceNode; -import bjc.dicelang.v1.ast.nodes.IntegerLiteralNode; -import bjc.dicelang.v1.ast.nodes.OperatorDiceNode; -import bjc.utils.data.ITree; -import bjc.utils.data.Tree; -import bjc.utils.funcdata.IList; - -import java.util.function.BinaryOperator; - -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/bjc/dicelang/v1/ast/optimization/ConstantCollapser.java b/dice-lang/src/bjc/dicelang/v1/ast/optimization/ConstantCollapser.java deleted file mode 100644 index bf44953..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ast/optimization/ConstantCollapser.java +++ /dev/null @@ -1,76 +0,0 @@ -package bjc.dicelang.v1.ast.optimization; - -import bjc.dicelang.v1.ComplexDice; -import bjc.dicelang.v1.ast.DiceASTUtils; -import bjc.dicelang.v1.ast.nodes.IDiceASTNode; -import bjc.dicelang.v1.ast.nodes.IntegerLiteralNode; -import bjc.dicelang.v1.ast.nodes.OperatorDiceNode; -import bjc.utils.data.ITree; -import bjc.utils.data.Tree; -import bjc.utils.funcdata.IList; - -/** - * 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/bjc/dicelang/v1/ast/optimization/IOptimizationPass.java b/dice-lang/src/bjc/dicelang/v1/ast/optimization/IOptimizationPass.java deleted file mode 100644 index 082f042..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ast/optimization/IOptimizationPass.java +++ /dev/null @@ -1,33 +0,0 @@ -package bjc.dicelang.v1.ast.optimization; - -import bjc.dicelang.v1.ast.nodes.IDiceASTNode; -import bjc.utils.data.ITree; -import bjc.utils.funcdata.IList; - -/** - * 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/bjc/dicelang/v1/ast/optimization/OperationCondenser.java b/dice-lang/src/bjc/dicelang/v1/ast/optimization/OperationCondenser.java deleted file mode 100644 index 7ce6f5d..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ast/optimization/OperationCondenser.java +++ /dev/null @@ -1,96 +0,0 @@ -package bjc.dicelang.v1.ast.optimization; - -import bjc.dicelang.v1.ast.nodes.DiceASTType; -import bjc.dicelang.v1.ast.nodes.IDiceASTNode; -import bjc.dicelang.v1.ast.nodes.OperatorDiceNode; -import bjc.utils.data.IHolder; -import bjc.utils.data.ITree; -import bjc.utils.data.Identity; -import bjc.utils.data.TopDownTransformResult; -import bjc.utils.data.Tree; - -/** - * Condenses chained operations into a single level - * - * @author ben - * - */ -public class OperationCondenser { - /** - * Condense chained similiar operations into a single level - * - * @param ast - * The AST to condense - * @return The condensed AST - */ - public static ITree<IDiceASTNode> condense(ITree<IDiceASTNode> ast) { - return ast.topDownTransform(OperationCondenser::pickNode, OperationCondenser::doCondense); - } - - private static 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/bjc/dicelang/v1/ast/optimization/package-info.java b/dice-lang/src/bjc/dicelang/v1/ast/optimization/package-info.java deleted file mode 100644 index 3c74a21..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ast/optimization/package-info.java +++ /dev/null @@ -1,7 +0,0 @@ -/** - * Contains optimizations on dice ASTs - * - * @author ben - * - */ -package bjc.dicelang.v1.ast.optimization;
\ No newline at end of file diff --git a/dice-lang/src/bjc/dicelang/v1/ast/package-info.java b/dice-lang/src/bjc/dicelang/v1/ast/package-info.java deleted file mode 100644 index f1de4f7..0000000 --- a/dice-lang/src/bjc/dicelang/v1/ast/package-info.java +++ /dev/null @@ -1,7 +0,0 @@ -/** - * New implementation of AST for dice-lang - * - * @author ben - * - */ -package bjc.dicelang.v1.ast;
\ No newline at end of file diff --git a/dice-lang/src/bjc/dicelang/v1/examples/.gitignore b/dice-lang/src/bjc/dicelang/v1/examples/.gitignore deleted file mode 100644 index a804034..0000000 --- a/dice-lang/src/bjc/dicelang/v1/examples/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/.DiceASTLanguageTest.java.swp -/.swp diff --git a/dice-lang/src/bjc/dicelang/v1/examples/DiceASTLanguageTest.java b/dice-lang/src/bjc/dicelang/v1/examples/DiceASTLanguageTest.java deleted file mode 100644 index 205d986..0000000 --- a/dice-lang/src/bjc/dicelang/v1/examples/DiceASTLanguageTest.java +++ /dev/null @@ -1,235 +0,0 @@ -package bjc.dicelang.v1.examples; - -import bjc.dicelang.v1.ast.DiceASTEvaluator; -import bjc.dicelang.v1.ast.DiceASTInliner; -import bjc.dicelang.v1.ast.DiceASTOptimizer; -import bjc.dicelang.v1.ast.DiceASTParser; -import bjc.dicelang.v1.ast.DiceASTReferenceSanitizer; -import bjc.dicelang.v1.ast.IResult; -import bjc.dicelang.v1.ast.nodes.IDiceASTNode; -import bjc.dicelang.v1.ast.optimization.ConstantCollapser; -import bjc.dicelang.v1.ast.optimization.OperationCondenser; -import bjc.utils.data.ITree; -import bjc.utils.funcdata.FunctionalMap; -import bjc.utils.funcdata.FunctionalStringTokenizer; -import bjc.utils.funcdata.IList; -import bjc.utils.funcdata.IMap; - -import java.util.InputMismatchException; -import java.util.Scanner; - -/** - * Test interface for AST-based dice language - * - * @author ben - * - */ -public class DiceASTLanguageTest { - private static IMap<String, DiceASTPragma> actions; - - private static DiceASTOptimizer optimizer; - - // Set up things that need to be configured - static { - actions = new FunctionalMap<>(); - - // Inline all the variables in a given expression - actions.put("inline", DiceASTLanguageTest::handleInlineAction); - - // Print out the enviroment - actions.put("env", (tokenizer, enviroment) -> { - enviroment.forEach((varName, varValue) -> { - System.out.println(varName + " is bound to " + varValue); - }); - }); - - // Create and configure the optimizer - optimizer = new DiceASTOptimizer(); - - optimizer.addPass(new ConstantCollapser()); - } - - // Read in a command - private static String getNextCommand(Scanner inputSource, int commandNumber) { - // Print a prompt using the current command number - System.out.print("\ndice-lang-" + commandNumber + "> "); - - // Read in the next command - return inputSource.nextLine(); - } - - private static void handleInlineAction(FunctionalStringTokenizer tokenizer, - IMap<String, ITree<IDiceASTNode>> enviroment) { - // Skip the pragma name - tokenizer.nextToken(); - - // Get the pragma arguments - IList<String> pragmaArgs = tokenizer.toList(); - - if(pragmaArgs.getSize() < 3) { - // Complain about pragma arguments not being valid - System.err.println("ERROR: Inline requires at least 3 parameters. They are:" - + "\n\t1. The name of the expression to inline." - + "\n\t2. The name of the variable to bind the result to." - + "\n\t3 and onwards. Names of variables to inline in the expression."); - } else { - // Get arguments - String inlineExpression = pragmaArgs.getByIndex(0); - String variableName = pragmaArgs.getByIndex(1); - - // Grab the variables we want to inline - IList<String> inlinedVariables = pragmaArgs.tail().tail(); - - // Actually inline the variable - ITree<IDiceASTNode> inlinedExpression = DiceASTInliner.selectiveInline( - enviroment.get(inlineExpression), enviroment, inlinedVariables); - - // Stick the inlined variable into the enviroment - enviroment.put(variableName, inlinedExpression); - } - } - - /** - * Main method of class - * - * @param args - * Unused CLI args - */ - public static void main(String[] args) { - // Prepare the things we need for input - Scanner inputSource = new Scanner(System.in); - int commandNumber = 0; - - // Grab the initial command - String currentLine = getNextCommand(inputSource, commandNumber); - - // The enviroment for variables - IMap<String, ITree<IDiceASTNode>> enviroment = new FunctionalMap<>(); - - // Handle commands - while(!currentLine.equalsIgnoreCase("quit")) { - // Get the name of a possible action - String possibleActionName = currentLine.split(" ")[0]; - - // Check and see if we're executing an action - if(actions.containsKey(possibleActionName)) { - // Execute action - FunctionalStringTokenizer tokenizer = new FunctionalStringTokenizer(currentLine); - - // Execute the action - actions.get(possibleActionName).accept(tokenizer, enviroment); - - // Get the next command - currentLine = getNextCommand(inputSource, commandNumber); - - continue; - } - - // The AST we are going to build - ITree<IDiceASTNode> builtAST; - - // Time command preparation - long time = System.nanoTime(); - - // Prepare the command - IList<String> preparedTokens = DiceExpressionPreparer.prepareCommand(currentLine); - - System.out.println("Command prepared in " + (double) (System.nanoTime() - time) / 1000000000 - + " s"); - - try { - // Time the AST creation - time = System.nanoTime(); - - // Create the AST - builtAST = DiceASTParser.createFromString(preparedTokens); - - System.out.println("Command parsed in " - + (double) (System.nanoTime() - time) / 1000000000 + " s"); - } catch(InputMismatchException | IllegalStateException | UnsupportedOperationException ex) { - // Tell the user there was an error in parsing - System.out.println("PARSING ERROR: " + ex.getLocalizedMessage()); - - // Move onto the next command - currentLine = getNextCommand(inputSource, commandNumber); - - continue; - } - - // Print out parsed AST - System.out.println("\tParsed: " + builtAST.toString()); - - // Time AST transformation - time = System.nanoTime(); - - // Transform the AST - ITree<IDiceASTNode> transformedAST = transformAST(builtAST, enviroment); - - System.out.println("Command transformed in " + (double) (System.nanoTime() - time) / 1000000000 - + " s"); - - // Print out the transformed AST - System.out.println("\tTransformed: " + transformedAST.toString()); - - try { - // Time the evaluation - time = System.nanoTime(); - - // Evaluate the expression once - IResult sampleResult = DiceASTEvaluator.evaluateAST(transformedAST, enviroment); - - System.out.println("Command evaluated in " - + (double) (System.nanoTime() - time) / 1000000000 + " s"); - - // Print out the result of evaluating the - // expression - System.out.println("\t\tSample Result: " + sampleResult); - - // Update the 'last' meta-variable - enviroment.put("last", transformedAST); - } catch(UnsupportedOperationException usex) { - // Tell the user there was an error in - // evaluation - System.out.println("EVALUATION ERROR: " + usex.getLocalizedMessage()); - - // Get the next command - currentLine = getNextCommand(inputSource, commandNumber); - - // Process it - continue; - } - - // Increase the number of commands - commandNumber++; - - // Get the next command - currentLine = getNextCommand(inputSource, commandNumber); - } - - System.out.println("Bye."); - - // Cleanup after ourselves - inputSource.close(); - } - - // Transform a parsed AST - private static ITree<IDiceASTNode> transformAST(ITree<IDiceASTNode> builtAST, - IMap<String, ITree<IDiceASTNode>> enviroment) { - // Optimize the tree first - ITree<IDiceASTNode> optimizedTree = optimizer.optimizeTree(builtAST, enviroment); - - // Then, condense unnecessary operations - ITree<IDiceASTNode> condensedTree = OperationCondenser.condense(optimizedTree); - - // Next, sanitize references - ITree<IDiceASTNode> sanitizedTree = DiceASTReferenceSanitizer.sanitize(condensedTree, enviroment); - - // Re-optimize the sanitized & condensed tree - optimizedTree = optimizer.optimizeTree(sanitizedTree, enviroment); - - // Re-condense the newly optimized tree - condensedTree = OperationCondenser.condense(optimizedTree); - - return condensedTree; - } -} diff --git a/dice-lang/src/bjc/dicelang/v1/examples/DiceASTPragma.java b/dice-lang/src/bjc/dicelang/v1/examples/DiceASTPragma.java deleted file mode 100644 index 502dafd..0000000 --- a/dice-lang/src/bjc/dicelang/v1/examples/DiceASTPragma.java +++ /dev/null @@ -1,21 +0,0 @@ -package bjc.dicelang.v1.examples; - -import bjc.dicelang.v1.ast.nodes.IDiceASTNode; -import bjc.utils.data.ITree; -import bjc.utils.funcdata.FunctionalStringTokenizer; -import bjc.utils.funcdata.IMap; - -import java.util.function.BiConsumer; - -/** - * Alias for the type of a 'pragma' or special language command - * - * To explain it, a pragma is a function that takes a tokenizer with the rest of - * the line, and an enviroment that contains variable bindings - * - * @author ben - * - */ -public interface DiceASTPragma extends BiConsumer<FunctionalStringTokenizer, IMap<String, ITree<IDiceASTNode>>> { - // Just an alias -} diff --git a/dice-lang/src/bjc/dicelang/v1/examples/DiceExpressionParserTest.java b/dice-lang/src/bjc/dicelang/v1/examples/DiceExpressionParserTest.java deleted file mode 100644 index 9d51c28..0000000 --- a/dice-lang/src/bjc/dicelang/v1/examples/DiceExpressionParserTest.java +++ /dev/null @@ -1,58 +0,0 @@ -package bjc.dicelang.v1.examples; - -import bjc.dicelang.v1.DiceExpressionParser; -import bjc.dicelang.v1.IDiceExpression; - -import java.util.HashMap; -import java.util.Scanner; - -/** - * Driver class for testing expression parser - * - * @author ben - * - */ -public class DiceExpressionParserTest { - /** - * Run the parser test - * - * @param args - * Unused CLI arguments - */ - public static void main(String[] args) { - /* - * Get a scanner for input - */ - Scanner scn = new Scanner(System.in); - - /* - * Ask to enter a expression - */ - System.out.print("Enter dice expression: "); - - String exp = scn.nextLine(); - - /* - * Enter amount of times to roll an expression - */ - System.out.print("Enter number of times to roll: "); - - int nTimes = Integer.parseInt(scn.nextLine()); - - IDiceExpression dexp = DiceExpressionParser.parse(exp, new HashMap<>()); - - /* - * Roll the dice a specified amount of times - */ - for(int i = 1; i <= nTimes; i++) { - int roll = dexp.roll(); - - System.out.println("Rolled " + roll); - } - - /* - * Clean up after ourselves - */ - scn.close(); - } -} diff --git a/dice-lang/src/bjc/dicelang/v1/examples/DiceExpressionPreparer.java b/dice-lang/src/bjc/dicelang/v1/examples/DiceExpressionPreparer.java deleted file mode 100644 index 5f38374..0000000 --- a/dice-lang/src/bjc/dicelang/v1/examples/DiceExpressionPreparer.java +++ /dev/null @@ -1,98 +0,0 @@ -package bjc.dicelang.v1.examples; - -import bjc.utils.data.IPair; -import bjc.utils.data.Pair; -import bjc.utils.funcdata.FunctionalStringTokenizer; -import bjc.utils.funcdata.IList; -import bjc.utils.funcutils.ListUtils; -import bjc.utils.parserutils.ShuntingYard; - -import java.util.Deque; -import java.util.LinkedList; - -/** - * Prepare a dice expression to be parsed - * - * @author ben - * - */ -public class DiceExpressionPreparer { - /** - * The yard to use for shunting expressions - */ - private static ShuntingYard<String> yard; - - private static final int MATH_PREC = 20; - private static final int DICE_PREC = 10; - private static final int EXPR_PREC = 0; - - // Do initialization for all parsers - static { - // The shunter we're going to use - yard = new ShuntingYard<>(false); - - // Configure the shunters operators - // Basic mathematical operators - yard.addOp("+", 0 + MATH_PREC); - yard.addOp("-", 0 + MATH_PREC); - - yard.addOp("*", 1 + MATH_PREC); - yard.addOp("/", 1 + MATH_PREC); - - yard.addOp("d", 0 + DICE_PREC); // dice operator: use for - // creating - // variable size dice groups - yard.addOp("c", 1 + DICE_PREC); // compound operator: use for - // creating compound dice from expressions - - yard.addOp("=>", 0 + EXPR_PREC); // let operator: evaluate an - // expression in the context of another - yard.addOp(":=", 1 + EXPR_PREC); // binding operator: Bind a - // name - // to a variable expression - } - - /** - * Prepare a command, turning raw tokens into input for the tree builder - * - * @param currentLine - * The command to prepare - * @return A stream of tokens representing the command - */ - public static IList<String> prepareCommand(String currentLine) { - // Split the command into tokens - IList<String> tokens = FunctionalStringTokenizer.fromString(currentLine).toList(); - - // The linked list to use for handling tokens - Deque<IPair<String, String>> ops = new LinkedList<>(); - - // Prepare the list for operator expansion - ops.add(new Pair<>("+", "\\+")); - ops.add(new Pair<>("-", "-")); - ops.add(new Pair<>("*", "\\*")); - ops.add(new Pair<>("/", "/")); - ops.add(new Pair<>(":=", ":=")); - ops.add(new Pair<>("=>", "=>")); - - // Expand infix single tokens to multiple infix tokens - IList<String> semiExpandedTokens = ListUtils.splitTokens(tokens, ops); - - // Reinitialize the list - ops = new LinkedList<>(); - - // Prepare the list for deaffixation - ops.add(new Pair<>("(", "\\(")); - ops.add(new Pair<>(")", "\\)")); - ops.add(new Pair<>("[", "\\[")); - ops.add(new Pair<>("]", "\\]")); - - // Deaffix ('s and ['s from tokens - IList<String> fullyExpandedTokens = ListUtils.deAffixTokens(semiExpandedTokens, ops); - - // Remove blank tokens - fullyExpandedTokens.removeIf((strang) -> strang.equals("")); - - // Shunt the tokens, and hand them back - return yard.postfix(fullyExpandedTokens, (token) -> token); - } -} diff --git a/dice-lang/src/bjc/dicelang/v1/examples/DiceLanguageState.java b/dice-lang/src/bjc/dicelang/v1/examples/DiceLanguageState.java deleted file mode 100644 index 17c147c..0000000 --- a/dice-lang/src/bjc/dicelang/v1/examples/DiceLanguageState.java +++ /dev/null @@ -1,34 +0,0 @@ -package bjc.dicelang.v1.examples; - -import bjc.dicelang.v1.DiceExpressionParser; -import bjc.dicelang.v1.IDiceExpression; -import bjc.utils.data.Pair; - -import java.util.Map; - -/** - * Internal state of dice language - * - * @author ben - * - */ -public class DiceLanguageState extends Pair<DiceExpressionParser, Map<String, IDiceExpression>> { - - /** - * Create a new state - */ - public DiceLanguageState() { - } - - /** - * Create a new state with the desired parameters - * - * @param left - * The parser to use - * @param right - * The enviroment to use - */ - public DiceLanguageState(DiceExpressionParser left, Map<String, IDiceExpression> right) { - super(left, right); - } -} diff --git a/dice-lang/src/bjc/dicelang/v1/examples/DiceLanguageTest.java b/dice-lang/src/bjc/dicelang/v1/examples/DiceLanguageTest.java deleted file mode 100644 index 9a13b78..0000000 --- a/dice-lang/src/bjc/dicelang/v1/examples/DiceLanguageTest.java +++ /dev/null @@ -1,95 +0,0 @@ -package bjc.dicelang.v1.examples; - -import bjc.dicelang.v1.DiceExpressionParser; -import bjc.dicelang.v1.IDiceExpression; - -import java.util.HashMap; -import java.util.Map; -import java.util.Scanner; -import java.util.function.BiConsumer; - -/** - * Test of dice language - * - * @author ben - * - */ -public class DiceLanguageTest { - private static Map<String, BiConsumer<String, DiceLanguageState>> acts; - - static { - acts = new HashMap<>(); - - acts.put("roll", DiceLanguageTest::rollReference); - acts.put("env", DiceLanguageTest::printEnv); - } - - /** - * Main method - * - * @param args - * Unused CLI args - */ - public static void main(String[] args) { - Scanner scn = new Scanner(System.in); - int i = 0; - - System.out.print("dice-lang-" + i + "> "); - String ln = scn.nextLine(); - - DiceExpressionParser dep = new DiceExpressionParser(); - Map<String, IDiceExpression> env = new HashMap<>(); - DiceLanguageState state = new DiceLanguageState(dep, env); - - while(!ln.equalsIgnoreCase("quit")) { - String header = ln.split(" ")[0]; - - if(acts.containsKey(header)) { - acts.get(header).accept(ln, state); - } else { - IDiceExpression exp = DiceExpressionParser.parse(ln, env); - - System.out.println("\tParsed: " + exp.toString()); - System.out.println("\tSample Roll: " + exp.roll()); - - env.put("last", exp); - } - - i++; - - System.out.print("dice-lang-" + i + "> "); - ln = scn.nextLine(); - } - - System.out.println("Bye."); - scn.close(); - } - - /** - * @param ln - * Unused parameter, kept to comply with expected type - * sig - */ - private static void printEnv(String ln, DiceLanguageState stat) { - System.out.println("Printing enviroment for debugging purposes."); - - stat.doWith((dep, env) -> env.forEach( - (key, exp) -> System.out.println("\tKey: " + key + "\tExp: " + exp.toString()))); - } - - private static void rollReference(String ln, DiceLanguageState stat) { - String[] strangs = ln.split(" "); - - System.out.println("\tRolling dice expression " + strangs[1] + " " + strangs[2] + " times."); - - int nRolls = Integer.parseInt(strangs[2]); - - IDiceExpression dexp = stat.merge((dep, env) -> env.get(strangs[1])); - - for(int i = 1; i <= nRolls; i++) { - int roll = dexp.roll(); - - System.out.println("\tRolled " + roll); - } - } -} |
