summaryrefslogtreecommitdiff
path: root/dice-lang/src/main/java/bjc/dicelang/ast
diff options
context:
space:
mode:
Diffstat (limited to 'dice-lang/src/main/java/bjc/dicelang/ast')
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/DiceASTDefinedChecker.java61
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/DiceASTExpression.java307
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/DiceASTFlattener.java145
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/DiceASTInliner.java136
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/DiceASTParser.java144
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/DiceASTReferenceChecker.java60
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/IOperatorCollapser.java18
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/nodes/LiteralDiceNode.java13
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/nodes/OperatorDiceNode.java8
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/optimization/DiceASTOptimizer.java59
10 files changed, 44 insertions, 907 deletions
diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTDefinedChecker.java b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTDefinedChecker.java
deleted file mode 100644
index c26098c..0000000
--- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTDefinedChecker.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package bjc.dicelang.ast;
-
-import java.util.Map;
-import java.util.function.Consumer;
-
-import bjc.dicelang.ast.nodes.DiceASTType;
-import bjc.dicelang.ast.nodes.IDiceASTNode;
-import bjc.dicelang.ast.nodes.VariableDiceNode;
-import bjc.utils.data.IHolder;
-
-/**
- * Check if the specified node references a particular variable
- *
- * @author ben
- *
- */
-public final class DiceASTDefinedChecker
- implements Consumer<IDiceASTNode> {
- /**
- * This is true if the specified node references the set variable
- */
- private IHolder<Boolean> referencesVariable;
-
- private Map<String, DiceASTExpression> enviroment;
-
- /**
- * Create a new reference checker
- *
- * @param referencesVar
- * The holder of whether the variable is referenced or not
- * @param env
- * The enviroment to check undefinedness against
- */
- public DiceASTDefinedChecker(IHolder<Boolean> referencesVar,
- Map<String, DiceASTExpression> env) {
- this.referencesVariable = referencesVar;
- this.enviroment = env;
- }
-
- @Override
- public void accept(IDiceASTNode astNode) {
- referencesVariable.transform((bool) -> checkUndefined(astNode));
- }
-
- /**
- * Check if a given AST node references an undefined variable
- *
- * @param astNode
- * The node to check
- * @return Whether or not the node directly the variable
- */
- private boolean checkUndefined(IDiceASTNode astNode) {
- if (astNode.getType() == DiceASTType.VARIABLE) {
- VariableDiceNode node = (VariableDiceNode) astNode;
-
- return !enviroment.containsKey(node.getVariable());
- } else {
- return false;
- }
- }
-} \ No newline at end of file
diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTExpression.java b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTExpression.java
deleted file mode 100644
index 3552926..0000000
--- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTExpression.java
+++ /dev/null
@@ -1,307 +0,0 @@
-package bjc.dicelang.ast;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.function.Function;
-
-import bjc.dicelang.ComplexDice;
-import bjc.dicelang.IDiceExpression;
-import bjc.dicelang.ast.nodes.DiceASTType;
-import bjc.dicelang.ast.nodes.IDiceASTNode;
-import bjc.dicelang.ast.nodes.LiteralDiceNode;
-import bjc.dicelang.ast.nodes.OperatorDiceNode;
-import bjc.dicelang.ast.nodes.VariableDiceNode;
-import bjc.utils.data.GenHolder;
-import bjc.utils.data.Pair;
-import bjc.utils.funcdata.bst.ITreePart.TreeLinearizationMethod;
-import bjc.utils.parserutils.AST;
-
-/**
- * An implementation of {@link IDiceExpression} backed by an AST of
- * {@link IDiceASTNode}s
- *
- * @author ben
- *
- */
-public class DiceASTExpression implements IDiceExpression {
-
- private static final class VariableRetriever
- implements Function<IDiceASTNode, String> {
- @Override
- public String apply(IDiceASTNode node) {
- if (node.getType() != DiceASTType.VARIABLE) {
- throw new UnsupportedOperationException(
- "Attempted to assign to something that isn't a variable."
- + " This isn't supported yet. The problem node is "
- + node);
- }
-
- return ((VariableDiceNode) node).getVariable();
- }
- }
-
- /**
- * 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 Map<IDiceASTNode, IOperatorCollapser> buildOperations(
- Map<String, DiceASTExpression> enviroment) {
- Map<IDiceASTNode, IOperatorCollapser> operatorCollapsers = new HashMap<>();
-
- operatorCollapsers.put(OperatorDiceNode.ADD,
- (leftNode, rightNode) -> {
- return leftNode.merge((leftValue, leftAST) -> {
- return rightNode.merge((rightValue, rightAST) -> {
- return new Pair<>(leftValue + rightValue,
- new AST<>(OperatorDiceNode.ADD,
- leftAST, rightAST));
- });
- });
-
- });
- operatorCollapsers.put(OperatorDiceNode.SUBTRACT,
- (leftNode, rightNode) -> {
- return leftNode.merge((leftValue, leftAST) -> {
- return rightNode.merge((rightValue, rightAST) -> {
- return new Pair<>(leftValue - rightValue,
- new AST<>(OperatorDiceNode.SUBTRACT,
- leftAST, rightAST));
- });
- });
- });
-
- operatorCollapsers.put(OperatorDiceNode.MULTIPLY,
- (leftNode, rightNode) -> {
- return leftNode.merge((leftValue, leftAST) -> {
- return rightNode.merge((rightValue, rightAST) -> {
- return new Pair<>(leftValue * rightValue,
- new AST<>(OperatorDiceNode.MULTIPLY,
- leftAST, rightAST));
- });
- });
-
- });
- operatorCollapsers.put(OperatorDiceNode.DIVIDE,
- (leftNode, rightNode) -> {
- return leftNode.merge((leftValue, leftAST) -> {
- return rightNode.merge((rightValue, rightAST) -> {
- if (rightValue == 0) {
- throw new ArithmeticException(
- "Attempted to divide by zero. The AST of the problem expression is "
- + rightAST);
- }
-
- return new Pair<>(leftValue / rightValue,
- new AST<>(OperatorDiceNode.DIVIDE,
- leftAST, rightAST));
- });
- });
- });
-
- operatorCollapsers.put(OperatorDiceNode.ASSIGN, (left, right) -> {
- return parseBinding(enviroment, left, right);
- });
-
- operatorCollapsers.put(OperatorDiceNode.COMPOUND,
- DiceASTExpression::parseCompound);
-
- operatorCollapsers.put(OperatorDiceNode.GROUP,
- DiceASTExpression::parseGroup);
-
- return operatorCollapsers;
- }
-
- private static Pair<Integer, AST<IDiceASTNode>> parseBinding(
- Map<String, DiceASTExpression> enviroment,
- Pair<Integer, AST<IDiceASTNode>> left,
- Pair<Integer, AST<IDiceASTNode>> right) {
- return left.merge((leftValue, leftAST) -> {
- return right.merge((rightValue, rightAST) -> {
- String variableName = leftAST
- .collapse(new VariableRetriever(), (operator) -> {
- throw new UnsupportedOperationException(
- "Can only assign to plain variable names. The problem operator is "
- + operator);
- }, (returnedAST) -> returnedAST);
-
- GenHolder<Boolean> selfReference = new GenHolder<>(false);
-
- DiceASTReferenceChecker refChecker = new DiceASTReferenceChecker(
- selfReference, variableName);
-
- rightAST.traverse(TreeLinearizationMethod.PREORDER,
- refChecker);
-
- // Ignore meta-variable that'll be auto-frozen to restore
- // definition sanity
- if (selfReference.unwrap((bool) -> bool)
- && !variableName.equals("last")) {
- throw new UnsupportedOperationException(
- "Variable '" + variableName
- + "' references itself. Problematic definition: \n\t"
- + rightAST);
- }
-
- if (!variableName.equals("last")) {
- enviroment.put(variableName,
- new DiceASTExpression(rightAST, enviroment));
- } else {
- // Do nothing, last is a auto-handled meta-variable
- }
-
- return new Pair<>(rightValue, new AST<>(
- OperatorDiceNode.ASSIGN, leftAST, rightAST));
- });
- });
- }
-
- private static Pair<Integer, AST<IDiceASTNode>> parseCompound(
- Pair<Integer, AST<IDiceASTNode>> leftNode,
- Pair<Integer, AST<IDiceASTNode>> rightNode) {
- return leftNode.merge((leftValue, leftAST) -> {
- return rightNode.merge((rightValue, rightAST) -> {
- int compoundValue = Integer
- .parseInt(Integer.toString(leftValue)
- + Integer.toString(rightValue));
-
- return new Pair<>(compoundValue, new AST<>(
- OperatorDiceNode.COMPOUND, leftAST, rightAST));
- });
- });
- }
-
- private static Pair<Integer, AST<IDiceASTNode>> parseGroup(
- Pair<Integer, AST<IDiceASTNode>> leftNode,
- Pair<Integer, AST<IDiceASTNode>> rightNode) {
- return leftNode.merge((leftValue, leftAST) -> {
- return rightNode.merge((rightValue, rightAST) -> {
- if (leftValue < 0) {
- throw new UnsupportedOperationException(
- "Can't attempt to roll a negative number of dice."
- + " The problematic AST is "
- + leftAST);
- } else if (rightValue < 1) {
- throw new UnsupportedOperationException(
- "Can't roll dice with less than one side."
- + " The problematic AST is "
- + rightAST);
- }
-
- int rolledValue = new ComplexDice(leftValue, rightValue)
- .roll();
-
- return new Pair<>(rolledValue, new AST<>(
- OperatorDiceNode.GROUP, leftAST, rightAST));
- });
- });
- }
-
- /**
- * The AST this expression will evaluate
- */
- private AST<IDiceASTNode> ast;
-
- /**
- * The enviroment to evaluate bindings and such against
- */
- private Map<String, DiceASTExpression> env;
-
- /**
- * Create a new dice expression backed by an AST
- *
- * @param ast
- * The AST backing this expression
- * @param env
- * The enviroment to evaluate bindings against
- */
- public DiceASTExpression(AST<IDiceASTNode> ast,
- Map<String, DiceASTExpression> env) {
- this.ast = ast;
- this.env = env;
- }
-
- /**
- * Expand a leaf AST token into a pair for evaluation
- *
- * @param leafNode
- * The token to evaluate
- * @return A pair consisting of the token's value and the AST it
- * represents
- */
- private Pair<Integer, AST<IDiceASTNode>> evaluateLeaf(
- IDiceASTNode leafNode) {
- if (leafNode.getType() == DiceASTType.VARIABLE) {
- VariableDiceNode node = (VariableDiceNode) leafNode;
-
- return parseVariable(node);
- } else if (leafNode.getType() == DiceASTType.LITERAL) {
- LiteralDiceNode node = (LiteralDiceNode) leafNode;
-
- return node.toParseValue();
- } else {
- throw new UnsupportedOperationException("Found leaf operator "
- + leafNode + ". These aren't supported.");
- }
- }
-
- private Pair<Integer, AST<IDiceASTNode>> parseVariable(
- VariableDiceNode leafNode) {
- String varName = leafNode.getVariable();
-
- if (env.containsKey(varName)) {
- return new Pair<>(env.get(varName).roll(),
- new AST<>(leafNode));
- } else {
- // Handle special case for defining variables
- return new Pair<>(0, new AST<>(leafNode));
- }
- }
-
- /**
- * Get the AST bound to this expression
- *
- * @return the ast
- */
- public AST<IDiceASTNode> getAst() {
- return ast;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see bjc.utils.dice.IDiceExpression#roll()
- */
- @Override
- public int roll() {
- Map<IDiceASTNode, IOperatorCollapser> operations = buildOperations(
- env);
-
- return ast.collapse(this::evaluateLeaf, operations::get,
- (returnedValue) -> returnedValue
- .merge((left, right) -> left));
- }
-
- /*
- * (non-Javadoc)
- *
- * @see java.lang.Object#toString()
- */
- @Override
- public String toString() {
- return ast.toString();
- }
-
- @Override
- public int optimize() {
- throw new UnsupportedOperationException(
- "Use DiceASTOptimizer for optimizing these");
- }
-
- @Override
- public boolean canOptimize() {
- return false;
- }
-} \ No newline at end of file
diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTFlattener.java b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTFlattener.java
deleted file mode 100644
index a54a088..0000000
--- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTFlattener.java
+++ /dev/null
@@ -1,145 +0,0 @@
-package bjc.dicelang.ast;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.function.BinaryOperator;
-import java.util.function.Function;
-
-import org.apache.commons.lang3.StringUtils;
-
-import bjc.dicelang.BindingDiceExpression;
-import bjc.dicelang.ComplexDice;
-import bjc.dicelang.CompoundDice;
-import bjc.dicelang.OperatorDiceExpression;
-import bjc.dicelang.DiceExpressionType;
-import bjc.dicelang.IDiceExpression;
-import bjc.dicelang.ReferenceDiceExpression;
-import bjc.dicelang.ScalarDie;
-import bjc.dicelang.ast.nodes.DiceASTType;
-import bjc.dicelang.ast.nodes.IDiceASTNode;
-import bjc.dicelang.ast.nodes.LiteralDiceNode;
-import bjc.dicelang.ast.nodes.OperatorDiceNode;
-import bjc.dicelang.ast.nodes.VariableDiceNode;
-import bjc.utils.parserutils.AST;
-
-/**
- * Flatten an {@link AST} of {@link IDiceASTNode} into a
- * {@link IDiceExpression}
- *
- * @author ben
- *
- */
-public class DiceASTFlattener {
- private static final class NodeCollapser
- implements Function<IDiceASTNode, IDiceExpression> {
- private Map<String, IDiceExpression> enviroment;
-
- public NodeCollapser(Map<String, IDiceExpression> env) {
- this.enviroment = env;
- }
-
- @Override
- public IDiceExpression apply(IDiceASTNode nod) {
- if (nod.getType() == DiceASTType.LITERAL) {
- return expFromLiteral((LiteralDiceNode) nod);
- } else if (nod.getType() == DiceASTType.VARIABLE) {
- String varName = ((VariableDiceNode) nod).getVariable();
-
- return new ReferenceDiceExpression(varName, enviroment);
- } else {
- throw new UnsupportedOperationException(
- "Attempted to flatten something that can't be"
- + " flattened. The culprit is " + nod);
- }
- }
-
- /**
- * Create a dice expression from a literal token
- *
- * @param tok
- * The token to convert to an expression
- * @return The dice expression represented by the token
- */
- private static IDiceExpression
- expFromLiteral(LiteralDiceNode tok) {
- String data = tok.getData();
-
- if (data.equals("")) {
- throw new UnsupportedOperationException(
- "Can't convert a blank token into a literal");
- }
-
- if (StringUtils.countMatches(data, 'c') == 1
- && !data.equalsIgnoreCase("c")) {
- String[] strangs = data.split("c");
-
- return new CompoundDice(ComplexDice.fromString(strangs[0]),
- ComplexDice.fromString(strangs[1]));
- } else if (StringUtils.countMatches(data, 'd') == 1
- && !data.equalsIgnoreCase("d")) {
- return ComplexDice.fromString(data);
- } else {
- return new ScalarDie(Integer.parseInt(data));
- }
- }
- }
-
- /**
- * Build the operations to use for tree flattening
- *
- * @param env
- * The enviroment the tree will be flattened against
- * @return The operations needed for tree flattening
- */
- private static Map<IDiceASTNode, BinaryOperator<IDiceExpression>>
- buildOperations(Map<String, IDiceExpression> env) {
- Map<IDiceASTNode, BinaryOperator<IDiceExpression>> opCollapsers =
- new HashMap<>();
-
- opCollapsers.put(OperatorDiceNode.ADD, (left, right) -> {
- return new OperatorDiceExpression(right, left,
- DiceExpressionType.ADD);
- });
- opCollapsers.put(OperatorDiceNode.SUBTRACT, (left, right) -> {
- return new OperatorDiceExpression(right, left,
- DiceExpressionType.SUBTRACT);
- });
- opCollapsers.put(OperatorDiceNode.MULTIPLY, (left, right) -> {
- return new OperatorDiceExpression(right, left,
- DiceExpressionType.MULTIPLY);
- });
- opCollapsers.put(OperatorDiceNode.DIVIDE, (left, right) -> {
- return new OperatorDiceExpression(right, left,
- DiceExpressionType.DIVIDE);
- });
- opCollapsers.put(OperatorDiceNode.ASSIGN, (left, right) -> {
- return new BindingDiceExpression(left, right, env);
- });
- opCollapsers.put(OperatorDiceNode.COMPOUND, (left, right) -> {
- return new CompoundDice(left, right);
- });
- opCollapsers.put(OperatorDiceNode.GROUP, (left, right) -> {
- return new ComplexDice(left, right);
- });
-
- return opCollapsers;
- }
-
- /**
- * Flatten a AST into a dice expression
- *
- * @param ast
- * The AST to flatten
- * @param env
- * The enviroment to flatten against
- * @return The AST, flattened into a dice expression
- */
- public static IDiceExpression flatten(AST<IDiceASTNode> ast,
- Map<String, IDiceExpression> env) {
- Map<IDiceASTNode, BinaryOperator<IDiceExpression>> opCollapsers =
- buildOperations(env);
-
- return ast.collapse(new NodeCollapser(env), opCollapsers::get,
- (r) -> r);
- }
-}
diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTInliner.java b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTInliner.java
deleted file mode 100644
index ef4a904..0000000
--- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTInliner.java
+++ /dev/null
@@ -1,136 +0,0 @@
-package bjc.dicelang.ast;
-
-import java.util.function.Function;
-
-import bjc.dicelang.ast.nodes.DiceASTType;
-import bjc.dicelang.ast.nodes.IDiceASTNode;
-import bjc.dicelang.ast.nodes.VariableDiceNode;
-import bjc.utils.funcdata.FunctionalList;
-import bjc.utils.funcdata.FunctionalMap;
-import bjc.utils.parserutils.AST;
-
-/**
- * Inline references in a dice AST, replacing variable references with what
- * the variables refer to
- *
- * @author ben
- *
- */
-public class DiceASTInliner {
- private static class NodeInliner
- implements Function<IDiceASTNode, AST<IDiceASTNode>> {
- private FunctionalMap<String, AST<IDiceASTNode>> enviroment;
-
- public NodeInliner(FunctionalMap<String, AST<IDiceASTNode>> env) {
- enviroment = env;
- }
-
- @Override
- public AST<IDiceASTNode> apply(IDiceASTNode nod) {
- if (nod.getType() == DiceASTType.VARIABLE) {
- return expandNode((VariableDiceNode) nod);
- } else {
- return new AST<>(nod);
- }
- }
-
- protected AST<IDiceASTNode>
- expandNode(VariableDiceNode variableNode) {
- String varName = variableNode.getVariable();
-
- if (!enviroment.containsKey(varName)) {
- throw new IllegalArgumentException(
- "Attempted to freeze reference"
- + " to an undefined variable " + varName);
- }
-
- return enviroment.get(varName);
- }
- }
-
- private static final class SelectiveInliner extends NodeInliner {
-
- private FunctionalList<String> variableNames;
-
- public SelectiveInliner(
- FunctionalMap<String, AST<IDiceASTNode>> env,
- FunctionalList<String> varNames) {
- super(env);
-
- variableNames = varNames;
- }
-
- @Override
- protected AST<IDiceASTNode>
- expandNode(VariableDiceNode variableNode) {
- if (variableNames.contains(variableNode.getVariable())) {
- return super.expandNode(variableNode);
- } else {
- return new AST<>(variableNode);
- }
- }
- }
-
- /**
- * Inline the references in an AST
- *
- * @param tree
- * The tree to inline references in
- * @param env
- * The enviroment to get reference values from
- * @return The tree with references inlined
- */
- public static AST<IDiceASTNode> inlineAST(AST<IDiceASTNode> tree,
- FunctionalMap<String, AST<IDiceASTNode>> env) {
- return selectiveInline(tree, env);
- }
-
- /**
- * Inline the references in an expression backed by an AST
- *
- * @param tree
- * The tree-backed expression to inline references in
- * @param env
- * The enviroment to get reference values from
- * @return The tree with references inlined
- */
- public static AST<IDiceASTNode> inlineAST(DiceASTExpression tree,
- FunctionalMap<String, DiceASTExpression> env) {
- return inlineAST(tree.getAst(),
- env.mapValues(expression -> expression.getAst()));
- }
-
- /**
- * Inline references to specified variables
- *
- * @param tree
- * The tree-backed expression to inline references in
- * @param env
- * The enviroment to resolve variables against
- * @param varNames
- * The names of the variables to inline
- * @return An AST with the specified variables inlined
- */
- public static AST<IDiceASTNode> selectiveInline(AST<IDiceASTNode> tree,
- FunctionalMap<String, AST<IDiceASTNode>> env,
- String... varNames) {
- return selectiveInline(tree, env, new FunctionalList<>(varNames));
- }
-
- /**
- * Inline references to specified variables
- *
- * @param tree
- * The tree-backed expression to inline references in
- * @param env
- * The enviroment to resolve variables against
- * @param varNames
- * The names of the variables to inline
- * @return An AST with the specified variables inline
- */
- public static AST<IDiceASTNode> selectiveInline(AST<IDiceASTNode> tree,
- FunctionalMap<String, AST<IDiceASTNode>> env,
- FunctionalList<String> varNames) {
- return tree.expand(new SelectiveInliner(env, varNames));
- }
-} \ No newline at end of file
diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTParser.java b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTParser.java
deleted file mode 100644
index fb77ad5..0000000
--- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTParser.java
+++ /dev/null
@@ -1,144 +0,0 @@
-package bjc.dicelang.ast;
-
-import java.util.Deque;
-import java.util.LinkedList;
-import java.util.function.Function;
-
-import org.apache.commons.lang3.StringUtils;
-
-import bjc.dicelang.ast.nodes.IDiceASTNode;
-import bjc.dicelang.ast.nodes.LiteralDiceNode;
-import bjc.dicelang.ast.nodes.OperatorDiceNode;
-import bjc.dicelang.ast.nodes.VariableDiceNode;
-import bjc.utils.data.Pair;
-import bjc.utils.funcdata.FunctionalList;
-import bjc.utils.funcdata.FunctionalStringTokenizer;
-import bjc.utils.funcutils.ListUtils;
-import bjc.utils.parserutils.AST;
-import bjc.utils.parserutils.ShuntingYard;
-import bjc.utils.parserutils.TreeConstructor;
-
-/**
- * Create an AST from a string expression
- *
- * @author ben
- *
- */
-public class DiceASTParser {
- private static final class NodeBaker
- implements Function<String, IDiceASTNode> {
- @Override
- public IDiceASTNode apply(String tok) {
- if (isOperator(tok)) {
- return OperatorDiceNode.fromString(tok);
- } else if (NodeBaker.isLiteral(tok)) {
- return new LiteralDiceNode(tok);
- } else {
- return new VariableDiceNode(tok);
- }
- }
-
- /**
- * Check if a token represents a literal
- *
- * @param tok
- * The token to check
- * @return Whether or not the token represents a literal
- */
- private static boolean isLiteral(String tok) {
- if (StringUtils.countMatches(tok, 'c') == 1
- && !tok.equalsIgnoreCase("c")) {
- return true;
- } else if (StringUtils.countMatches(tok, 'd') == 1
- && !tok.equalsIgnoreCase("d")) {
- return true;
- } else {
- try {
- Integer.parseInt(tok);
- return true;
- } catch (NumberFormatException nfx) {
- return false;
- }
- }
- }
- }
-
- /**
- * The yard to use for shunting expressions
- */
- private static ShuntingYard<String> yard;
-
- static {
- yard = new ShuntingYard<>();
-
- yard.addOp("d", 5); // dice operator: use for creating variable
- // size dice groups
- yard.addOp("c", 6); // compound operator: use for creating compound
- // dice from expressions
- yard.addOp(":=", 0); // binding operator: Bind a name to a variable
- // expression
- }
-
- /**
- * Build an AST from a string expression
- *
- * @param exp
- * The string to build from
- * @return An AST built from the passed in string
- */
- public AST<IDiceASTNode> buildAST(String exp) {
- FunctionalList<String> tokens =
- FunctionalStringTokenizer.fromString(exp).toList();
-
- Deque<Pair<String, String>> ops = new LinkedList<>();
-
- ops.add(new Pair<>("+", "\\+"));
- ops.add(new Pair<>("-", "-"));
- ops.add(new Pair<>("*", "\\*"));
- ops.add(new Pair<>("/", "/"));
- ops.add(new Pair<>(":=", ":="));
-
- FunctionalList<String> semiExpandedTokens =
- ListUtils.splitTokens(tokens, ops);
-
- ops = new LinkedList<>();
-
- ops.add(new Pair<>("(", "\\("));
- ops.add(new Pair<>(")", "\\)"));
-
- FunctionalList<String> fullyExpandedTokens =
- ListUtils.deAffixTokens(semiExpandedTokens, ops);
-
- FunctionalList<String> shunted =
- yard.postfix(fullyExpandedTokens, (s) -> s);
-
- AST<String> rawAST = TreeConstructor.constructTree(shunted,
- DiceASTParser::isOperator);
-
- AST<IDiceASTNode> bakedAST = rawAST.transmuteAST(new NodeBaker());
-
- return bakedAST;
- }
-
- /**
- * Check if a token represents an operator
- *
- * @param tok
- * The token to check if it represents an operator
- * @return Whether or not the token represents an operator
- */
- private static boolean isOperator(String tok) {
- switch (tok) {
- case ":=":
- case "+":
- case "-":
- case "*":
- case "/":
- case "c":
- case "d":
- return true;
- default:
- return false;
- }
- }
-}
diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTReferenceChecker.java b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTReferenceChecker.java
deleted file mode 100644
index 8fa4d55..0000000
--- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTReferenceChecker.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package bjc.dicelang.ast;
-
-import java.util.function.Consumer;
-
-import bjc.dicelang.ast.nodes.DiceASTType;
-import bjc.dicelang.ast.nodes.IDiceASTNode;
-import bjc.dicelang.ast.nodes.VariableDiceNode;
-import bjc.utils.data.IHolder;
-
-/**
- * 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);
- } else {
- return false;
- }
- }
-} \ No newline at end of file
diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/IOperatorCollapser.java b/dice-lang/src/main/java/bjc/dicelang/ast/IOperatorCollapser.java
deleted file mode 100644
index c872583..0000000
--- a/dice-lang/src/main/java/bjc/dicelang/ast/IOperatorCollapser.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package bjc.dicelang.ast;
-
-import java.util.function.BinaryOperator;
-
-import bjc.dicelang.ast.nodes.IDiceASTNode;
-import bjc.utils.data.Pair;
-import bjc.utils.parserutils.AST;
-
-/**
- * Alias for operator collapsers. Because 68-char types are too long
- *
- * @author ben
- *
- */
-public interface IOperatorCollapser
- extends BinaryOperator<Pair<Integer, AST<IDiceASTNode>>> {
-
-}
diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/LiteralDiceNode.java b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/LiteralDiceNode.java
index e689c7f..1a6d2bf 100644
--- a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/LiteralDiceNode.java
+++ b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/LiteralDiceNode.java
@@ -38,7 +38,9 @@ public class LiteralDiceNode implements IDiceASTNode {
/**
* Create a new node with the given value
- * @param val The value for this node
+ *
+ * @param val
+ * The value for this node
*/
public LiteralDiceNode(int val) {
this(Integer.toString(val));
@@ -126,8 +128,12 @@ public class LiteralDiceNode implements IDiceASTNode {
try {
return new ScalarDie(Integer.parseInt(literalData));
} catch (NumberFormatException nfex) {
- throw new UnsupportedOperationException(
+ UnsupportedOperationException usex = new UnsupportedOperationException(
"Found malformed leaf token " + this);
+
+ usex.initCause(nfex);
+
+ throw usex;
}
}
}
@@ -165,7 +171,8 @@ public class LiteralDiceNode implements IDiceASTNode {
try {
Integer.parseInt(value);
return true;
- } catch (NumberFormatException nfex) {
+ } catch (@SuppressWarnings("unused") NumberFormatException nfex) {
+ // We don't care about details
return false;
}
}
diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/OperatorDiceNode.java b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/OperatorDiceNode.java
index e1eb316..2820cfb 100644
--- a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/OperatorDiceNode.java
+++ b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/OperatorDiceNode.java
@@ -38,7 +38,11 @@ public enum OperatorDiceNode implements IDiceASTNode {
/**
* Represents subtracting two nodes
*/
- SUBTRACT;
+ SUBTRACT,
+ /**
+ * Represents executing one statement in the context of the other
+ */
+ LET;
/**
* Create a operator node from a string
@@ -63,6 +67,8 @@ public enum OperatorDiceNode implements IDiceASTNode {
return GROUP;
case "c":
return COMPOUND;
+ case "->":
+ return LET;
default:
throw new IllegalArgumentException(
s + " is not a valid operator node");
diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/optimization/DiceASTOptimizer.java b/dice-lang/src/main/java/bjc/dicelang/ast/optimization/DiceASTOptimizer.java
index e6c62ee..f6be7ab 100644
--- a/dice-lang/src/main/java/bjc/dicelang/ast/optimization/DiceASTOptimizer.java
+++ b/dice-lang/src/main/java/bjc/dicelang/ast/optimization/DiceASTOptimizer.java
@@ -36,26 +36,26 @@ public class DiceASTOptimizer {
@Override
public AST<IDiceASTNode> apply(AST<IDiceASTNode> leftAST,
AST<IDiceASTNode> rightAST) {
- AST<IDiceASTNode> rightBranchOfLeftAST =
- leftAST.applyToRight((rightSideAST) -> rightSideAST);
- AST<IDiceASTNode> leftBranchOfLeftAST =
- leftAST.applyToRight((rightSideAST) -> rightSideAST);
+ AST<IDiceASTNode> rightBranchOfLeftAST = leftAST
+ .applyToRight((rightSideAST) -> rightSideAST);
+ AST<IDiceASTNode> leftBranchOfLeftAST = leftAST
+ .applyToRight((rightSideAST) -> rightSideAST);
boolean leftContainsNestedConstant = DiceASTOptimizer
.checkNodeType(rightBranchOfLeftAST, LITERAL)
&& DiceASTOptimizer.isNodeConstant(leftAST);
- boolean isRightConstant =
- DiceASTOptimizer.checkNodeType(rightAST, LITERAL)
- && DiceASTOptimizer.isNodeConstant(leftAST);
+ boolean isRightConstant = DiceASTOptimizer
+ .checkNodeType(rightAST, LITERAL)
+ && DiceASTOptimizer.isNodeConstant(leftAST);
if (leftContainsNestedConstant && isRightConstant) {
int combinedValue = valueCollapser.apply(
getNodeValue(rightBranchOfLeftAST),
getNodeValue(rightAST));
- AST<IDiceASTNode> newRightBranch =
- new AST<>(new LiteralDiceNode(combinedValue));
+ AST<IDiceASTNode> newRightBranch = new AST<>(
+ new LiteralDiceNode(combinedValue));
return new AST<>(type, leftBranchOfLeftAST,
newRightBranch);
@@ -82,13 +82,13 @@ public class DiceASTOptimizer {
@Override
public AST<IDiceASTNode> apply(AST<IDiceASTNode> leftAST,
AST<IDiceASTNode> rightAST) {
- boolean isLeftConstant =
- DiceASTOptimizer.checkNodeType(leftAST, LITERAL)
- && DiceASTOptimizer.isNodeConstant(leftAST);
+ boolean isLeftConstant = DiceASTOptimizer
+ .checkNodeType(leftAST, LITERAL)
+ && DiceASTOptimizer.isNodeConstant(leftAST);
- boolean isRightConstant =
- DiceASTOptimizer.checkNodeType(rightAST, LITERAL)
- && DiceASTOptimizer.isNodeConstant(leftAST);
+ boolean isRightConstant = DiceASTOptimizer
+ .checkNodeType(rightAST, LITERAL)
+ && DiceASTOptimizer.isNodeConstant(leftAST);
if (isLeftConstant) {
if (isRightConstant) {
@@ -107,10 +107,8 @@ public class DiceASTOptimizer {
}
}
- private static Map<IDiceASTNode, BinaryOperator<AST<IDiceASTNode>>>
- buildConstantCollapsers() {
- Map<IDiceASTNode, BinaryOperator<AST<IDiceASTNode>>> operatorCollapsers =
- new HashMap<>();
+ private static Map<IDiceASTNode, BinaryOperator<AST<IDiceASTNode>>> buildConstantCollapsers() {
+ Map<IDiceASTNode, BinaryOperator<AST<IDiceASTNode>>> operatorCollapsers = new HashMap<>();
operatorCollapsers.put(OperatorDiceNode.ADD,
new ArithmeticOperationCollapser(OperatorDiceNode.ADD,
@@ -131,10 +129,8 @@ public class DiceASTOptimizer {
return operatorCollapsers;
}
- private static Map<IDiceASTNode, BinaryOperator<AST<IDiceASTNode>>>
- buildNestedConstantCollapsers() {
- Map<IDiceASTNode, BinaryOperator<AST<IDiceASTNode>>> operatorCollapsers =
- new HashMap<>();
+ private static Map<IDiceASTNode, BinaryOperator<AST<IDiceASTNode>>> buildNestedConstantCollapsers() {
+ Map<IDiceASTNode, BinaryOperator<AST<IDiceASTNode>>> operatorCollapsers = new HashMap<>();
operatorCollapsers.put(OperatorDiceNode.ADD,
new NestedArithmeticOperationCollapser(
@@ -167,9 +163,9 @@ public class DiceASTOptimizer {
IDiceExpression leaf) {
if (leaf.canOptimize()) {
return new LiteralDiceNode(Integer.toString(leaf.optimize()));
- } else {
- return node;
}
+
+ return node;
}
private static AST<IDiceASTNode> finishTree(AST<IDiceASTNode> tree) {
@@ -184,14 +180,13 @@ public class DiceASTOptimizer {
* @return The optimized tree
*/
public static AST<IDiceASTNode> optimizeTree(AST<IDiceASTNode> tree) {
- AST<IDiceASTNode> astWithConstantsFolded =
- tree.collapse(DiceASTOptimizer::collapseLeaf,
- buildConstantCollapsers()::get,
- DiceASTOptimizer::finishTree);
+ AST<IDiceASTNode> astWithConstantsFolded = tree.collapse(
+ DiceASTOptimizer::collapseLeaf,
+ buildConstantCollapsers()::get,
+ DiceASTOptimizer::finishTree);
- AST<IDiceASTNode> astWithNestedConstantsFolded =
- astWithConstantsFolded.collapse(
- DiceASTOptimizer::collapseLeaf,
+ AST<IDiceASTNode> astWithNestedConstantsFolded = astWithConstantsFolded
+ .collapse(DiceASTOptimizer::collapseLeaf,
buildNestedConstantCollapsers()::get,
DiceASTOptimizer::finishTree);