use of jetbrick.template.parser.code.SegmentCode in project jetbrick-template-1x by subchen.
the class JetTemplateCodeVisitor method visitExpr_array_get.
@Override
public Code visitExpr_array_get(Expr_array_getContext ctx) {
SegmentCode lhs = (SegmentCode) ctx.expression(0).accept(this);
SegmentCode rhs = (SegmentCode) ctx.expression(1).accept(this);
assert_not_null_constantContext(lhs.getNode());
assert_not_null_constantContext(rhs.getNode());
boolean isSafeCall = globalSafeCall || "?".equals(ctx.getChild(1).getText());
Class<?> lhsKlass = lhs.getKlass();
if (lhsKlass.isArray()) {
if (!ClassUtils.isAssignable(Integer.TYPE, rhs.getKlass())) {
throw reportError("Type mismatch: cannot convert from " + rhs.getKlassName() + " to int.", lhs.getNode());
}
TypedKlass resultKlass = TypedKlass.create(lhsKlass.getComponentType(), lhs.getTypeArgs());
boolean boxWhenSafeCall = resultKlass.isPrimitive();
if (isSafeCall) {
resultKlass = resultKlass.asBoxedTypedKlass();
}
StringBuilder sb = new StringBuilder();
if (isSafeCall) {
sb.append('(');
sb.append(lhs.toString());
sb.append("==null?(");
sb.append(resultKlass.getSource());
sb.append(")null:");
if (boxWhenSafeCall) {
sb.append(resultKlass.getSource()).append(".valueOf(");
}
sb.append(lhs.toString());
sb.append('[');
sb.append(rhs.toString());
sb.append(']');
if (boxWhenSafeCall) {
sb.append(')');
}
sb.append(')');
} else {
sb.append(lhs.toString());
sb.append('[');
sb.append(rhs.toString());
sb.append(']');
}
return new SegmentCode(resultKlass, sb.toString(), ctx);
} else {
TypedKlass resultKlass = null;
// try to List.get(index) or Map.get(name) or JetContext.get(name)
if (List.class.isAssignableFrom(lhsKlass)) {
if (!ClassUtils.isAssignable(Integer.TYPE, rhs.getKlass())) {
throw reportError("The method get(int) in the type List is not applicable for the arguments (" + rhs.getKlassName() + ")", rhs.getNode());
}
// 取出可能的List泛型
if (lhs.getTypeArgs() != null && lhs.getTypeArgs().length == 1) {
resultKlass = lhs.getTypeArgs()[0];
}
} else if (Map.class.isAssignableFrom(lhsKlass)) {
// 取出可能的Map泛型
if (lhs.getTypeArgs() != null && lhs.getTypeArgs().length == 2) {
// value 对应的泛型
resultKlass = lhs.getTypeArgs()[1];
}
} else if (JetContext.class.isAssignableFrom(lhsKlass)) {
if (!String.class.equals(rhs.getKlass())) {
throw reportError("The method get(String) in the type JetContext is not applicable for the arguments (" + rhs.getKlassName() + ")", rhs.getNode());
}
resultKlass = TypedKlass.Object;
} else {
throw reportError("Operator [] is not applicable for the object (" + lhs.getKlassName() + ").", ctx);
}
if (resultKlass == null) {
resultKlass = TypedKlass.Object;
}
boolean boxWhenSafeCall = resultKlass.isPrimitive();
if (isSafeCall) {
resultKlass = resultKlass.asBoxedTypedKlass();
}
StringBuilder sb = new StringBuilder();
if (isSafeCall) {
sb.append('(');
sb.append(lhs.toString());
sb.append("==null?(");
sb.append(resultKlass.getSource());
sb.append(")null:");
if (boxWhenSafeCall) {
sb.append(resultKlass.getSource()).append(".valueOf(");
}
sb.append(lhs.toString());
sb.append(".get(");
sb.append(rhs.toString());
sb.append(')');
if (boxWhenSafeCall) {
sb.append(')');
}
sb.append(')');
} else {
sb.append(lhs.toString());
sb.append(".get(");
sb.append(rhs.toString());
sb.append(')');
}
return new SegmentCode(resultKlass, sb.toString(), ctx);
}
}
use of jetbrick.template.parser.code.SegmentCode in project jetbrick-template-1x by subchen.
the class JetTemplateCodeVisitor method visitExpr_compare_equality.
@Override
public Code visitExpr_compare_equality(Expr_compare_equalityContext ctx) {
SegmentCode lhs = (SegmentCode) ctx.expression(0).accept(this);
SegmentCode rhs = (SegmentCode) ctx.expression(1).accept(this);
TerminalNode op = (TerminalNode) ctx.getChild(1);
assert_not_void_expression(lhs);
assert_not_void_expression(rhs);
StringBuilder source = new StringBuilder(32);
source.append("==".equals(op.getText()) ? "JetUtils.asEquals(" : "JetUtils.asNotEquals(");
source.append(lhs.toString());
source.append(',');
source.append(rhs.toString());
source.append(')');
return new SegmentCode(Boolean.TYPE, source.toString(), ctx);
}
use of jetbrick.template.parser.code.SegmentCode in project jetbrick-template-1x by subchen.
the class JetTemplateCodeVisitor method visitExpr_math_binary_shift.
@Override
public Code visitExpr_math_binary_shift(Expr_math_binary_shiftContext ctx) {
SegmentCode lhs = (SegmentCode) ctx.expression(0).accept(this);
SegmentCode rhs = (SegmentCode) ctx.expression(1).accept(this);
// Combined '>' '>' => '>>'
String op = "";
for (int i = 1; i < ctx.getChildCount() - 1; i++) {
ParseTree node = ctx.getChild(i);
if (node instanceof TerminalNode) {
op = op + node.getText();
}
}
// 类型检查
Class<?> resultKlass = PromotionUtils.get_binary_shift(lhs.getKlass(), rhs.getKlass(), op);
if (resultKlass == null) {
throw reportError("The BinaryOperator \"" + op + "\" is not applicable for the operands " + lhs.getKlassName() + " and " + rhs.getKlassName(), ctx.getChild(1));
}
String source = "(" + lhs.toString() + op + rhs.toString() + ")";
return new SegmentCode(resultKlass, source, ctx);
}
use of jetbrick.template.parser.code.SegmentCode in project jetbrick-template-1x by subchen.
the class JetTemplateCodeVisitor method visitExpr_static_method_invocation.
@Override
public Code visitExpr_static_method_invocation(Expr_static_method_invocationContext ctx) {
SegmentCode static_type_name_code = (SegmentCode) ctx.static_type_name().accept(this);
String typeName = static_type_name_code.toString();
String name = ctx.IDENTIFIER().getText();
// 获取静态 Class
Class<?> beanClass = resolver.resolveClass(typeName);
if (beanClass == null) {
throw reportError("java.lang.ClassNotFoundException: " + typeName, static_type_name_code.getNode());
}
// 处理参数
Expression_listContext expression_list = ctx.expression_list();
SegmentListCode segmentListCode = (expression_list == null) ? SegmentListCode.EMPTY : (SegmentListCode) expression_list.accept(this);
Class<?>[] parameterTypes = segmentListCode.getParameterTypes();
Method method = resolver.resolveStaticMethod(beanClass, name, parameterTypes);
if (method == null) {
throw reportError("The static method " + getMethodSignature(name, parameterTypes) + " is undefined for the type " + beanClass.getName(), ctx.IDENTIFIER());
}
if (securityManager != null) {
securityManager.checkMemberAccess(method);
}
// 生成代码
StringBuilder sb = new StringBuilder();
sb.append(ClassUtils.getShortClassName(method.getDeclaringClass()));
sb.append('.');
sb.append(name);
sb.append('(');
sb.append(segmentListCode.toString());
sb.append(')');
TypedKlass resultKlass = TypedKlassUtils.getMethodReturnTypedKlass(method);
return new SegmentCode(resultKlass, sb.toString(), ctx);
}
use of jetbrick.template.parser.code.SegmentCode in project jetbrick-template-1x by subchen.
the class JetTemplateCodeVisitor method visitExpr_compare_relational.
@Override
public Code visitExpr_compare_relational(Expr_compare_relationalContext ctx) {
SegmentCode lhs = (SegmentCode) ctx.expression(0).accept(this);
SegmentCode rhs = (SegmentCode) ctx.expression(1).accept(this);
TerminalNode op = (TerminalNode) ctx.getChild(1);
assert_not_void_expression(lhs);
assert_not_void_expression(rhs);
assert_not_null_constantContext(lhs.getNode());
assert_not_null_constantContext(rhs.getNode());
Class<?> c1 = lhs.getKlass();
Class<?> c2 = rhs.getKlass();
// 类型校验
boolean pass = true;
if (NumberClassUtils.isNumbericClass(c1)) {
pass = NumberClassUtils.isNumbericClass(c2);
} else if (NumberClassUtils.isNumbericClass(c2)) {
pass = false;
} else {
pass = c1.isAssignableFrom(c2) || c2.isAssignableFrom(c1);
}
if (pass == false) {
throw reportError("The operator " + op.getText() + " is undefined for the argument type(s) " + lhs.getKlassName() + ", " + rhs.getKlassName(), op);
}
String suffix = "";
switch(op.getSymbol().getType()) {
case JetTemplateParser.OP_RELATIONAL_GT:
suffix = ">0";
break;
case JetTemplateParser.OP_RELATIONAL_LT:
suffix = "<0";
break;
case JetTemplateParser.OP_RELATIONAL_GE:
suffix = ">=0";
break;
case JetTemplateParser.OP_RELATIONAL_LE:
suffix = "<=0";
break;
default:
throw reportError("Unexpected operator :" + op.getText(), ctx);
}
StringBuilder source = new StringBuilder(32);
source.append("(JetUtils.asCompareWith(");
source.append(lhs.toString());
source.append(',');
source.append(rhs.toString());
source.append(')');
source.append(suffix);
source.append(')');
return new SegmentCode(Boolean.TYPE, source.toString(), ctx);
}
Aggregations