diff options
Diffstat (limited to 'base/src/bjc/dicelang/eval/Evaluator.java')
| -rw-r--r-- | base/src/bjc/dicelang/eval/Evaluator.java | 74 |
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; |
