summaryrefslogtreecommitdiff
path: root/dice-lang/src/bjc/dicelang/v2/Evaluator.java
diff options
context:
space:
mode:
Diffstat (limited to 'dice-lang/src/bjc/dicelang/v2/Evaluator.java')
-rw-r--r--dice-lang/src/bjc/dicelang/v2/Evaluator.java157
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));
}
}