Проверка по типам вместо instanceof

This commit is contained in:
Victor 2016-01-09 13:51:44 +02:00
parent a17bef18c5
commit 87637951a8
12 changed files with 63 additions and 20 deletions

View File

@ -42,6 +42,11 @@ public final class ArrayValue implements Value, Iterable<Value> {
this(array.elements); this(array.elements);
} }
@Override
public int type() {
return Types.ARRAY;
}
public Value get(int index) { public Value get(int index) {
return elements[index]; return elements[index];
} }

View File

@ -14,6 +14,11 @@ public final class FunctionValue implements Value {
this.value = value; this.value = value;
} }
@Override
public int type() {
return Types.FUNCTION;
}
@Override @Override
public double asNumber() { public double asNumber() {
throw new RuntimeException("Cannot cast function to number"); throw new RuntimeException("Cannot cast function to number");

View File

@ -21,6 +21,11 @@ public class MapValue implements Value, Iterable<Map.Entry<Value, Value>> {
this.map = map; this.map = map;
} }
@Override
public int type() {
return Types.MAP;
}
public Value get(Value key) { public Value get(Value key) {
return map.get(key); return map.get(key);
} }

View File

@ -19,6 +19,11 @@ public final class NumberValue implements Value {
this.value = value; this.value = value;
} }
@Override
public int type() {
return Types.NUMBER;
}
@Override @Override
public double asNumber() { public double asNumber() {
return value; return value;

View File

@ -14,6 +14,11 @@ public final class StringValue implements Value {
this.value = value; this.value = value;
} }
@Override
public int type() {
return Types.STRING;
}
@Override @Override
public double asNumber() { public double asNumber() {
try { try {

View File

@ -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;
}

View File

@ -9,4 +9,6 @@ public interface Value {
double asNumber(); double asNumber();
String asString(); String asString();
int type();
} }

View File

@ -2,6 +2,7 @@ package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.lib.ArrayValue; import com.annimon.ownlang.lib.ArrayValue;
import com.annimon.ownlang.lib.MapValue; import com.annimon.ownlang.lib.MapValue;
import com.annimon.ownlang.lib.Types;
import com.annimon.ownlang.lib.Value; import com.annimon.ownlang.lib.Value;
import com.annimon.ownlang.lib.Variables; import com.annimon.ownlang.lib.Variables;
import java.util.List; import java.util.List;
@ -23,7 +24,7 @@ public final class ArrayAccessExpression implements Expression {
@Override @Override
public Value eval() { public Value eval() {
Value container = Variables.get(variable); Value container = Variables.get(variable);
if (container instanceof ArrayValue) { if (container.type() == Types.ARRAY) {
return getArray().get(lastIndex()); return getArray().get(lastIndex());
} }
return consumeMap(container).get(indices.get(0).eval()); return consumeMap(container).get(indices.get(0).eval());
@ -47,19 +48,17 @@ public final class ArrayAccessExpression implements Expression {
} }
private ArrayValue consumeArray(Value value) { private ArrayValue consumeArray(Value value) {
if (value instanceof ArrayValue) { if (value.type() != Types.ARRAY) {
return (ArrayValue) value;
} else {
throw new RuntimeException("Array expected"); throw new RuntimeException("Array expected");
} }
return (ArrayValue) value;
} }
public MapValue consumeMap(Value value) { public MapValue consumeMap(Value value) {
if (value instanceof MapValue) { if (value.type() != Types.MAP) {
return (MapValue) value;
} else {
throw new RuntimeException("Map expected"); throw new RuntimeException("Map expected");
} }
return (MapValue) value;
} }
@Override @Override

View File

@ -1,6 +1,6 @@
package com.annimon.ownlang.parser.ast; 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.Value;
import com.annimon.ownlang.lib.Variables; import com.annimon.ownlang.lib.Variables;
@ -21,7 +21,7 @@ public final class ArrayAssignmentStatement implements Statement {
@Override @Override
public void execute() { public void execute() {
final Value container = Variables.get(array.variable); final Value container = Variables.get(array.variable);
if (container instanceof ArrayValue) { if (container.type() == Types.ARRAY) {
array.getArray().set(array.lastIndex(), expression.eval()); array.getArray().set(array.lastIndex(), expression.eval());
return; return;
} }

View File

@ -3,6 +3,7 @@ package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.lib.ArrayValue; import com.annimon.ownlang.lib.ArrayValue;
import com.annimon.ownlang.lib.NumberValue; import com.annimon.ownlang.lib.NumberValue;
import com.annimon.ownlang.lib.StringValue; import com.annimon.ownlang.lib.StringValue;
import com.annimon.ownlang.lib.Types;
import com.annimon.ownlang.lib.Value; import com.annimon.ownlang.lib.Value;
/** /**
@ -52,13 +53,15 @@ public final class BinaryExpression implements Expression {
final Value value1 = expr1.eval(); final Value value1 = expr1.eval();
final Value value2 = expr2.eval(); final Value value2 = expr2.eval();
if (value1 instanceof StringValue) { switch (value1.type()) {
return eval((StringValue) value1, value2); 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) { private Value eval(StringValue value1, Value value2) {
@ -81,7 +84,7 @@ public final class BinaryExpression implements Expression {
private Value eval(ArrayValue value1, Value value2) { private Value eval(ArrayValue value1, Value value2) {
switch (operation) { switch (operation) {
case LSHIFT: case LSHIFT:
if (!(value2 instanceof ArrayValue)) if (value2.type() != Types.ARRAY)
throw new RuntimeException("Cannot merge non array value to array"); throw new RuntimeException("Cannot merge non array value to array");
return ArrayValue.merge(value1, (ArrayValue) value2); return ArrayValue.merge(value1, (ArrayValue) value2);
case PUSH: case PUSH:

View File

@ -2,6 +2,7 @@ package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.lib.NumberValue; import com.annimon.ownlang.lib.NumberValue;
import com.annimon.ownlang.lib.StringValue; import com.annimon.ownlang.lib.StringValue;
import com.annimon.ownlang.lib.Types;
import com.annimon.ownlang.lib.Value; import com.annimon.ownlang.lib.Value;
/** /**
@ -56,7 +57,7 @@ public final class ConditionalExpression implements Expression {
final Value value2 = expr2.eval(); final Value value2 = expr2.eval();
double number1, number2; double number1, number2;
if (value1 instanceof StringValue) { if (value1.type() == Types.STRING) {
number1 = value1.asString().compareTo(value2.asString()); number1 = value1.asString().compareTo(value2.asString());
number2 = 0; number2 = 0;
} else { } else {

View File

@ -3,8 +3,7 @@ package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.lib.Function; import com.annimon.ownlang.lib.Function;
import com.annimon.ownlang.lib.FunctionValue; import com.annimon.ownlang.lib.FunctionValue;
import com.annimon.ownlang.lib.Functions; import com.annimon.ownlang.lib.Functions;
import static com.annimon.ownlang.lib.Functions.isExists; import com.annimon.ownlang.lib.Types;
import com.annimon.ownlang.lib.UserDefinedFunction;
import com.annimon.ownlang.lib.Value; import com.annimon.ownlang.lib.Value;
import com.annimon.ownlang.lib.Variables; import com.annimon.ownlang.lib.Variables;
import java.util.ArrayList; import java.util.ArrayList;
@ -47,7 +46,9 @@ public final class FunctionalExpression implements Expression {
if (Functions.isExists(key)) return Functions.get(key); if (Functions.isExists(key)) return Functions.get(key);
if (Variables.isExists(key)) { if (Variables.isExists(key)) {
final Value value = Variables.get(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); throw new RuntimeException("Unknown function " + key);
} }