summaryrefslogtreecommitdiff
path: root/dice-lang/src/main/java/bjc/dicelang
diff options
context:
space:
mode:
authorbculkin2442 <bjculkin@mix.wvu.edu>2016-04-03 17:45:05 -0400
committerbculkin2442 <bjculkin@mix.wvu.edu>2016-04-03 17:45:05 -0400
commitc8ae1ec096f5d1ac6db4f3a0035f7da106444e4e (patch)
tree6c32c65d84d11efcea2bad699d0b68fbbb362290 /dice-lang/src/main/java/bjc/dicelang
parent9a6ac8c88689073cd0769da15b40c4fe091f0813 (diff)
General code refactoring and maintenance
Diffstat (limited to 'dice-lang/src/main/java/bjc/dicelang')
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/DiceASTExpression.java102
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/DiceASTFreezer.java144
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/DiceASTReferenceChecker.java63
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/DiceASTType.java27
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/IDiceASTNode.java9
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/IOperatorCollapser.java17
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/LiteralDiceNode.java60
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/OperatorDiceNode.java5
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/VariableDiceNode.java62
9 files changed, 379 insertions, 110 deletions
diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTExpression.java b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTExpression.java
index a79c466..078c952 100644
--- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTExpression.java
+++ b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTExpression.java
@@ -2,13 +2,12 @@ package bjc.dicelang.ast;
import java.util.HashMap;
import java.util.Map;
-import java.util.function.BinaryOperator;
-
import org.apache.commons.lang3.StringUtils;
import bjc.dicelang.ComplexDice;
import bjc.dicelang.CompoundDice;
import bjc.dicelang.IDiceExpression;
+
import bjc.utils.data.Pair;
import bjc.utils.parserutils.AST;
@@ -24,67 +23,84 @@ public class DiceASTExpression implements IDiceExpression {
/**
* Build the map of operations to use when collapsing the AST
*
- * @param env
+ * @param enviroment
* The enviroment to evaluate bindings and such against
* @return The operations to use when collapsing the AST
*/
- private static
- Map<IDiceASTNode, BinaryOperator<Pair<Integer, AST<IDiceASTNode>>>>
- buildOperations(Map<String, DiceASTExpression> env) {
- Map<IDiceASTNode, BinaryOperator<Pair<Integer, AST<IDiceASTNode>>>> opCollapsers =
+ private static Map<IDiceASTNode, IOperatorCollapser>
+ buildOperations(Map<String, DiceASTExpression> enviroment) {
+ Map<IDiceASTNode, IOperatorCollapser> operatorCollapsers =
new HashMap<>();
- opCollapsers.put(OperatorDiceNode.ADD, (left, right) -> {
- return left.merge((lval, last) -> right.merge((rval, rast) -> {
- return new Pair<>(lval + rval,
- new AST<>(OperatorDiceNode.ADD, last, rast));
- }));
-
- });
- opCollapsers.put(OperatorDiceNode.SUBTRACT, (left, right) -> {
- return left.merge((lval, last) -> right.merge((rval, rast) -> {
- return new Pair<>(lval - rval,
- new AST<>(OperatorDiceNode.SUBTRACT, last, rast));
- }));
-
- });
- opCollapsers.put(OperatorDiceNode.MULTIPLY, (left, right) -> {
- return left.merge((lval, last) -> right.merge((rval, rast) -> {
- return new Pair<>(lval * rval,
- new AST<>(OperatorDiceNode.MULTIPLY, last, rast));
- }));
-
- });
- opCollapsers.put(OperatorDiceNode.DIVIDE, (left, right) -> {
+ 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,
+ (left, right) -> {
+ return left.merge(
+ (lval, last) -> right.merge((rval, rast) -> {
+ return new Pair<>(lval - rval,
+ new AST<>(
+ OperatorDiceNode.SUBTRACT,
+ last, rast));
+ }));
+
+ });
+ operatorCollapsers.put(OperatorDiceNode.MULTIPLY,
+ (left, right) -> {
+ return left.merge(
+ (lval, last) -> right.merge((rval, rast) -> {
+ return new Pair<>(lval * rval,
+ new AST<>(
+ OperatorDiceNode.MULTIPLY,
+ last, rast));
+ }));
+
+ });
+ operatorCollapsers.put(OperatorDiceNode.DIVIDE, (left, right) -> {
return left.merge((lval, last) -> right.merge((rval, rast) -> {
return new Pair<>(lval / rval,
new AST<>(OperatorDiceNode.DIVIDE, last, rast));
}));
});
- opCollapsers.put(OperatorDiceNode.ASSIGN, (left, right) -> {
+ operatorCollapsers.put(OperatorDiceNode.ASSIGN, (left, right) -> {
return left.merge((lval, last) -> right.merge((rval, rast) -> {
String nam = last.collapse((nod) -> {
return ((VariableDiceNode) nod).getVariable();
}, (v) -> (lv, rv) -> null, (r) -> r);
- env.put(nam, new DiceASTExpression(rast, env));
+ enviroment.put(nam,
+ new DiceASTExpression(rast, enviroment));
return new Pair<>(rval,
new AST<>(OperatorDiceNode.ASSIGN, last, rast));
}));
});
- opCollapsers.put(OperatorDiceNode.COMPOUND, (left, right) -> {
- return left.merge((lval, last) -> right.merge((rval, rast) -> {
- int ival = Integer.parseInt(
- Integer.toString(lval) + Integer.toString(rval));
-
- return new Pair<>(ival,
- new AST<>(OperatorDiceNode.COMPOUND, last, rast));
- }));
- });
- opCollapsers.put(OperatorDiceNode.GROUP, (left, right) -> {
+ operatorCollapsers.put(OperatorDiceNode.COMPOUND,
+ (left, right) -> {
+ return left.merge(
+ (lval, last) -> right.merge((rval, rast) -> {
+ int ival = Integer
+ .parseInt(Integer.toString(lval)
+ + Integer.toString(rval));
+
+ return new Pair<>(ival,
+ new AST<>(
+ OperatorDiceNode.COMPOUND,
+ last, rast));
+ }));
+ });
+ operatorCollapsers.put(OperatorDiceNode.GROUP, (left, right) -> {
return left.merge((lval, last) -> right.merge((rval, rast) -> {
return new Pair<>(new ComplexDice(lval, rval).roll(),
@@ -92,7 +108,7 @@ public class DiceASTExpression implements IDiceExpression {
}));
});
- return opCollapsers;
+ return operatorCollapsers;
}
/**
@@ -176,7 +192,7 @@ public class DiceASTExpression implements IDiceExpression {
*/
@Override
public int roll() {
- Map<IDiceASTNode, BinaryOperator<Pair<Integer, AST<IDiceASTNode>>>> operations =
+ Map<IDiceASTNode, IOperatorCollapser> operations =
buildOperations(env);
return ast.collapse(this::evalLeaf, operations::get,
diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTFreezer.java b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTFreezer.java
index 0e2134b..bad24f8 100644
--- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTFreezer.java
+++ b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTFreezer.java
@@ -1,7 +1,9 @@
package bjc.dicelang.ast;
-import java.util.Map;
+import java.util.function.Function;
+import bjc.utils.funcdata.FunctionalList;
+import bjc.utils.funcdata.FunctionalMap;
import bjc.utils.parserutils.AST;
/**
@@ -12,32 +14,57 @@ import bjc.utils.parserutils.AST;
*
*/
public class DiceASTFreezer {
- /**
- * Expand a reference
- *
- * @param vnode
- * The node containing the reference to expand
- * @param env
- * The enviroment to expand against
- * @return The expanded reference
- */
- private static AST<IDiceASTNode> expandNode(VariableDiceNode vnode,
- Map<String, AST<IDiceASTNode>> env) {
- return env.get(vnode.getVariable());
+ private static class NodeFreezer
+ implements Function<IDiceASTNode, AST<IDiceASTNode>> {
+ private FunctionalMap<String, AST<IDiceASTNode>> enviroment;
+
+ public NodeFreezer(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);
+ }
}
- /**
- * Expand a reference
- *
- * @param vnode
- * The node containing the reference to expand
- * @param env
- * The enviroment to expand against
- * @return The expanded reference
- */
- private static AST<IDiceASTNode> expandNode2(VariableDiceNode vnode,
- Map<String, DiceASTExpression> env) {
- return env.get(vnode.getVariable()).getAst();
+ private static final class SelectiveFreezer extends NodeFreezer {
+
+ private FunctionalList<String> variableNames;
+
+ public SelectiveFreezer(
+ 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);
+ }
+ }
}
/**
@@ -49,20 +76,9 @@ public class DiceASTFreezer {
* The enviroment to get reference values from
* @return The tree with references frozen
*/
- @SuppressWarnings("unused")
public static AST<IDiceASTNode> freezeAST(AST<IDiceASTNode> tree,
- Map<String, AST<IDiceASTNode>> env) {
- return tree.collapse((nod) -> {
- if (nod instanceof VariableDiceNode) {
- return expandNode((VariableDiceNode) nod, env);
- } else {
- // Type is specified here so compiler can know the type
- // we're using
- return new AST<IDiceASTNode>(nod);
- }
- } , (op) -> (left, right) -> {
- return new AST<IDiceASTNode>(op, left, right);
- } , (r) -> r);
+ FunctionalMap<String, AST<IDiceASTNode>> env) {
+ return selectiveFreeze(tree, env);
}
/**
@@ -74,19 +90,43 @@ public class DiceASTFreezer {
* The enviroment to get reference values from
* @return The tree with references frozen
*/
- @SuppressWarnings("unused")
public static AST<IDiceASTNode> freezeAST(DiceASTExpression tree,
- Map<String, DiceASTExpression> env) {
- return tree.getAst().collapse((nod) -> {
- if (nod instanceof VariableDiceNode) {
- return expandNode2((VariableDiceNode) nod, env);
- } else {
- // Type is specified here so compiler can know the type
- // we're using
- return new AST<IDiceASTNode>(nod);
- }
- } , (op) -> (left, right) -> {
- return new AST<IDiceASTNode>(op, left, right);
- } , (r) -> r);
+ FunctionalMap<String, DiceASTExpression> env) {
+ return freezeAST(tree.getAst(),
+ env.mapValues(expression -> expression.getAst()));
+ }
+
+ /**
+ * Freeze references to specified variables
+ *
+ * @param tree
+ * The tree-backed expression to freeze references in
+ * @param env
+ * The enviroment to resolve variables against
+ * @param varNames
+ * The names of the variables to freeze
+ * @return An AST with the specified variables frozen
+ */
+ public static AST<IDiceASTNode> selectiveFreeze(AST<IDiceASTNode> tree,
+ FunctionalMap<String, AST<IDiceASTNode>> env,
+ String... varNames) {
+ return selectiveFreeze(tree, env, new FunctionalList<>(varNames));
+ }
+
+ /**
+ * Freeze references to specified variables
+ *
+ * @param tree
+ * The tree-backed expression to freeze references in
+ * @param env
+ * The enviroment to resolve variables against
+ * @param varNames
+ * The names of the variables to freeze
+ * @return An AST with the specified variables frozen
+ */
+ public static AST<IDiceASTNode> selectiveFreeze(AST<IDiceASTNode> tree,
+ FunctionalMap<String, AST<IDiceASTNode>> env,
+ FunctionalList<String> varNames) {
+ return tree.expand(new SelectiveFreezer(env, varNames));
}
-}
+} \ No newline at end of file
diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTReferenceChecker.java b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTReferenceChecker.java
new file mode 100644
index 0000000..aaabe8b
--- /dev/null
+++ b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTReferenceChecker.java
@@ -0,0 +1,63 @@
+package bjc.dicelang.ast;
+
+import java.util.function.Consumer;
+
+import bjc.utils.data.GenHolder;
+
+/**
+ * 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 GenHolder<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(GenHolder<Boolean> referencesVar,
+ String varName) {
+ this.referencesVariable = referencesVar;
+ this.varName = varName;
+ }
+
+ @Override
+ public void accept(IDiceASTNode astNode) {
+ if (!referencesVariable.unwrap(bool -> bool)) {
+ if (isDirectReferenceToLast(astNode)) {
+ referencesVariable.transform((bool) -> false);
+ }
+ }
+ }
+
+ /**
+ * Check if a given AST node directly references the meta-variable
+ * last
+ *
+ * @param astNode
+ * The node to check
+ * @return Whether or not the node directly references last
+ */
+ private boolean isDirectReferenceToLast(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/DiceASTType.java b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTType.java
new file mode 100644
index 0000000..0a128f5
--- /dev/null
+++ b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTType.java
@@ -0,0 +1,27 @@
+package bjc.dicelang.ast;
+
+/**
+ * An enum to represent the type of node an AST node is
+ *
+ * @author ben
+ *
+ */
+public enum DiceASTType {
+ /**
+ * A node that contains a literal value
+ */
+ LITERAL,
+ /**
+ * A node that contains an operator expression
+ */
+ OPERATOR,
+ /**
+ * A node that contains a variable reference
+ */
+ VARIABLE;
+
+ @Override
+ public String toString() {
+ return this.name().toLowerCase();
+ }
+} \ No newline at end of file
diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/IDiceASTNode.java b/dice-lang/src/main/java/bjc/dicelang/ast/IDiceASTNode.java
index 439bdac..38a1cc1 100644
--- a/dice-lang/src/main/java/bjc/dicelang/ast/IDiceASTNode.java
+++ b/dice-lang/src/main/java/bjc/dicelang/ast/IDiceASTNode.java
@@ -13,4 +13,11 @@ public interface IDiceASTNode {
* @return Whether or not this node represents an operator
*/
public boolean isOperator();
-}
+
+ /**
+ * Get the type of AST node this node is
+ *
+ * @return The type of AST node this AST node is
+ */
+ public DiceASTType getType();
+} \ 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
new file mode 100644
index 0000000..ebd0436
--- /dev/null
+++ b/dice-lang/src/main/java/bjc/dicelang/ast/IOperatorCollapser.java
@@ -0,0 +1,17 @@
+package bjc.dicelang.ast;
+
+import java.util.function.BinaryOperator;
+
+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/LiteralDiceNode.java b/dice-lang/src/main/java/bjc/dicelang/ast/LiteralDiceNode.java
index 8157844..b80f1a4 100644
--- a/dice-lang/src/main/java/bjc/dicelang/ast/LiteralDiceNode.java
+++ b/dice-lang/src/main/java/bjc/dicelang/ast/LiteralDiceNode.java
@@ -10,7 +10,7 @@ public class LiteralDiceNode implements IDiceASTNode {
/**
* The value contained by this node
*/
- private String data;
+ private String value;
/**
* Create a new node with the given value
@@ -19,12 +19,35 @@ public class LiteralDiceNode implements IDiceASTNode {
* The value to be in this node
*/
public LiteralDiceNode(String data) {
- this.data = data;
+ this.value = data;
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
@Override
- public boolean isOperator() {
- return false;
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ } else if (obj == null) {
+ return false;
+ } else if (getClass() != obj.getClass()) {
+ return false;
+ } else {
+ LiteralDiceNode other = (LiteralDiceNode) obj;
+
+ if (value == null) {
+ if (other.value != null) {
+ return false;
+ }
+ } else if (!value.equals(other.value)) {
+ return false;
+ }
+
+ return true;
+ }
}
/**
@@ -33,7 +56,30 @@ public class LiteralDiceNode implements IDiceASTNode {
* @return the data stored in this AST node
*/
public String getData() {
- return data;
+ return value;
+ }
+
+ @Override
+ public DiceASTType getType() {
+ return DiceASTType.LITERAL;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((value == null) ? 0 : value.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean isOperator() {
+ return false;
}
/*
@@ -43,6 +89,6 @@ public class LiteralDiceNode implements IDiceASTNode {
*/
@Override
public String toString() {
- return data;
+ return value;
}
-}
+} \ No newline at end of file
diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/OperatorDiceNode.java b/dice-lang/src/main/java/bjc/dicelang/ast/OperatorDiceNode.java
index 45c3d58..90e08b7 100644
--- a/dice-lang/src/main/java/bjc/dicelang/ast/OperatorDiceNode.java
+++ b/dice-lang/src/main/java/bjc/dicelang/ast/OperatorDiceNode.java
@@ -69,6 +69,11 @@ public enum OperatorDiceNode implements IDiceASTNode {
}
}
+ @Override
+ public DiceASTType getType() {
+ return DiceASTType.OPERATOR;
+ }
+
/*
* (non-Javadoc)
*
diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/VariableDiceNode.java b/dice-lang/src/main/java/bjc/dicelang/ast/VariableDiceNode.java
index e02952d..e2dec64 100644
--- a/dice-lang/src/main/java/bjc/dicelang/ast/VariableDiceNode.java
+++ b/dice-lang/src/main/java/bjc/dicelang/ast/VariableDiceNode.java
@@ -10,16 +10,50 @@ public class VariableDiceNode implements IDiceASTNode {
/**
* The variable referenced by this node
*/
- private String var;
+ private String variableName;
/**
* Create a new node representing the specified variable
*
- * @param data
+ * @param varName
* The name of the variable being referenced
*/
- public VariableDiceNode(String data) {
- this.var = data;
+ 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;
}
/**
@@ -28,7 +62,21 @@ public class VariableDiceNode implements IDiceASTNode {
* @return the variable referenced by this AST node
*/
public String getVariable() {
- return var;
+ 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;
}
/*
@@ -48,6 +96,6 @@ public class VariableDiceNode implements IDiceASTNode {
*/
@Override
public String toString() {
- return var;
+ return variableName;
}
-}
+} \ No newline at end of file