Search in sources :

Example 11 with SegmentCode

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);
    }
}
Also used : TypedKlass(jetbrick.template.parser.support.TypedKlass) SegmentCode(jetbrick.template.parser.code.SegmentCode) Map(java.util.Map) HashMap(java.util.HashMap)

Example 12 with SegmentCode

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);
}
Also used : SegmentCode(jetbrick.template.parser.code.SegmentCode) TerminalNode(org.antlr.v4.runtime.tree.TerminalNode)

Example 13 with SegmentCode

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);
}
Also used : SegmentCode(jetbrick.template.parser.code.SegmentCode) TerminalNode(org.antlr.v4.runtime.tree.TerminalNode) ParseTree(org.antlr.v4.runtime.tree.ParseTree)

Example 14 with SegmentCode

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);
}
Also used : TypedKlass(jetbrick.template.parser.support.TypedKlass) SegmentCode(jetbrick.template.parser.code.SegmentCode) Expression_listContext(jetbrick.template.parser.grammer.JetTemplateParser.Expression_listContext) Method(java.lang.reflect.Method) SegmentListCode(jetbrick.template.parser.code.SegmentListCode)

Example 15 with SegmentCode

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);
}
Also used : SegmentCode(jetbrick.template.parser.code.SegmentCode) TerminalNode(org.antlr.v4.runtime.tree.TerminalNode)

Aggregations

SegmentCode (jetbrick.template.parser.code.SegmentCode)42 SegmentListCode (jetbrick.template.parser.code.SegmentListCode)14 TypedKlass (jetbrick.template.parser.support.TypedKlass)12 BlockCode (jetbrick.template.parser.code.BlockCode)11 DefineExpressionCode (jetbrick.template.parser.code.DefineExpressionCode)9 ExpressionContext (jetbrick.template.parser.grammer.JetTemplateParser.ExpressionContext)9 MacroCode (jetbrick.template.parser.code.MacroCode)8 ForExpressionCode (jetbrick.template.parser.code.ForExpressionCode)7 TerminalNode (org.antlr.v4.runtime.tree.TerminalNode)7 Code (jetbrick.template.parser.code.Code)6 ScopeCode (jetbrick.template.parser.code.ScopeCode)6 TagCode (jetbrick.template.parser.code.TagCode)6 TemplateClassCode (jetbrick.template.parser.code.TemplateClassCode)6 TextCode (jetbrick.template.parser.code.TextCode)6 Expression_listContext (jetbrick.template.parser.grammer.JetTemplateParser.Expression_listContext)6 Method (java.lang.reflect.Method)4 HashMap (java.util.HashMap)3 Map (java.util.Map)3 Field (java.lang.reflect.Field)2 ConstantContext (jetbrick.template.parser.grammer.JetTemplateParser.ConstantContext)2