summaryrefslogtreecommitdiff
path: root/base/src/bjc/dicelang/eval
diff options
context:
space:
mode:
authorBenjamin Culkin <bjculkin@sitri.goetia>2023-11-09 01:58:31 +0000
committerBenjamin Culkin <bjculkin@sitri.goetia>2023-11-09 01:58:31 +0000
commit13a96e852f2fea4d3b3cb03cf803007b9b63041e (patch)
treeea7bff952e92efa4b932526a9c84e8bc70de9a6d /base/src/bjc/dicelang/eval
parentd9dcc94aa16a1609e47f8369dfe21a8d260887a9 (diff)
Add decimals
Add decimal literals and default to them over floats
Diffstat (limited to 'base/src/bjc/dicelang/eval')
-rw-r--r--base/src/bjc/dicelang/eval/DecimalEvaluatorResult.java39
-rw-r--r--base/src/bjc/dicelang/eval/Evaluator.java74
-rw-r--r--base/src/bjc/dicelang/eval/EvaluatorResult.java4
3 files changed, 115 insertions, 2 deletions
diff --git a/base/src/bjc/dicelang/eval/DecimalEvaluatorResult.java b/base/src/bjc/dicelang/eval/DecimalEvaluatorResult.java
new file mode 100644
index 0000000..8b37d53
--- /dev/null
+++ b/base/src/bjc/dicelang/eval/DecimalEvaluatorResult.java
@@ -0,0 +1,39 @@
+package bjc.dicelang.eval;
+
+import java.math.BigDecimal;
+import java.util.Objects;
+
+public class DecimalEvaluatorResult extends EvaluatorResult {
+ public BigDecimal val;
+
+ public DecimalEvaluatorResult(BigDecimal val) {
+ super(Type.DEC);
+
+ this.val = val;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "(" + val + ")";
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + Objects.hash(val);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ DecimalEvaluatorResult other = (DecimalEvaluatorResult) obj;
+ return Objects.equals(val, other.val);
+ }
+}
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;
diff --git a/base/src/bjc/dicelang/eval/EvaluatorResult.java b/base/src/bjc/dicelang/eval/EvaluatorResult.java
index ff86447..f721734 100644
--- a/base/src/bjc/dicelang/eval/EvaluatorResult.java
+++ b/base/src/bjc/dicelang/eval/EvaluatorResult.java
@@ -28,6 +28,10 @@ public class EvaluatorResult {
*/
INT,
/**
+ * The type of a decimal
+ */
+ DEC,
+ /**
* The type of a float.
*/
FLOAT,