summaryrefslogtreecommitdiff
path: root/dice-lang/src/examples/java/bjc
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/examples/java/bjc
parent9a6ac8c88689073cd0769da15b40c4fe091f0813 (diff)
General code refactoring and maintenance
Diffstat (limited to 'dice-lang/src/examples/java/bjc')
-rw-r--r--dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTLanguagePragmaHandlers.java81
-rw-r--r--dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTLanguageState.java10
-rw-r--r--dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTLanguageTest.java253
3 files changed, 258 insertions, 86 deletions
diff --git a/dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTLanguagePragmaHandlers.java b/dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTLanguagePragmaHandlers.java
new file mode 100644
index 0000000..3eaf6b0
--- /dev/null
+++ b/dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTLanguagePragmaHandlers.java
@@ -0,0 +1,81 @@
+package bjc.dicelang.examples;
+
+import java.util.Map;
+import java.util.function.BiConsumer;
+
+import bjc.dicelang.ast.DiceASTExpression;
+import bjc.dicelang.ast.DiceASTFreezer;
+import bjc.dicelang.ast.DiceASTParser;
+import bjc.dicelang.ast.IDiceASTNode;
+import bjc.utils.funcdata.FunctionalMap;
+import bjc.utils.parserutils.AST;
+
+/**
+ * Container for pragma handlers
+ *
+ * @author ben
+ *
+ */
+public class DiceASTLanguagePragmaHandlers {
+ /**
+ * Handles freezing a specified expression to a new name
+ *
+ * @author ben
+ *
+ */
+ public static final class FreezeHandler implements
+ BiConsumer<DiceASTParser, Map<String, DiceASTExpression>> {
+ private String expressionToFreeze;
+ private String resultingVariable;
+
+ /**
+ * Create a new freeze handler
+ *
+ * @param expressionToFreeze
+ * The name of the expression to freeze
+ * @param resultingVariable
+ * The name of the variable to bind the frozen
+ * expression to
+ */
+ public FreezeHandler(String expressionToFreeze,
+ String resultingVariable) {
+ this.expressionToFreeze = expressionToFreeze;
+ this.resultingVariable = resultingVariable;
+ }
+
+ @Override
+ public void accept(DiceASTParser astParser,
+ Map<String, DiceASTExpression> enviroment) {
+ if (enviroment.containsKey(expressionToFreeze)) {
+ System.err.println(
+ "ERROR: There is no expression bound to the variable "
+ + expressionToFreeze + ".");
+ } else {
+ AST<IDiceASTNode> frozenAST = DiceASTFreezer.freezeAST(
+ enviroment.get(expressionToFreeze),
+ new FunctionalMap<>(enviroment));
+
+ enviroment.put(resultingVariable,
+ new DiceASTExpression(frozenAST, enviroment));
+ }
+ }
+ }
+
+ /**
+ * Print the enviroment for debugging/inspection purposes
+ *
+ * @author ben
+ *
+ */
+ public static final class EnviromentPrinter implements
+ BiConsumer<DiceASTParser, Map<String, DiceASTExpression>> {
+ @Override
+ public void accept(DiceASTParser astParser,
+ Map<String, DiceASTExpression> enviroment) {
+ enviroment.forEach((variable, boundExpression) -> System.out
+ .println("\tKey: " + variable + "\n\t\tExp: "
+ + boundExpression.toString()));
+ }
+ }
+
+}
diff --git a/dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTLanguageState.java b/dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTLanguageState.java
index f5a6a29..92e75e3 100644
--- a/dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTLanguageState.java
+++ b/dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTLanguageState.java
@@ -2,8 +2,8 @@ package bjc.dicelang.examples;
import java.util.Map;
-import bjc.dicelang.DiceExpressionParser;
import bjc.dicelang.ast.DiceASTExpression;
+import bjc.dicelang.ast.DiceASTParser;
import bjc.utils.data.Pair;
/**
@@ -12,8 +12,8 @@ import bjc.utils.data.Pair;
* @author ben
*
*/
-public class DiceASTLanguageState extends
- Pair<DiceExpressionParser, Map<String, DiceASTExpression>> {
+public class DiceASTLanguageState
+ extends Pair<DiceASTParser, Map<String, DiceASTExpression>> {
/**
* Create a new state
@@ -29,8 +29,8 @@ public class DiceASTLanguageState extends
* @param right
* The enviroment to use
*/
- public DiceASTLanguageState(DiceExpressionParser left,
+ public DiceASTLanguageState(DiceASTParser left,
Map<String, DiceASTExpression> right) {
super(left, right);
}
-}
+} \ No newline at end of file
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 e0f276d..a21ed66 100644
--- a/dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTLanguageTest.java
+++ b/dice-lang/src/examples/java/bjc/dicelang/examples/DiceASTLanguageTest.java
@@ -4,16 +4,18 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.function.BiConsumer;
-import java.util.function.Consumer;
-import bjc.dicelang.DiceExpressionParser;
import bjc.dicelang.IDiceExpression;
import bjc.dicelang.ast.DiceASTExpression;
import bjc.dicelang.ast.DiceASTFreezer;
import bjc.dicelang.ast.DiceASTParser;
+import bjc.dicelang.ast.DiceASTReferenceChecker;
import bjc.dicelang.ast.IDiceASTNode;
-import bjc.dicelang.ast.VariableDiceNode;
+
+import static bjc.dicelang.examples.DiceASTLanguagePragmaHandlers.*;
+
import bjc.utils.data.GenHolder;
+import bjc.utils.funcdata.FunctionalMap;
import bjc.utils.funcdata.bst.ITreePart.TreeLinearizationMethod;
import bjc.utils.parserutils.AST;
@@ -24,75 +26,127 @@ import bjc.utils.parserutils.AST;
*
*/
public class DiceASTLanguageTest {
- private static final class LastChecker
- implements Consumer<IDiceASTNode> {
- private GenHolder<Boolean> canUpdateLast;
+ /**
+ * The 'special commands' that aren't normal expressions that can be
+ * invoked from the prompt
+ */
+ private static Map<String, BiConsumer<String, DiceASTLanguageState>> specialCommands;
- public LastChecker(GenHolder<Boolean> canUpdateLast) {
- this.canUpdateLast = canUpdateLast;
- }
+ static {
+ specialCommands = new HashMap<>();
- @Override
- public void accept(IDiceASTNode tn) {
- if (tn instanceof VariableDiceNode && ((VariableDiceNode) tn)
- .getVariable().equals("last")) {
- canUpdateLast.transform((s) -> false);
- } else {
- canUpdateLast.transform((s) -> true);
- }
- }
+ // Put all the defined special commands in place
+ specialCommands.put("roll", DiceASTLanguageTest::rollReference);
+ specialCommands.put("env", DiceASTLanguageTest::printEnv);
+ specialCommands.put("freeze", DiceASTLanguageTest::freezeVar);
}
- private static Map<String, BiConsumer<String, DiceASTLanguageState>> acts;
-
- static {
- acts = new HashMap<>();
+ /**
+ * Freeze the references in an expression.
+ *
+ * This means replace variable references with the current contents of
+ * the variables they refer to
+ *
+ * @param command
+ * The command and its arguments
+ * @param languageState
+ * The state of the language at the moment
+ */
+ private static void freezeVar(String command,
+ DiceASTLanguageState languageState) {
+ // Split the string into components
+ String[] args = command.split(" ");
+
+ // Make sure we have the correct amount of arguments
+ if (args.length != 3) {
+ System.err.println(
+ "ERROR: Freeze requires you provide the name of expression"
+ + " to freeze, as well as the name of the variable to bind"
+ + " the result to.");
+ return;
+ }
- acts.put("roll", DiceASTLanguageTest::rollReference);
- acts.put("env", DiceASTLanguageTest::printEnv);
- acts.put("freeze", DiceASTLanguageTest::freezeVar);
- }
+ String expressionToFreeze = args[1];
- private static void freezeVar(String ln, DiceASTLanguageState stat) {
- String[] strangs = ln.split(" ");
+ String resultingVariable = args[2];
- System.out.println("Freezing references in " + strangs[1]);
+ System.out.println("Freezing references in " + args[1]
+ + " and binding to " + resultingVariable);
- stat.doWith((dep, env) -> {
- env.put(strangs[1], new DiceASTExpression(
- DiceASTFreezer.freezeAST(env.get(strangs[1]), env),
- env));
- });
+ languageState.doWith(
+ new FreezeHandler(expressionToFreeze, resultingVariable));
}
/**
- * @param ln
- * Unused parameter, kept in place to conform to expected
- * type sig
+ * Print all bound variables in the current enviroment, as well as what
+ * they're bound to
+ *
+ * @param command
+ * The command and its arguments
+ * @param stat
+ * The state of the language at the moment
*/
- private static void printEnv(String ln, DiceASTLanguageState stat) {
+ private static void printEnv(String command,
+ DiceASTLanguageState 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())));
+ stat.doWith(new EnviromentPrinter());
}
- private static void rollReference(String ln,
- DiceASTLanguageState stat) {
- String[] strangs = ln.split(" ");
+ /**
+ * Roll an expression a given number of times
+ *
+ * @param command
+ * The command and its arguments
+ * @param languageState
+ * The state of the language at the moments
+ */
+ private static void rollReference(String command,
+ DiceASTLanguageState languageState) {
+ String[] args = command.split(" ");
+
+ if (args.length != 3) {
+ System.err.println("ERROR: Roll requires two arguments."
+ + " The name of the expression to roll, "
+ + "followed by the number of times to roll it");
+ return;
+ }
- System.out.println("\tRolling dice expression " + strangs[1] + " "
- + strangs[2] + " times.");
+ System.out.println("\tRolling dice expression " + args[1] + " "
+ + args[2] + " times.");
- int nRolls = Integer.parseInt(strangs[2]);
+ String expressionName = args[1];
- IDiceExpression dexp =
- stat.merge((dep, env) -> env.get(strangs[1]));
+ int numberOfRolls;
- for (int i = 1; i <= nRolls; i++) {
- int roll = dexp.roll();
+ try {
+ numberOfRolls = Integer.parseInt(args[2]);
+ } catch (NumberFormatException nfex) {
+ System.err.println(
+ "ERROR: The second argument must be a valid number, and "
+ + args[2] + " is not one.");
+ return;
+ }
- System.out.println("\tRolled " + roll);
+ IDiceExpression expressionToRoll =
+ languageState.merge((astParser, enviroment) -> {
+ if (!enviroment.containsKey(expressionName)) {
+ return null;
+ } else {
+ return enviroment.get(expressionName);
+ }
+ });
+
+ if (expressionToRoll == null) {
+ System.err.println(
+ "ERROR: There is no expression bound to the variable "
+ + expressionName + ".");
+ }
+
+ for (int i = 1; i <= numberOfRolls; i++) {
+ int currentRoll = expressionToRoll.roll();
+
+ System.out.println("\tRolled " + currentRoll);
}
}
@@ -103,49 +157,86 @@ public class DiceASTLanguageTest {
* Unused CLI args
*/
public static void main(String[] args) {
- Scanner scn = new Scanner(System.in);
- int i = 0;
+ Scanner inputSource = new Scanner(System.in);
+ int commandNumber = 0;
- System.out.print("dice-lang-" + i + "> ");
- String ln = scn.nextLine();
+ System.out.print("dice-lang-" + commandNumber + "> ");
+ String currentLine = inputSource.nextLine();
- DiceASTParser dap = new DiceASTParser();
+ // The enviroment for variables
+ Map<String, DiceASTExpression> enviroment = new HashMap<>();
- DiceExpressionParser dep = new DiceExpressionParser();
- Map<String, DiceASTExpression> env = new HashMap<>();
- DiceASTLanguageState state = new DiceASTLanguageState(dep, env);
+ // The parser to turn strings into AST's
+ DiceASTParser astParser = new DiceASTParser();
- while (!ln.equalsIgnoreCase("quit")) {
- String header = ln.split(" ")[0];
+ DiceASTLanguageState languageState =
+ new DiceASTLanguageState(astParser, enviroment);
- if (acts.containsKey(header)) {
- acts.get(header).accept(ln, state);
- } else {
+ while (!currentLine.equalsIgnoreCase("quit")) {
+ String prospectiveCommandName = currentLine.split(" ")[0];
- AST<IDiceASTNode> builtAST = dap.buildAST(ln);
- DiceASTExpression exp =
- new DiceASTExpression(builtAST, env);
-
- System.out.println("\tParsed: " + exp.toString());
- System.out.println("\tSample Roll: " + exp.roll());
-
- GenHolder<Boolean> canUpdateLast = new GenHolder<>(false);
-
- exp.getAst().traverse(TreeLinearizationMethod.PREORDER,
- new LastChecker(canUpdateLast));
+ // Handle special commands
+ if (specialCommands.containsKey(prospectiveCommandName)) {
+ specialCommands.get(prospectiveCommandName)
+ .accept(currentLine, languageState);
+ } else {
- if (canUpdateLast.unwrap((s) -> s)) {
- env.put("last", exp);
+ // Build an AST from the string expression
+ AST<IDiceASTNode> builtAST =
+ astParser.buildAST(currentLine);
+
+ // Build a rollable expression from the AST
+ DiceASTExpression expression =
+ new DiceASTExpression(builtAST, enviroment);
+
+ // Print out results
+ System.out.println("\tParsed: " + expression.toString());
+ System.out
+ .println("\t\tSample Roll: " + expression.roll());
+
+ // Assume we can update last by default
+ GenHolder<Boolean> canUpdateLast = new GenHolder<>(true);
+
+ // Check that no node references last
+ expression.getAst().traverse(
+ TreeLinearizationMethod.PREORDER,
+ new DiceASTReferenceChecker(canUpdateLast,
+ "last"));
+
+ // Update last if we can
+ if (canUpdateLast.unwrap((flag) -> flag)) {
+ enviroment.put("last", expression);
+ } else {
+ // We need to freeze out references to last
+ enviroment.put("last",
+ freezeOutLast(enviroment, builtAST));
}
}
- i++;
+ // Increase the number of commands
+ commandNumber++;
- System.out.print("dice-lang-" + i + "> ");
- ln = scn.nextLine();
+ // Read a new command
+ System.out.print("dice-lang-" + commandNumber + "> ");
+ currentLine = inputSource.nextLine();
}
System.out.println("Bye.");
- scn.close();
+
+ // Cleanup after ourselves
+ inputSource.close();
+ }
+
+ private static DiceASTExpression freezeOutLast(
+ Map<String, DiceASTExpression> enviroment,
+ AST<IDiceASTNode> builtAST) {
+ FunctionalMap<String, AST<IDiceASTNode>> transformedEnviroment =
+ new FunctionalMap<>(enviroment)
+ .mapValues((expr) -> expr.getAst());
+
+ AST<IDiceASTNode> expressionSansLast = DiceASTFreezer
+ .selectiveFreeze(builtAST, transformedEnviroment, "last");
+
+ return new DiceASTExpression(expressionSansLast, enviroment);
}
}