summaryrefslogtreecommitdiff
path: root/base
diff options
context:
space:
mode:
authorstudent <student@localhost>2018-04-04 16:26:53 -0400
committerstudent <student@localhost>2018-04-04 16:26:53 -0400
commit43524b0742f195304829e5bd4dd12492f8ad1aa1 (patch)
tree8b0a82ce08c8636be9bad88786bc087347ddc1a6 /base
parent9f492d118835acab63dab02bd601475e4127dd28 (diff)
More Evaluator work
Diffstat (limited to 'base')
-rw-r--r--base/src/bjc/dicelang/eval/Evaluator.java218
-rw-r--r--base/src/bjc/dicelang/eval/EvaluatorResult.java39
-rw-r--r--base/src/bjc/dicelang/eval/IntegerEvaluatorResult.java38
3 files changed, 180 insertions, 115 deletions
diff --git a/base/src/bjc/dicelang/eval/Evaluator.java b/base/src/bjc/dicelang/eval/Evaluator.java
index f754c59..d93958f 100644
--- a/base/src/bjc/dicelang/eval/Evaluator.java
+++ b/base/src/bjc/dicelang/eval/Evaluator.java
@@ -162,104 +162,125 @@ public class Evaluator {
}
switch (ast.getHead().operatorType) {
- /*
- * @TODO 10/09/17 Ben Culkin :CoerceRefactor
- *
- * :EvaluatorSplit
- *
- * Coercing should be moved to its own class, or at the very least its own
- * method. When the evaluator splits, this node type'll be handled exclusively
- * by the type-checker.
- *
- * Coerce also needs to be able to coerce things to dice and ratios (whenever
- * they get added).
- */
case COERCE:
- final ITree<Node> toCoerce = ast.getChild(0);
- final ITree<Node> retVal = new Tree<>(toCoerce.getHead());
- final Deque<ITree<Node>> children = new LinkedList<>();
+ return doTypeCoercion(ast, ctx);
- /* The current type we are coercing to. */
- CoerceSteps curLevel = CoerceSteps.INTEGER;
+ case DICESCALAR: {
+ final EvaluatorResult opr = ast.getChild(0).getHead().resultVal;
- for (int i = 0; i < toCoerce.getChildrenCount(); i++) {
- final ITree<Node> child = toCoerce.getChild(i);
- ITree<Node> nChild = null;
+ if (opr.type != INT) {
+ Errors.inst.printError(EK_EVAL_INVDCREATE, opr.type.toString());
+ }
- /* Tell our thunk we processed a node. */
- if (ctx.isDebug) {
- /* Evaluate each step of the child. */
- final Iterator<ITree<Node>> nd = stepDebug(child);
+ IntegerEvaluatorResult irs = (IntegerEvaluatorResult) opr;
- for (; nd.hasNext(); nChild = nd.next()) {
- ctx.thunk.accept(new SingleIterator<>(child));
- }
- } else {
- /* Evaluate the child. */
- nChild = new Tree<>(new Node(Node.Type.RESULT, evaluate(child)));
+ ScalarDie die = new ScalarDie(irs.value);
- ctx.thunk.accept(new SingleIterator<>(nChild));
- }
+ final EvaluatorResult sres = new DiceEvaluatorResult(die);
- if (nChild == null) {
- Errors.inst.printError(EK_EVAL_INVNODE);
- return new Tree<>(Node.FAIL(ast));
- }
+ return new Tree<>(new Node(Node.Type.RESULT, sres));
+ }
+ case DICEFUDGE: {
+ final EvaluatorResult oprn = ast.getChild(0).getHead().resultVal;
- final Node childNode = nChild.getHead();
- final EvaluatorResult res = childNode.resultVal;
+ if (oprn.type != INT) {
+ Errors.inst.printError(EK_EVAL_INVDCREATE, oprn.type.toString());
+ }
- /* Move up to coercing to a float. */
- if (res.type == FLOAT) {
- curLevel = CoerceSteps.DOUBLE;
- }
+ IntegerEvaluatorResult irs = (IntegerEvaluatorResult) oprn;
- children.add(nChild);
- }
+ ScalarDie die = new ScalarDie(irs.value);
+
+ final EvaluatorResult fres = new DiceEvaluatorResult(die);
- for (final ITree<Node> child : children) {
- final Node nd = child.getHead();
- final EvaluatorResult res = nd.resultVal;
-
- switch (res.type) {
- case INT:
- /*
- * Coerce ints to doubles if we need to.
- */
- if (curLevel == CoerceSteps.DOUBLE) {
- nd.resultVal = new FloatEvaluatorResult((double) res.intVal);
- }
- default:
- /* Do nothing */
- break;
+ return new Tree<>(new Node(Node.Type.RESULT, fres));
+ }
+ default: {
+ Errors.inst.printError(EK_EVAL_INVUNARY, ast.getHead().operatorType.toString());
+
+ return new Tree<>(Node.FAIL(ast));
+ }
+ }
+ }
+
+ /*
+ * @TODO 10/09/17 Ben Culkin :CoerceRefactor
+ *
+ * :EvaluatorSplit
+ *
+ * Coercing should be moved to its own class, or at the very least its own
+ * method. When the evaluator splits, this node type'll be handled exclusively
+ * by the type-checker.
+ *
+ * Coerce also needs to be able to coerce things to dice and ratios (whenever
+ * they get added).
+ */
+ private ITree<Node> doTypeCoercion(final ITree<Node> ast, final Context ctx) {
+ final ITree<Node> toCoerce = ast.getChild(0);
+ final ITree<Node> retVal = new Tree<>(toCoerce.getHead());
+ final Deque<ITree<Node>> children = new LinkedList<>();
+
+ /* The current type we are coercing to. */
+ CoerceSteps curLevel = CoerceSteps.INTEGER;
+
+ for (int i = 0; i < toCoerce.getChildrenCount(); i++) {
+ final ITree<Node> child = toCoerce.getChild(i);
+ ITree<Node> nChild = null;
+
+ /* Tell our thunk we processed a node. */
+ if (ctx.isDebug) {
+ /* Evaluate each step of the child. */
+ final Iterator<ITree<Node>> nd = stepDebug(child);
+
+ for (; nd.hasNext(); nChild = nd.next()) {
+ ctx.thunk.accept(new SingleIterator<>(child));
}
+ } else {
+ /* Evaluate the child. */
+ nChild = new Tree<>(new Node(Node.Type.RESULT, evaluate(child)));
- retVal.addChild(child);
+ ctx.thunk.accept(new SingleIterator<>(nChild));
}
- return retVal;
- case DICESCALAR:
- final EvaluatorResult opr = ast.getChild(0).getHead().resultVal;
+ if (nChild == null) {
+ Errors.inst.printError(EK_EVAL_INVNODE);
+ return new Tree<>(Node.FAIL(ast));
+ }
- if (opr.type != INT) {
- Errors.inst.printError(EK_EVAL_INVDCREATE, opr.type.toString());
+ final Node childNode = nChild.getHead();
+ final EvaluatorResult res = childNode.resultVal;
+
+ /* Move up to coercing to a float. */
+ if (res.type == FLOAT) {
+ curLevel = CoerceSteps.DOUBLE;
}
- final EvaluatorResult sres = new DiceEvaluatorResult(new ScalarDie(opr.intVal));
- return new Tree<>(new Node(Node.Type.RESULT, sres));
- case DICEFUDGE:
- final EvaluatorResult oprn = ast.getChild(0).getHead().resultVal;
+ children.add(nChild);
+ }
- if (oprn.type != INT) {
- Errors.inst.printError(EK_EVAL_INVDCREATE, oprn.type.toString());
+ for (final ITree<Node> child : children) {
+ final Node nd = child.getHead();
+ final EvaluatorResult res = nd.resultVal;
+
+ switch (res.type) {
+ case INT:
+ /*
+ * Coerce ints to doubles if we need to.
+ */
+ if (curLevel == CoerceSteps.DOUBLE) {
+ IntegerEvaluatorResult rs = (IntegerEvaluatorResult) res;
+
+ nd.resultVal = new FloatEvaluatorResult((double) rs.value);
+ }
+ default:
+ /* Do nothing */
+ break;
}
- final EvaluatorResult fres = new DiceEvaluatorResult(new ScalarDie(oprn.intVal));
- return new Tree<>(new Node(Node.Type.RESULT, fres));
- default:
- Errors.inst.printError(EK_EVAL_INVUNARY, ast.getHead().operatorType.toString());
- return new Tree<>(Node.FAIL(ast));
+ retVal.addChild(child);
}
+
+ return retVal;
}
/* Evaluate a binary operator. */
@@ -310,7 +331,7 @@ public class Evaluator {
final String strang = ((StringEvaluatorResult) left).stringVal;
switch (op) {
- case STRCAT:
+ case STRCAT: {
if (right.type != STRING) {
Errors.inst.printError(EK_EVAL_UNSTRING, right.type.toString());
return new Tree<>(Node.FAIL(right));
@@ -320,20 +341,22 @@ public class Evaluator {
final EvaluatorResult cres = new StringEvaluatorResult(strang + strung);
return new Tree<>(new Node(Node.Type.RESULT, cres));
- case STRREP:
+ }
+ case STRREP: {
if (right.type != INT) {
Errors.inst.printError(EK_EVAL_INVSTRING, right.type.toString());
return new Tree<>(Node.FAIL(right));
}
String res = strang;
- final long count = right.intVal;
+ final long count = ((IntegerEvaluatorResult) right).value;
for (long i = 1; i < count; i++) {
res += strang;
}
return new Tree<>(new Node(Node.Type.RESULT, new StringEvaluatorResult(res)));
+ }
default:
Errors.inst.printError(EK_EVAL_UNSTRING, op.toString());
return new Tree<>(Node.FAIL());
@@ -353,7 +376,7 @@ public class Evaluator {
*
* ADDENDA: Replace the .diceVal.isList() with .isList()
*/
- case DICEGROUP:
+ case DICEGROUP: {
if (left.type == DICE && !((DiceEvaluatorResult) left).diceVal.isList()) {
Die lhs = ((ScalarDiceExpression) ((DiceEvaluatorResult) left).diceVal).scalar;
@@ -364,7 +387,7 @@ public class Evaluator {
res = new DiceEvaluatorResult(simple);
} else if (right.type == INT) {
- res = new DiceEvaluatorResult(new SimpleDie(lhs, right.intVal));
+ res = new DiceEvaluatorResult(new SimpleDie(lhs, ((IntegerEvaluatorResult) right).value));
} else {
Errors.inst.printError(EK_EVAL_INVDGROUP, right.type.toString());
return new Tree<>(Node.FAIL(right));
@@ -384,8 +407,8 @@ public class Evaluator {
Errors.inst.printError(EK_EVAL_INVDGROUP, left.type.toString());
return new Tree<>(Node.FAIL(left));
}
-
- case DICECONCAT:
+ }
+ case DICECONCAT: {
if (left.type != DICE || ((DiceEvaluatorResult) left).diceVal.isList()) {
Errors.inst.printError(EK_EVAL_INVDICE, left.type.toString());
return new Tree<>(Node.FAIL(left));
@@ -400,8 +423,8 @@ public class Evaluator {
}
break;
-
- case DICELIST:
+ }
+ case DICELIST: {
if (left.type != DICE || ((DiceEvaluatorResult) left).diceVal.isList()) {
Errors.inst.printError(EK_EVAL_INVDICE, left.type.toString());
return new Tree<>(Node.FAIL(left));
@@ -416,7 +439,7 @@ public class Evaluator {
}
break;
-
+ }
default:
Errors.inst.printError(EK_EVAL_UNDICE, op.toString());
return new Tree<>(Node.FAIL());
@@ -456,7 +479,7 @@ public class Evaluator {
EvaluatorResult res = null;
switch (op) {
- case ADD:
+ case ADD: {
if (left.type == INT) {
res = new EvaluatorResult(INT, left.intVal + right.intVal);
} else if (left.type == DICE) {
@@ -478,8 +501,8 @@ public class Evaluator {
}
break;
-
- case SUBTRACT:
+ }
+ case SUBTRACT: {
if (left.type == INT) {
res = new EvaluatorResult(INT, left.intVal - right.intVal);
} else if (left.type == DICE) {
@@ -501,8 +524,8 @@ public class Evaluator {
}
break;
-
- case MULTIPLY:
+ }
+ case MULTIPLY: {
if (left.type == INT) {
res = new EvaluatorResult(INT, left.intVal * right.intVal);
} else if (left.type == DICE) {
@@ -524,8 +547,8 @@ public class Evaluator {
}
break;
-
- case DIVIDE:
+ }
+ case DIVIDE: {
if (left.type == INT) {
if (right.intVal == 0) {
Errors.inst.printError(EK_EVAL_DIVZERO);
@@ -547,8 +570,8 @@ public class Evaluator {
}
break;
-
- case IDIVIDE:
+ }
+ case IDIVIDE: {
if (left.type == INT) {
if (right.intVal == 0) {
Errors.inst.printError(EK_EVAL_DIVZERO);
@@ -570,7 +593,7 @@ public class Evaluator {
}
break;
-
+ }
default:
Errors.inst.printError(EK_EVAL_UNMATH, op.toString());
return new Tree<>(Node.FAIL());
@@ -585,7 +608,7 @@ public class Evaluator {
switch (tk.type) {
case INT_LIT:
- res = new EvaluatorResult(INT, tk.intValue);
+ res = new IntegerEvaluatorResult(tk.intValue);
break;
case FLOAT_LIT:
res = new FloatEvaluatorResult(((FloatToken) tk).floatValue);
@@ -598,6 +621,7 @@ public class Evaluator {
break;
default:
Errors.inst.printError(EK_EVAL_UNTOK, tk.type.toString());
+
res = new EvaluatorResult(FAILURE);
}
diff --git a/base/src/bjc/dicelang/eval/EvaluatorResult.java b/base/src/bjc/dicelang/eval/EvaluatorResult.java
index 1a783ad..ff86447 100644
--- a/base/src/bjc/dicelang/eval/EvaluatorResult.java
+++ b/base/src/bjc/dicelang/eval/EvaluatorResult.java
@@ -46,37 +46,40 @@ public class EvaluatorResult {
*/
public final EvaluatorResult.Type type;
- // These may or may not have values based
- // off of the result type
- /**
- * The integer value of the result.
- */
- public long intVal;
-
/**
* Create a new result.
*
* @param typ
- * The type of the result.
+ * The type of the result.
*/
protected EvaluatorResult(final EvaluatorResult.Type typ) {
type = typ;
}
- /**
- * Create a new result.
- *
- * @param typ
- * @param iVal
- */
- public EvaluatorResult(final EvaluatorResult.Type typ, final long iVal) {
- this(typ);
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((type == null) ? 0 : type.hashCode());
+ return result;
+ }
- intVal = iVal;
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ EvaluatorResult other = (EvaluatorResult) obj;
+ if (type != other.type)
+ return false;
+ return true;
}
@Override
public String toString() {
- return type.toString();
+ return "EvaluatorResult [type=" + type + "]";
}
}
diff --git a/base/src/bjc/dicelang/eval/IntegerEvaluatorResult.java b/base/src/bjc/dicelang/eval/IntegerEvaluatorResult.java
new file mode 100644
index 0000000..f6f2ca0
--- /dev/null
+++ b/base/src/bjc/dicelang/eval/IntegerEvaluatorResult.java
@@ -0,0 +1,38 @@
+package bjc.dicelang.eval;
+
+public class IntegerEvaluatorResult extends EvaluatorResult {
+ public final long value;
+
+ public IntegerEvaluatorResult(long val) {
+ super(Type.INT);
+
+ value = val;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (int) (value ^ (value >>> 32));
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ IntegerEvaluatorResult other = (IntegerEvaluatorResult) obj;
+ if (value != other.value)
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "IntegerEvaluatorResult [value=" + value + "]";
+ }
+}