diff options
| author | student <student@localhost> | 2018-04-04 16:26:53 -0400 |
|---|---|---|
| committer | student <student@localhost> | 2018-04-04 16:26:53 -0400 |
| commit | 43524b0742f195304829e5bd4dd12492f8ad1aa1 (patch) | |
| tree | 8b0a82ce08c8636be9bad88786bc087347ddc1a6 /base/src | |
| parent | 9f492d118835acab63dab02bd601475e4127dd28 (diff) | |
More Evaluator work
Diffstat (limited to 'base/src')
| -rw-r--r-- | base/src/bjc/dicelang/eval/Evaluator.java | 218 | ||||
| -rw-r--r-- | base/src/bjc/dicelang/eval/EvaluatorResult.java | 39 | ||||
| -rw-r--r-- | base/src/bjc/dicelang/eval/IntegerEvaluatorResult.java | 38 |
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 + "]"; + } +} |
