summaryrefslogtreecommitdiff
path: root/base/src/bjc/dicelang/eval/Evaluator.java
diff options
context:
space:
mode:
Diffstat (limited to 'base/src/bjc/dicelang/eval/Evaluator.java')
-rw-r--r--base/src/bjc/dicelang/eval/Evaluator.java74
1 files changed, 72 insertions, 2 deletions
diff --git a/base/src/bjc/dicelang/eval/Evaluator.java b/base/src/bjc/dicelang/eval/Evaluator.java
index 9e41017..3717de3 100644
--- a/base/src/bjc/dicelang/eval/Evaluator.java
+++ b/base/src/bjc/dicelang/eval/Evaluator.java
@@ -1,5 +1,6 @@
package bjc.dicelang.eval;
+import java.math.BigDecimal;
import java.util.Deque;
import java.util.Iterator;
import java.util.LinkedList;
@@ -8,6 +9,7 @@ import java.util.function.Consumer;
import bjc.dicelang.DiceLangEngine;
import bjc.dicelang.Errors;
import bjc.dicelang.Node;
+import bjc.dicelang.Node.Type;
import bjc.dicelang.dice.CompoundDie;
import bjc.dicelang.dice.Die;
import bjc.dicelang.dice.MathDie;
@@ -15,6 +17,7 @@ import bjc.dicelang.dice.ScalarDiceExpression;
import bjc.dicelang.dice.ScalarDie;
import bjc.dicelang.dice.SimpleDie;
import bjc.dicelang.dice.SimpleDieList;
+import bjc.dicelang.tokens.DecimalToken;
import bjc.dicelang.tokens.DiceToken;
import bjc.dicelang.tokens.FloatToken;
import bjc.dicelang.tokens.Token;
@@ -42,7 +45,7 @@ import static bjc.dicelang.eval.EvaluatorResult.Type.*;
public class Evaluator {
/* The steps of type coercion. */
private static enum CoerceSteps {
- INTEGER, DOUBLE;
+ INTEGER, DOUBLE, DECIMAL;
}
/* The context during iteration. */
@@ -254,7 +257,9 @@ public class Evaluator {
/* Move up to coercing to a float. */
if (res.type == FLOAT) {
curLevel = CoerceSteps.DOUBLE;
- }
+ } else if (res.type == DEC) {
+ curLevel = CoerceSteps.DECIMAL;
+ }
children.add(nChild);
}
@@ -272,6 +277,20 @@ public class Evaluator {
IntegerEvaluatorResult rs = (IntegerEvaluatorResult) res;
nd.resultVal = new FloatEvaluatorResult(rs.value);
+ } else if (curLevel == CoerceSteps.DECIMAL) {
+ IntegerEvaluatorResult rs = (IntegerEvaluatorResult) res;
+
+ nd.resultVal = new DecimalEvaluatorResult(new BigDecimal(rs.value));
+ }
+ break;
+ case FLOAT:
+ /*
+ * Coerce decimals to doubles if we need to.
+ */
+ if (curLevel == CoerceSteps.DECIMAL) {
+ FloatEvaluatorResult rs = (FloatEvaluatorResult) res;
+
+ nd.resultVal = new DecimalEvaluatorResult(new BigDecimal(rs.floatVal));
}
default:
/* Do nothing */
@@ -462,6 +481,9 @@ public class Evaluator {
} else if (left.type == INT && right.type != INT) {
Errors.inst.printError(EK_EVAL_MISMATH);
return new SimpleTree<>(Node.FAIL(right));
+ } else if (left.type == DEC && right.type != DEC) {
+ Errors.inst.printError(EK_EVAL_MISMATH);
+ return new SimpleTree<>(Node.FAIL(right));
} else if (left.type == FLOAT && right.type != FLOAT) {
Errors.inst.printError(EK_EVAL_MISMATH);
return new SimpleTree<>(Node.FAIL(right));
@@ -474,6 +496,9 @@ public class Evaluator {
} else if (right.type == FLOAT && left.type != FLOAT) {
Errors.inst.printError(EK_EVAL_MISMATH);
return new SimpleTree<>(Node.FAIL(left));
+ } else if (right.type == DEC && left.type != DEC) {
+ Errors.inst.printError(EK_EVAL_MISMATH);
+ return new SimpleTree<>(Node.FAIL(left));
} else if (right.type == DICE && left.type != DICE) {
Errors.inst.printError(EK_EVAL_MISMATH);
return new SimpleTree<>(Node.FAIL(left));
@@ -488,6 +513,11 @@ public class Evaluator {
long rval = ((IntegerEvaluatorResult) right).value;
res = new IntegerEvaluatorResult(lval + rval);
+ } else if (left.type == DEC) {
+ BigDecimal lval = ((DecimalEvaluatorResult) left).val;
+ BigDecimal rval = ((DecimalEvaluatorResult) right).val;
+
+ res = new DecimalEvaluatorResult(lval.add(rval));
} else if (left.type == DICE) {
if (((DiceEvaluatorResult) left).diceVal.isList()) {
Errors.inst.printError(EK_EVAL_INVDICE, left.toString());
@@ -514,6 +544,11 @@ public class Evaluator {
long rval = ((IntegerEvaluatorResult) right).value;
res = new IntegerEvaluatorResult(lval - rval);
+ } else if (left.type == DEC) {
+ BigDecimal lval = ((DecimalEvaluatorResult) left).val;
+ BigDecimal rval = ((DecimalEvaluatorResult) right).val;
+
+ res = new DecimalEvaluatorResult(lval.subtract(rval));
} else if (left.type == DICE) {
if (((DiceEvaluatorResult) left).diceVal.isList()) {
Errors.inst.printError(EK_EVAL_INVDICE, left.toString());
@@ -540,6 +575,11 @@ public class Evaluator {
long rval = ((IntegerEvaluatorResult) right).value;
res = new IntegerEvaluatorResult(lval * rval);
+ } else if (left.type == DEC) {
+ BigDecimal lval = ((DecimalEvaluatorResult) left).val;
+ BigDecimal rval = ((DecimalEvaluatorResult) right).val;
+
+ res = new DecimalEvaluatorResult(lval.multiply(rval));
} else if (left.type == DICE) {
if (((DiceEvaluatorResult) left).diceVal.isList()) {
Errors.inst.printError(EK_EVAL_INVDICE, left.toString());
@@ -571,6 +611,24 @@ public class Evaluator {
} else {
res = new FloatEvaluatorResult(lval / rval);
}
+ } else if (left.type == DEC) {
+ BigDecimal lval = ((DecimalEvaluatorResult) left).val;
+ BigDecimal rval = ((DecimalEvaluatorResult) right).val;
+
+ if (rval.equals(BigDecimal.ZERO)) {
+ Errors.inst.printError(EK_EVAL_DIVZERO);
+ res = new FailureEvaluatorResult(right);
+ }
+ try {
+ res = new DecimalEvaluatorResult(lval.divide(rval));
+ } catch (ArithmeticException aex) {
+ Errors.inst.printError(EK_EVAL_ARITH, aex.getMessage());
+ SimpleTree<Node> cause = new SimpleTree<Node>(new Node(Type.BINOP, op),
+ new SimpleTree<>(new Node(Type.RESULT, left)),
+ new SimpleTree<>(new Node(Type.RESULT, right)));
+
+ res = new FailureEvaluatorResult(cause);
+ }
} else if (left.type == FLOAT) {
if (((FloatEvaluatorResult) right).floatVal == 0) {
Errors.inst.printError(EK_EVAL_DIVZERO);
@@ -597,6 +655,15 @@ public class Evaluator {
} else {
res = new IntegerEvaluatorResult((int) (lval / rval));
}
+ } else if (left.type == DEC) {
+ BigDecimal lval = ((DecimalEvaluatorResult) left).val;
+ BigDecimal rval = ((DecimalEvaluatorResult) right).val;
+
+ if (rval.equals(BigDecimal.ZERO)) {
+ Errors.inst.printError(EK_EVAL_DIVZERO);
+ res = new FailureEvaluatorResult(right);
+ }
+ res = new DecimalEvaluatorResult(lval.divideToIntegralValue(rval));
} else if (left.type == FLOAT) {
if (((FloatEvaluatorResult) right).floatVal == 0) {
Errors.inst.printError(EK_EVAL_DIVZERO);
@@ -634,6 +701,9 @@ public class Evaluator {
case DICE_LIT:
res = new DiceEvaluatorResult(((DiceToken) tk).diceValue);
break;
+ case DEC_LIT:
+ res = new DecimalEvaluatorResult(((DecimalToken) tk).val);
+ break;
case STRING_LIT:
res = new StringEvaluatorResult(eng.getStringLiteral((int) tk.intValue));
break;