summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbculkin2442 <bjculkin@mix.wvu.edu>2016-04-17 20:41:47 -0400
committerbculkin2442 <bjculkin@mix.wvu.edu>2016-04-17 20:41:47 -0400
commit7c222f25d4b2d9f3b149d880f0e1acf8d673e4f5 (patch)
treea07cd6b07522d9ffe24a82c5a1a487d307875561
parentd9437c1d328ccc2b26bd0aae19c2aff7140e466b (diff)
Fixed a bug with arithmetic operators
-rw-r--r--dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTLanguageTest.java67
-rw-r--r--dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTPragma.java19
-rw-r--r--dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTReferenceSanitizer.java28
-rw-r--r--dice-lang/src/examples/java/bjc/dicelang/examples/DiceExpressionPreparer.java7
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/ArithmeticCollapser.java22
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/DiceASTEvaluator.java8
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/DiceASTInliner.java115
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/DiceASTParser.java20
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/nodes/OperatorDiceNode.java4
9 files changed, 266 insertions, 24 deletions
diff --git a/dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTLanguageTest.java b/dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTLanguageTest.java
index 18f0562..5dbaff3 100644
--- a/dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTLanguageTest.java
+++ b/dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTLanguageTest.java
@@ -3,10 +3,11 @@ package bjc.dicelang.examples;
import java.util.Scanner;
import bjc.dicelang.ast.DiceASTEvaluator;
+import bjc.dicelang.ast.DiceASTInliner;
import bjc.dicelang.ast.DiceASTParser;
import bjc.dicelang.ast.nodes.IDiceASTNode;
-
import bjc.utils.funcdata.FunctionalMap;
+import bjc.utils.funcdata.FunctionalStringTokenizer;
import bjc.utils.funcdata.IFunctionalList;
import bjc.utils.funcdata.IFunctionalMap;
import bjc.utils.funcdata.ITree;
@@ -18,6 +19,49 @@ import bjc.utils.funcdata.ITree;
*
*/
public class DiceASTLanguageTest {
+ private static IFunctionalMap<String, DiceASTPragma> actions;
+
+ static {
+ actions = new FunctionalMap<>();
+
+ actions.put("inline", DiceASTLanguageTest::handleInlineAction);
+
+ actions.put("env", (tokenizer, enviroment) -> {
+ enviroment.forEach((varName, varValue) -> {
+ System.out.println(varName + " is bound to " + varValue);
+ });
+ });
+ }
+
+ private static void handleInlineAction(
+ FunctionalStringTokenizer tokenizer,
+ IFunctionalMap<String, ITree<IDiceASTNode>> enviroment) {
+ // Skip the pragma name
+ tokenizer.nextToken();
+
+ IFunctionalList<String> pragmaArgs = tokenizer.toList();
+
+ if (pragmaArgs.getSize() < 3) {
+ 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 {
+ String inlineExpression = pragmaArgs.getByIndex(0);
+ String variableName = pragmaArgs.getByIndex(1);
+
+ IFunctionalList<String> inlinedVariables =
+ pragmaArgs.tail().tail();
+
+ ITree<IDiceASTNode> inlinedExpression = DiceASTInliner
+ .selectiveInline(enviroment.get(inlineExpression),
+ enviroment, inlinedVariables);
+
+ enviroment.put(variableName, inlinedExpression);
+ }
+ }
+
/**
* Main method of class
*
@@ -36,6 +80,25 @@ public class DiceASTLanguageTest {
new FunctionalMap<>();
while (!currentLine.equalsIgnoreCase("quit")) {
+ String possibleActionName = currentLine.split(" ")[0];
+
+ if (actions.containsKey(possibleActionName)) {
+ System.err.println(
+ "\nTRACE: Executing action " + possibleActionName
+ + " with line " + currentLine + "\n");
+
+ // Execute action
+ FunctionalStringTokenizer tokenizer =
+ new FunctionalStringTokenizer(currentLine);
+
+ actions.get(possibleActionName).accept(tokenizer,
+ enviroment);
+
+ currentLine = getNextCommand(inputSource, commandNumber);
+
+ continue;
+ }
+
// Build an AST from the string expression
ITree<IDiceASTNode> builtAST;
@@ -83,7 +146,7 @@ public class DiceASTLanguageTest {
private static String getNextCommand(Scanner inputSource,
int commandNumber) {
- System.out.print("dice-lang-" + commandNumber + "> ");
+ System.out.print("\ndice-lang-" + commandNumber + "> ");
return inputSource.nextLine();
}
diff --git a/dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTPragma.java b/dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTPragma.java
new file mode 100644
index 0000000..67b0adc
--- /dev/null
+++ b/dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTPragma.java
@@ -0,0 +1,19 @@
+package bjc.dicelang.examples;
+
+import java.util.function.BiConsumer;
+
+import bjc.dicelang.ast.nodes.IDiceASTNode;
+import bjc.utils.funcdata.FunctionalStringTokenizer;
+import bjc.utils.funcdata.IFunctionalMap;
+import bjc.utils.funcdata.ITree;
+
+/**
+ * Alias for the type of a 'pragma' or special language command
+ *
+ * @author ben
+ *
+ */
+public interface DiceASTPragma extends
+ BiConsumer<FunctionalStringTokenizer, IFunctionalMap<String, ITree<IDiceASTNode>>> {
+ // Just an alias
+}
diff --git a/dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTReferenceSanitizer.java b/dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTReferenceSanitizer.java
new file mode 100644
index 0000000..b2e441d
--- /dev/null
+++ b/dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTReferenceSanitizer.java
@@ -0,0 +1,28 @@
+package bjc.dicelang.examples;
+
+import bjc.dicelang.ast.nodes.IDiceASTNode;
+import bjc.utils.funcdata.IFunctionalMap;
+import bjc.utils.funcdata.ITree;
+
+/**
+ * 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 {
+ /**
+ * Sanitize the references in an AST
+ *
+ * @param ast
+ * @param enviroment
+ * @return The sanitized AST
+ */
+ public static ITree<IDiceASTNode> sanitize(ITree<IDiceASTNode> ast,
+ IFunctionalMap<String, ITree<IDiceASTNode>> enviroment) {
+ // TODO implement me
+ return null;
+ }
+}
diff --git a/dice-lang/src/examples/java/bjc/dicelang/examples/DiceExpressionPreparer.java b/dice-lang/src/examples/java/bjc/dicelang/examples/DiceExpressionPreparer.java
index 1d46cc9..91abf7d 100644
--- a/dice-lang/src/examples/java/bjc/dicelang/examples/DiceExpressionPreparer.java
+++ b/dice-lang/src/examples/java/bjc/dicelang/examples/DiceExpressionPreparer.java
@@ -52,10 +52,17 @@ public class DiceExpressionPreparer {
ops.add(new Pair<>("(", "\\("));
ops.add(new Pair<>(")", "\\)"));
+ ops.add(new Pair<>("+", "\\+"));
+ ops.add(new Pair<>("-", "-"));
+ ops.add(new Pair<>("*", "\\*"));
+ ops.add(new Pair<>("/", "/"));
+ ops.add(new Pair<>(":=", ":="));
IFunctionalList<String> fullyExpandedTokens =
ListUtils.deAffixTokens(semiExpandedTokens, ops);
+ fullyExpandedTokens.removeIf((strang) -> strang.equals(""));
+
return yard.postfix(fullyExpandedTokens, (token) -> token);
}
}
diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/ArithmeticCollapser.java b/dice-lang/src/main/java/bjc/dicelang/ast/ArithmeticCollapser.java
index 5ad0a0f..5c00fe2 100644
--- a/dice-lang/src/main/java/bjc/dicelang/ast/ArithmeticCollapser.java
+++ b/dice-lang/src/main/java/bjc/dicelang/ast/ArithmeticCollapser.java
@@ -16,8 +16,7 @@ import bjc.utils.funcdata.Tree;
* @author ben
*
*/
-final class ArithmeticCollapser
- implements IOperatorCollapser {
+final class ArithmeticCollapser implements IOperatorCollapser {
private OperatorDiceNode type;
private BinaryOperator<Integer> valueOp;
@@ -35,12 +34,18 @@ final class ArithmeticCollapser
new Pair<>(0, new Tree<>(type));
BinaryOperator<IPair<Integer, ITree<IDiceASTNode>>> reducer =
- (accumulatedState, currentState) -> {
- return reduceStates(accumulatedState,
- currentState);
+ (currentState, accumulatedState) -> {
+ // Force evaluation of accumulated state to prevent
+ // certain bugs from occuring
+ accumulatedState.merge((l, r) -> null);
+
+ return reduceStates(accumulatedState, currentState);
};
- return nodes.reduceAux(initState, reducer, (state) -> state);
+ IPair<Integer, ITree<IDiceASTNode>> reducedState =
+ nodes.reduceAux(initState, reducer, (state) -> state);
+
+ return reducedState;
}
private IPair<Integer, ITree<IDiceASTNode>> reduceStates(
@@ -52,9 +57,8 @@ final class ArithmeticCollapser
.bind((currentValue, currentTree) -> {
accumulatedTree.addChild(currentTree);
- Integer combinedValue =
- valueOp.apply(accumulatedValue,
- currentValue);
+ Integer combinedValue = valueOp.apply(
+ accumulatedValue, currentValue);
return new Pair<>(combinedValue,
accumulatedTree);
diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTEvaluator.java b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTEvaluator.java
index e934b9f..016fa8a 100644
--- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTEvaluator.java
+++ b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTEvaluator.java
@@ -112,7 +112,10 @@ public class DiceASTEvaluator {
String variableName = ((VariableDiceNode) leafNode).getVariable();
if (enviroment.containsKey(variableName)) {
- return evaluateAST(enviroment.get(variableName), enviroment);
+ int result =
+ evaluateAST(enviroment.get(variableName), enviroment);
+
+ return result;
}
// Value to allow for assignments
@@ -148,6 +151,9 @@ public class DiceASTEvaluator {
IPair<Integer, ITree<IDiceASTNode>> valueNode =
nodes.getByIndex(1);
+ // Force valueNode to materialize for debugging purposes
+ valueNode.merge((l, r) -> null);
+
return nameNode.bindRight((nameTree) -> {
return valueNode.bind((valueValue, valueTree) -> {
if (containsSimpleVariable(nameTree)) {
diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTInliner.java b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTInliner.java
new file mode 100644
index 0000000..6091cc3
--- /dev/null
+++ b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTInliner.java
@@ -0,0 +1,115 @@
+package bjc.dicelang.ast;
+
+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.IFunctionalList;
+import bjc.utils.funcdata.IFunctionalMap;
+import bjc.utils.funcdata.ITree;
+import bjc.utils.funcdata.Tree;
+
+/**
+ * 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,
+ IFunctionalMap<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,
+ IFunctionalMap<String, ITree<IDiceASTNode>> enviroment,
+ boolean specificInline,
+ IFunctionalList<String> variableNames) {
+ if (node.getType() != DiceASTType.VARIABLE) {
+ return new Tree<>(node);
+ }
+
+ String variableName = ((VariableDiceNode) node).getVariable();
+
+ if (specificInline) {
+ if (variableNames.contains(variableName)) {
+ if (!enviroment.containsKey(variableName)) {
+ throw new UnsupportedOperationException(
+ "Attempted to inline non-existant variable "
+ + variableName);
+ }
+
+ return enviroment.get(variableName);
+ }
+ } else {
+ if (!enviroment.containsKey(variableName)) {
+ throw new UnsupportedOperationException(
+ "Attempted to inline non-existant variable "
+ + variableName);
+ }
+
+ return enviroment.get(variableName);
+ }
+
+ return new Tree<>(node);
+ }
+
+ /**
+ * Inline the specified variables in the AST
+ *
+ * @param ast
+ * The AST to inline variables into
+ * @param enviroment
+ * The enviroment to inline from
+ * @param variables
+ * The variables to inline
+ * @return The inlined AST
+ */
+ public static ITree<IDiceASTNode> selectiveInline(
+ ITree<IDiceASTNode> ast,
+ IFunctionalMap<String, ITree<IDiceASTNode>> enviroment,
+ String... variables) {
+ if (variables != null && variables.length > 0) {
+ IFunctionalList<String> variableNames =
+ new FunctionalList<>(variables);
+
+ return ast.flatMapTree((node) -> {
+ return inlineNode(node, enviroment, true, variableNames);
+ });
+ }
+
+ return ast.flatMapTree((node) -> {
+ return inlineNode(node, enviroment, false, null);
+ });
+ }
+
+ /**
+ * 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,
+ IFunctionalMap<String, ITree<IDiceASTNode>> enviroment,
+ IFunctionalList<String> variables) {
+ return selectiveInline(ast, enviroment,
+ variables.toArray(new String[0]));
+ }
+}
diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTParser.java b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTParser.java
index 95495bd..d8c94dc 100644
--- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTParser.java
+++ b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTParser.java
@@ -28,17 +28,21 @@ public class DiceASTParser {
* The list of tokens to convert
* @return An AST built from the tokens
*/
- public static ITree<IDiceASTNode> createFromString(
- IFunctionalList<String> tokens) {
- ITree<String> rawTokens = TreeConstructor.constructTree(tokens,
- (token) -> {
+ public static ITree<IDiceASTNode>
+ createFromString(IFunctionalList<String> tokens) {
+ ITree<String> rawTokens =
+ TreeConstructor.constructTree(tokens, (token) -> {
return isOperatorNode(token);
}, (operator) -> false, null);
+
// The last argument is valid because there are no special
// operators yet, so it'll never get called
- return rawTokens.rebuildTree(DiceASTParser::convertLeafNode,
- DiceASTParser::convertOperatorNode);
+ ITree<IDiceASTNode> tokenizedTree =
+ rawTokens.rebuildTree(DiceASTParser::convertLeafNode,
+ DiceASTParser::convertOperatorNode);
+
+ return tokenizedTree;
}
private static boolean isOperatorNode(String token) {
@@ -52,8 +56,8 @@ public class DiceASTParser {
}
private static IDiceASTNode convertLeafNode(String leafNode) {
- DiceLiteralType literalType = ILiteralDiceNode
- .getLiteralType(leafNode);
+ DiceLiteralType literalType =
+ ILiteralDiceNode.getLiteralType(leafNode);
if (literalType != null) {
switch (literalType) {
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 d034943..ab47b56 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
@@ -2,10 +2,6 @@ package bjc.dicelang.ast.nodes;
import static bjc.dicelang.ast.nodes.DiceOperatorType.*;
-// The following classes need to be changed upon addition of a new operator
-// 1. DiceASTExpression
-// 2. DiceASTFlattener
-// 3. DiceASTParser
/**
* A node that represents an operator
*