diff --git a/src/com/annimon/ownlang/lib/ArrayValue.java b/src/com/annimon/ownlang/lib/ArrayValue.java index 9c96199..427c17d 100644 --- a/src/com/annimon/ownlang/lib/ArrayValue.java +++ b/src/com/annimon/ownlang/lib/ArrayValue.java @@ -42,6 +42,11 @@ public final class ArrayValue implements Value, Iterable { this(array.elements); } + @Override + public int type() { + return Types.ARRAY; + } + public Value get(int index) { return elements[index]; } diff --git a/src/com/annimon/ownlang/lib/FunctionValue.java b/src/com/annimon/ownlang/lib/FunctionValue.java index 29c7790..ac2b49f 100644 --- a/src/com/annimon/ownlang/lib/FunctionValue.java +++ b/src/com/annimon/ownlang/lib/FunctionValue.java @@ -14,6 +14,11 @@ public final class FunctionValue implements Value { this.value = value; } + @Override + public int type() { + return Types.FUNCTION; + } + @Override public double asNumber() { throw new RuntimeException("Cannot cast function to number"); diff --git a/src/com/annimon/ownlang/lib/MapValue.java b/src/com/annimon/ownlang/lib/MapValue.java index fb54763..1c77a97 100644 --- a/src/com/annimon/ownlang/lib/MapValue.java +++ b/src/com/annimon/ownlang/lib/MapValue.java @@ -20,6 +20,11 @@ public class MapValue implements Value, Iterable> { public MapValue(Map map) { this.map = map; } + + @Override + public int type() { + return Types.MAP; + } public Value get(Value key) { return map.get(key); diff --git a/src/com/annimon/ownlang/lib/NumberValue.java b/src/com/annimon/ownlang/lib/NumberValue.java index 0c522db..5744790 100644 --- a/src/com/annimon/ownlang/lib/NumberValue.java +++ b/src/com/annimon/ownlang/lib/NumberValue.java @@ -19,6 +19,11 @@ public final class NumberValue implements Value { this.value = value; } + @Override + public int type() { + return Types.NUMBER; + } + @Override public double asNumber() { return value; diff --git a/src/com/annimon/ownlang/lib/StringValue.java b/src/com/annimon/ownlang/lib/StringValue.java index 7b75ad0..59fed48 100644 --- a/src/com/annimon/ownlang/lib/StringValue.java +++ b/src/com/annimon/ownlang/lib/StringValue.java @@ -14,6 +14,11 @@ public final class StringValue implements Value { this.value = value; } + @Override + public int type() { + return Types.STRING; + } + @Override public double asNumber() { try { diff --git a/src/com/annimon/ownlang/lib/Types.java b/src/com/annimon/ownlang/lib/Types.java new file mode 100644 index 0000000..246b1c6 --- /dev/null +++ b/src/com/annimon/ownlang/lib/Types.java @@ -0,0 +1,12 @@ +package com.annimon.ownlang.lib; + +public final class Types { + + public static final int + OBJECT = 0, + NUMBER = 1, + STRING = 2, + ARRAY = 3, + MAP = 4, + FUNCTION = 5; +} diff --git a/src/com/annimon/ownlang/lib/Value.java b/src/com/annimon/ownlang/lib/Value.java index 9e8ea09..7f09b5f 100644 --- a/src/com/annimon/ownlang/lib/Value.java +++ b/src/com/annimon/ownlang/lib/Value.java @@ -9,4 +9,6 @@ public interface Value { double asNumber(); String asString(); + + int type(); } diff --git a/src/com/annimon/ownlang/parser/ast/ArrayAccessExpression.java b/src/com/annimon/ownlang/parser/ast/ArrayAccessExpression.java index 4db62d0..45f65c4 100644 --- a/src/com/annimon/ownlang/parser/ast/ArrayAccessExpression.java +++ b/src/com/annimon/ownlang/parser/ast/ArrayAccessExpression.java @@ -2,6 +2,7 @@ package com.annimon.ownlang.parser.ast; import com.annimon.ownlang.lib.ArrayValue; import com.annimon.ownlang.lib.MapValue; +import com.annimon.ownlang.lib.Types; import com.annimon.ownlang.lib.Value; import com.annimon.ownlang.lib.Variables; import java.util.List; @@ -23,7 +24,7 @@ public final class ArrayAccessExpression implements Expression { @Override public Value eval() { Value container = Variables.get(variable); - if (container instanceof ArrayValue) { + if (container.type() == Types.ARRAY) { return getArray().get(lastIndex()); } return consumeMap(container).get(indices.get(0).eval()); @@ -47,19 +48,17 @@ public final class ArrayAccessExpression implements Expression { } private ArrayValue consumeArray(Value value) { - if (value instanceof ArrayValue) { - return (ArrayValue) value; - } else { + if (value.type() != Types.ARRAY) { throw new RuntimeException("Array expected"); } + return (ArrayValue) value; } public MapValue consumeMap(Value value) { - if (value instanceof MapValue) { - return (MapValue) value; - } else { + if (value.type() != Types.MAP) { throw new RuntimeException("Map expected"); } + return (MapValue) value; } @Override diff --git a/src/com/annimon/ownlang/parser/ast/ArrayAssignmentStatement.java b/src/com/annimon/ownlang/parser/ast/ArrayAssignmentStatement.java index 5a41a8a..b2222ac 100644 --- a/src/com/annimon/ownlang/parser/ast/ArrayAssignmentStatement.java +++ b/src/com/annimon/ownlang/parser/ast/ArrayAssignmentStatement.java @@ -1,6 +1,6 @@ package com.annimon.ownlang.parser.ast; -import com.annimon.ownlang.lib.ArrayValue; +import com.annimon.ownlang.lib.Types; import com.annimon.ownlang.lib.Value; import com.annimon.ownlang.lib.Variables; @@ -21,7 +21,7 @@ public final class ArrayAssignmentStatement implements Statement { @Override public void execute() { final Value container = Variables.get(array.variable); - if (container instanceof ArrayValue) { + if (container.type() == Types.ARRAY) { array.getArray().set(array.lastIndex(), expression.eval()); return; } diff --git a/src/com/annimon/ownlang/parser/ast/BinaryExpression.java b/src/com/annimon/ownlang/parser/ast/BinaryExpression.java index 2e5f8ea..985e6b8 100644 --- a/src/com/annimon/ownlang/parser/ast/BinaryExpression.java +++ b/src/com/annimon/ownlang/parser/ast/BinaryExpression.java @@ -3,6 +3,7 @@ package com.annimon.ownlang.parser.ast; import com.annimon.ownlang.lib.ArrayValue; import com.annimon.ownlang.lib.NumberValue; import com.annimon.ownlang.lib.StringValue; +import com.annimon.ownlang.lib.Types; import com.annimon.ownlang.lib.Value; /** @@ -52,13 +53,15 @@ public final class BinaryExpression implements Expression { final Value value1 = expr1.eval(); final Value value2 = expr2.eval(); - if (value1 instanceof StringValue) { - return eval((StringValue) value1, value2); + switch (value1.type()) { + case Types.STRING: + return eval((StringValue) value1, value2); + case Types.ARRAY: + return eval((ArrayValue) value1, value2); + case Types.NUMBER: + default: + return eval(value1, value2); } - if (value1 instanceof ArrayValue) { - return eval((ArrayValue) value1, value2); - } - return eval(value1, value2); } private Value eval(StringValue value1, Value value2) { @@ -81,7 +84,7 @@ public final class BinaryExpression implements Expression { private Value eval(ArrayValue value1, Value value2) { switch (operation) { case LSHIFT: - if (!(value2 instanceof ArrayValue)) + if (value2.type() != Types.ARRAY) throw new RuntimeException("Cannot merge non array value to array"); return ArrayValue.merge(value1, (ArrayValue) value2); case PUSH: diff --git a/src/com/annimon/ownlang/parser/ast/ConditionalExpression.java b/src/com/annimon/ownlang/parser/ast/ConditionalExpression.java index c183806..5e8610b 100644 --- a/src/com/annimon/ownlang/parser/ast/ConditionalExpression.java +++ b/src/com/annimon/ownlang/parser/ast/ConditionalExpression.java @@ -2,6 +2,7 @@ package com.annimon.ownlang.parser.ast; import com.annimon.ownlang.lib.NumberValue; import com.annimon.ownlang.lib.StringValue; +import com.annimon.ownlang.lib.Types; import com.annimon.ownlang.lib.Value; /** @@ -56,7 +57,7 @@ public final class ConditionalExpression implements Expression { final Value value2 = expr2.eval(); double number1, number2; - if (value1 instanceof StringValue) { + if (value1.type() == Types.STRING) { number1 = value1.asString().compareTo(value2.asString()); number2 = 0; } else { diff --git a/src/com/annimon/ownlang/parser/ast/FunctionalExpression.java b/src/com/annimon/ownlang/parser/ast/FunctionalExpression.java index f86681e..800a2d2 100644 --- a/src/com/annimon/ownlang/parser/ast/FunctionalExpression.java +++ b/src/com/annimon/ownlang/parser/ast/FunctionalExpression.java @@ -3,8 +3,7 @@ package com.annimon.ownlang.parser.ast; import com.annimon.ownlang.lib.Function; import com.annimon.ownlang.lib.FunctionValue; import com.annimon.ownlang.lib.Functions; -import static com.annimon.ownlang.lib.Functions.isExists; -import com.annimon.ownlang.lib.UserDefinedFunction; +import com.annimon.ownlang.lib.Types; import com.annimon.ownlang.lib.Value; import com.annimon.ownlang.lib.Variables; import java.util.ArrayList; @@ -47,7 +46,9 @@ public final class FunctionalExpression implements Expression { if (Functions.isExists(key)) return Functions.get(key); if (Variables.isExists(key)) { final Value value = Variables.get(key); - if (value instanceof FunctionValue) return ((FunctionValue)value).getValue(); + if (value.type() == Types.FUNCTION) { + return ((FunctionValue)value).getValue(); + } } throw new RuntimeException("Unknown function " + key); }