diff options
Diffstat (limited to 'dice-lang/src/bjc/dicelang/v2/Evaluator.java')
| -rw-r--r-- | dice-lang/src/bjc/dicelang/v2/Evaluator.java | 157 |
1 files changed, 132 insertions, 25 deletions
diff --git a/dice-lang/src/bjc/dicelang/v2/Evaluator.java b/dice-lang/src/bjc/dicelang/v2/Evaluator.java index d9efbea..ef50364 100644 --- a/dice-lang/src/bjc/dicelang/v2/Evaluator.java +++ b/dice-lang/src/bjc/dicelang/v2/Evaluator.java @@ -4,11 +4,14 @@ import bjc.utils.data.ITree; import bjc.utils.data.Tree; import bjc.utils.data.TopDownTransformResult; +import static bjc.dicelang.v2.Errors.ErrorKey.*; +import static bjc.dicelang.v2.Evaluator.Result.Type.*; + public class Evaluator { public static class Result { public static enum Type { FAILURE, - INT, FLOAT, DICE + INT, FLOAT, DICE, STRING } public final Type type; @@ -18,6 +21,7 @@ public class Evaluator { public long intVal; public double floatVal; public DiceBox.DieExpression diceVal; + public String stringVal; public Result(Type typ) { type = typ; @@ -41,6 +45,24 @@ public class Evaluator { diceVal = dVal; } + public Result(Type typ, DiceBox.Die dVal) { + this(typ); + + diceVal = new DiceBox.DieExpression(dVal); + } + + public Result(Type typ, DiceBox.DieList dVal) { + this(typ); + + diceVal = new DiceBox.DieExpression(dVal); + } + + public Result(Type typ, String strang) { + this(typ); + + stringVal = strang; + } + public String toString() { switch(type) { case INT: @@ -49,6 +71,8 @@ public class Evaluator { return type.toString() + "(" + floatVal + ")"; case DICE: return type.toString() + "(" + diceVal + ")"; + case STRING: + return type.toString() + "(" + stringVal + ")"; case FAILURE: return type.toString(); default: @@ -57,6 +81,8 @@ public class Evaluator { } } + private final static Node FAIL = new Node(Node.Type.RESULT, new Result(Result.Type.FAILURE)); + private DiceLangEngine eng; public Evaluator(DiceLangEngine en) { @@ -78,14 +104,16 @@ public class Evaluator { switch(ast.getHead().type) { case UNARYOP: System.out.println("\tEVALUATOR ERROR: Unary operator evaluation isn't supported yet"); - return new Tree<>(new Node(Node.Type.RESULT, new Result(Result.Type.FAILURE))); + return new Tree<>(FAIL); case BINOP: return evaluateBinaryOp(ast); case TOKREF: return evaluateTokenRef(ast.getHead().tokenVal); + case ROOT: + return ast.getChild(ast.getChildrenCount() - 1); default: - System.out.println("\tERROR: Unknown node in evaluator: " + ast.getHead().type); - return new Tree<>(new Node(Node.Type.RESULT, new Result(Result.Type.FAILURE))); + Errors.inst.printError(EK_EVAL_INVNODE, ast.getHead().type.toString()); + return new Tree<>(FAIL); } } @@ -93,8 +121,9 @@ public class Evaluator { Token.Type binOp = ast.getHead().operatorType; if(ast.getChildrenCount() != 2) { - System.out.println("\tERROR: Binary operators only take two operands"); - return new Tree<>(new Node(Node.Type.RESULT, new Result(Result.Type.FAILURE))); + Errors.inst.printError(EK_EVAL_INVBIN, Integer.toString(ast.getChildrenCount())); + + return new Tree<>(FAIL); } ITree<Node> left = ast.getChild(0); @@ -107,17 +136,85 @@ public class Evaluator { case DIVIDE: case IDIVIDE: return evaluateMathBinary(binOp, left.getHead().resultVal, right.getHead().resultVal); + case DICEGROUP: + case DICECONCAT: + case DICELIST: + return evaluateDiceBinary(binOp, left.getHead().resultVal, right.getHead().resultVal); default: - System.out.println("\tERROR: Unknown binary operator: " + binOp); - return new Tree<>(new Node(Node.Type.RESULT, new Result(Result.Type.FAILURE))); + Errors.inst.printError(EK_EVAL_UNBIN, binOp.toString()); + return new Tree<>(FAIL); } } - private ITree<Node> evaluateMathBinary(Token.Type op, Result left, Result right) { - Result.Type resultType; + private ITree<Node> evaluateDiceBinary(Token.Type op, Result left, Result right) { + Result res = null; + switch(op) { + case DICEGROUP: + if(left.type == DICE && !left.diceVal.isList) { + if(right.type == DICE && !right.diceVal.isList) { + res = new Result(DICE, new DiceBox.SimpleDie(left.diceVal.scalar, + right.diceVal.scalar)); + } else if (right.type == INT) { + res = new Result(DICE, new DiceBox.SimpleDie(left.diceVal.scalar, right.intVal)); + } else { + Errors.inst.printError(EK_EVAL_INVDGROUP, right.type.toString()); + return new Tree<>(FAIL); + } + } else if(left.type == INT) { + if(right.type == DICE && !right.diceVal.isList) { + res = new Result(DICE, new DiceBox.SimpleDie(left.intVal, right.diceVal.scalar)); + } else if (right.type == INT) { + res = new Result(DICE, new DiceBox.SimpleDie(left.intVal, right.intVal)); + } else { + Errors.inst.printError(EK_EVAL_INVDGROUP, right.type.toString()); + return new Tree<>(FAIL); + } + } else { + Errors.inst.printError(EK_EVAL_INVDGROUP, left.type.toString()); + return new Tree<>(FAIL); + } + case DICECONCAT: + if(left.type != DICE || left.diceVal.isList) { + Errors.inst.printError(EK_EVAL_INVDICE, left.type.toString()); + return new Tree<>(FAIL); + } else if(right.type != DICE || right.diceVal.isList) { + Errors.inst.printError(EK_EVAL_INVDICE, right.type.toString()); + return new Tree<>(FAIL); + } else { + res = new Result(DICE, new DiceBox.CompoundDie(left.diceVal.scalar, + right.diceVal.scalar)); + } + break; + case DICELIST: + if(left.type != DICE || left.diceVal.isList) { + Errors.inst.printError(EK_EVAL_INVDICE, left.type.toString()); + return new Tree<>(FAIL); + } else if(right.type != DICE || right.diceVal.isList) { + Errors.inst.printError(EK_EVAL_INVDICE, right.type.toString()); + return new Tree<>(FAIL); + } else { + res = new Result(DICE, new DiceBox.SimpleDieList(left.diceVal.scalar, + right.diceVal.scalar)); + } + break; + default: + Errors.inst.printError(EK_EVAL_UNDICE, op.toString()); + return new Tree<>(FAIL); + } + + return new Tree<>(new Node(Node.Type.RESULT, res)); + } + + private ITree<Node> evaluateMathBinary(Token.Type op, Result left, Result right) { if(left.type == Result.Type.DICE || right.type == Result.Type.DICE) { System.out.println("\tEVALUATOR ERROR: Math on dice isn't supported yet"); + return new Tree<>(FAIL); + } else if(left.type == Result.Type.STRING || right.type == Result.Type.STRING) { + System.out.println("\tERROR: Math operators don't work on strings"); + return new Tree<>(FAIL); + } else if(left.type == Result.Type.FAILURE || right.type == Result.Type.FAILURE) { + return new Tree<>(FAIL); } Result res = null; @@ -172,14 +269,14 @@ public class Evaluator { if(left.type == Result.Type.INT) { if(right.type == Result.Type.INT) { if(right.intVal == 0) { - System.out.println("\tERROR: Attempted divide by zero"); + Errors.inst.printError(EK_EVAL_DIVZERO); res = new Result(Result.Type.FAILURE); } else { res = new Result(Result.Type.FLOAT, left.intVal / right.intVal); } } else { if(right.floatVal == 0) { - System.out.println("\tERROR: Attempted divide by zero"); + Errors.inst.printError(EK_EVAL_DIVZERO); res = new Result(Result.Type.FAILURE); } else { res = new Result(Result.Type.FLOAT, left.intVal / right.floatVal); @@ -188,14 +285,14 @@ public class Evaluator { } else { if(right.type == Result.Type.INT) { if(right.intVal == 0) { - System.out.println("\tERROR: Attempted divide by zero"); + Errors.inst.printError(EK_EVAL_DIVZERO); res = new Result(Result.Type.FAILURE); } else { res = new Result(Result.Type.FLOAT, left.floatVal / right.intVal); } } else { if(right.floatVal == 0) { - System.out.println("\tERROR: Attempted divide by zero"); + Errors.inst.printError(EK_EVAL_DIVZERO); res = new Result(Result.Type.FAILURE); } else { res = new Result(Result.Type.FLOAT, left.floatVal / right.floatVal); @@ -207,14 +304,14 @@ public class Evaluator { if(left.type == Result.Type.INT) { if(right.type == Result.Type.INT) { if(right.intVal == 0) { - System.out.println("\tERROR: Attempted divide by zero"); + Errors.inst.printError(EK_EVAL_DIVZERO); res = new Result(Result.Type.FAILURE); } else { res = new Result(Result.Type.INT, (int) (left.intVal / right.intVal)); } } else { if(right.floatVal == 0) { - System.out.println("\tERROR: Attempted divide by zero"); + Errors.inst.printError(EK_EVAL_DIVZERO); res = new Result(Result.Type.FAILURE); } else { res = new Result(Result.Type.INT, (int) (left.intVal / right.floatVal)); @@ -223,14 +320,14 @@ public class Evaluator { } else { if(right.type == Result.Type.INT) { if(right.intVal == 0) { - System.out.println("\tERROR: Attempted divide by zero"); + Errors.inst.printError(EK_EVAL_DIVZERO); res = new Result(Result.Type.FAILURE); } else { res = new Result(Result.Type.INT, (int) (left.floatVal / right.intVal)); } } else { if(right.floatVal == 0) { - System.out.println("\tERROR: Attempted divide by zero"); + Errors.inst.printError(EK_EVAL_DIVZERO); res = new Result(Result.Type.FAILURE); } else { res = new Result(Result.Type.INT, (int) (left.floatVal / right.floatVal)); @@ -239,24 +336,34 @@ public class Evaluator { } break; default: - System.out.println("\tERROR: Unknown math binary operator: " + op); - return new Tree<>(new Node(Node.Type.RESULT, new Result(Result.Type.FAILURE))); + Errors.inst.printError(EK_EVAL_UNMATH, op.toString()); + return new Tree<>(FAIL); } return new Tree<>(new Node(Node.Type.RESULT, res)); } private ITree<Node> evaluateTokenRef(Token tk) { + Result res = null; + switch(tk.type) { case INT_LIT: - return new Tree<>(new Node(Node.Type.RESULT, new Result(Result.Type.INT, tk.intValue))); + res = new Result(Result.Type.INT, tk.intValue); + break; case FLOAT_LIT: - return new Tree<>(new Node(Node.Type.RESULT, new Result(Result.Type.FLOAT, tk.floatValue))); + res = new Result(Result.Type.FLOAT, tk.floatValue); + break; case DICE_LIT: - return new Tree<>(new Node(Node.Type.RESULT, new Result(Result.Type.DICE, tk.diceValue))); + res = new Result(Result.Type.DICE, tk.diceValue); + break; + case STRING_LIT: + res = new Result(Result.Type.STRING, eng.stringLits.get((int)(tk.intValue))); + break; default: - System.out.println("\tERROR: Unknown token ref: " + tk.type); - return new Tree<>(new Node(Node.Type.RESULT, new Result(Result.Type.FAILURE))); + Errors.inst.printError(EK_EVAL_UNTOK, tk.type.toString()); + res = new Result(Result.Type.FAILURE); } + + return new Tree<>(new Node(Node.Type.RESULT, res)); } } |
