Map 定义初始化表达式,添加支持 key 可以为 int、long、float、double、true、false、null 常量

This commit is contained in:
James
2017-12-10 19:40:40 +08:00
parent bd1949fc56
commit e0abc218b1
6 changed files with 117 additions and 68 deletions

View File

@@ -20,54 +20,25 @@ import com.jfinal.template.expr.Sym;
import com.jfinal.template.stat.Scope;
/**
* STR INT LONG FLOAT DOUBLE true false null
* STR INT LONG FLOAT DOUBLE TRUE FALSE NULL
*/
public class Const extends Expr {
public static final Const TRUE = new Const(Boolean.TRUE, Sym.TRUE);
public static final Const FALSE = new Const(Boolean.FALSE, Sym.FALSE);
public static final Const NULL = new Const(null, Sym.NULL);
public static final Const TRUE = new Const(Sym.TRUE, Boolean.TRUE);
public static final Const FALSE = new Const(Sym.FALSE, Boolean.FALSE);
public static final Const NULL = new Const(Sym.NULL, null);
private Sym type;
private Object value;
private final Sym type;
private final Object value;
/**
* 构造 TRUE FALSE NULL 常量,无需对 value 进行转换
* INT LONG FLOAT DOUBLE 常量已在 NumTok 中转换成了确切的类型,无需再次转换
*/
private Const(Object value, Sym type) {
public Const(Sym type, Object value) {
this.type = type;
this.value = value;
}
public Const(Sym type, String value) {
this.type = type;
this.value = typeConvert(type, value);
}
private Object typeConvert(Sym type, String value) {
switch (type) {
case STR:
return value;
case INT:
return Integer.parseInt(value);
case LONG:
return Long.parseLong(value);
case FLOAT:
return Float.parseFloat(value);
case DOUBLE:
return Double.parseDouble(value);
/*
case TRUE:
case FALSE:
return Boolean.parseBoolean(value);
case NULL:
return null;
*/
default:
throw new RuntimeException("never happend");
}
}
public Object eval(Scope scope) {
return value;
}
@@ -108,6 +79,10 @@ public class Const extends Expr {
return type == Sym.DOUBLE;
}
public boolean isNumber() {
return value instanceof Number;
}
public Object getValue() {
return value;
}
@@ -136,6 +111,10 @@ public class Const extends Expr {
return (Double)value;
}
public Number getNumber() {
return (Number)value;
}
public String toString() {
return value != null ? value.toString() : "null";
}

View File

@@ -43,8 +43,8 @@ public class Index extends Expr {
@SuppressWarnings("rawtypes")
public Object eval(Scope scope) {
Object array = expr.eval(scope);
if (array == null) {
Object target = expr.eval(scope);
if (target == null) {
if (scope.getCtrl().isNullSafe()) {
return null;
}
@@ -56,25 +56,30 @@ public class Index extends Expr {
if (scope.getCtrl().isNullSafe()) {
return null;
}
throw new TemplateException("The index of list/array and the key of map can not be null", location);
}
if (array instanceof List) {
if (idx instanceof Integer) {
return ((List<?>)array).get((Integer)idx);
if (target instanceof java.util.Map) {
// Map 的 key 可以是 null不能抛异常
} else {
throw new TemplateException("The index of list and array can not be null", location);
}
throw new TemplateException("The index of list can only be integer", location);
}
if (array instanceof java.util.Map) {
return ((java.util.Map)array).get(idx);
}
if (array.getClass().isArray()) {
if (target instanceof List) {
if (idx instanceof Integer) {
return java.lang.reflect.Array.get(array, (Integer)idx);
return ((List<?>)target).get((Integer)idx);
}
throw new TemplateException("The index of array can only be integer", location);
throw new TemplateException("The index of list must be integer", location);
}
if (target instanceof java.util.Map) {
return ((java.util.Map)target).get(idx);
}
if (target.getClass().isArray()) {
if (idx instanceof Integer) {
return java.lang.reflect.Array.get(target, (Integer)idx);
}
throw new TemplateException("The index of array must be integer", location);
}
throw new TemplateException("Only the list array and map is supported by index access", location);

View File

@@ -83,6 +83,51 @@ public class Unary extends Expr {
throw new TemplateException("Unsupported operator: " + op.value(), location);
}
}
/**
* 如果可能的话,将 Unary 表达式转化成 Const 表达式,类似于 ExprParser.buildMapEntry() 需要这种转化来简化实现
* 除了可简化程序外,还起到一定的性能优化作用
*
* Number : +123 -456 +3.14 -0.12
* Boolean : !true !false
*
* 特别注意:
* Boolean 的支持并不需要,!true、!false 已在 ExprParser 中被 Logic 表达式接管,在此仅为逻辑上的完备性而添加
*/
public Expr toConstIfPossible() {
if (expr instanceof Const && (op == Sym.SUB || op == Sym.ADD || op == Sym.NOT)) {
} else {
return this;
}
Expr ret = this;
Const c = (Const)expr;
if (op == Sym.SUB) {
if (c.isInt()) {
ret = new Const(Sym.INT, -c.getInt());
} else if (c.isLong()) {
ret = new Const(Sym.LONG, -c.getLong());
} else if (c.isFloat()) {
ret = new Const(Sym.FLOAT, -c.getFloat());
} else if (c.isDouble()) {
ret = new Const(Sym.DOUBLE, -c.getDouble());
}
} else if (op == Sym.ADD) {
if (c.isNumber()) {
ret = c;
}
} else if (op == Sym.NOT) {
if (c.isBoolean()) {
ret = c.isTrue() ? Const.FALSE : Const.TRUE;
}
}
return ret;
}
public String toString() {
return op.toString() + expr.toString();
}
}