Search in sources :

Example 1 with TypedKlass

use of jetbrick.template.parser.support.TypedKlass in project jetbrick-template-1x by subchen.

the class JetTemplateCodeVisitor method visitSet_expression.

@Override
public Code visitSet_expression(Set_expressionContext ctx) {
    String name = assert_java_identifier(ctx.IDENTIFIER(), true);
    SegmentCode code = (SegmentCode) ctx.expression().accept(this);
    // 是否同时定义一个变量
    boolean defining = false;
    // 变量类型
    TypedKlass lhs = null;
    TypeContext type = ctx.type();
    if (type != null) {
        defining = true;
        // 定义一个变量
        SegmentCode c = (SegmentCode) type.accept(this);
        lhs = c.getTypedKlass();
        if (!scopeCode.define(name, lhs)) {
            throw reportError("Duplicate local variable " + name, ctx.IDENTIFIER());
        }
    } else {
        // 直接赋值,如果变量没有定义,则先定义
        lhs = scopeCode.resolve(name, false);
        defining = (lhs == null);
        if (defining) {
            lhs = code.getTypedKlass();
            scopeCode.define(name, lhs);
        }
    }
    // 进行赋值语句类型检查
    if (!ClassUtils.isAssignable(lhs.getKlass(), code.getKlass())) {
        // 是否支持正常赋值
        if (!ClassUtils.isAssignable(code.getKlass(), lhs.getKlass())) {
            // 是否支持强制类型转换
            throw reportError("Type mismatch: cannot convert from " + code.getTypedKlass().toString() + " to " + lhs.toString(), ctx);
        }
    }
    BlockCode c = scopeCode.createBlockCode(2);
    String source = name + " = (" + lhs.getSource() + ") " + code.toString() + "; // line: " + ctx.getStart().getLine();
    if (defining) {
        source = lhs.getSource() + " " + source;
    }
    c.addLine(source);
    c.addLine(Code.CONTEXT_NAME + ".put(\"" + name + "\", " + name + ");");
    return c;
}
Also used : BlockCode(jetbrick.template.parser.code.BlockCode) TypedKlass(jetbrick.template.parser.support.TypedKlass) SegmentCode(jetbrick.template.parser.code.SegmentCode) TypeContext(jetbrick.template.parser.grammer.JetTemplateParser.TypeContext)

Example 2 with TypedKlass

use of jetbrick.template.parser.support.TypedKlass in project jetbrick-template-1x by subchen.

the class JetTemplateCodeVisitor method visitExpr_new_array.

@Override
public Code visitExpr_new_array(Expr_new_arrayContext ctx) {
    SegmentCode code = (SegmentCode) ctx.type().accept(this);
    if (code.getKlass().isArray()) {
        throw reportError("Cannot specify an array dimension after an empty dimension", ctx.type());
    }
    StringBuilder typeSource = new StringBuilder(code.toString());
    // 生成代码
    StringBuilder source = new StringBuilder(32);
    source.append("(new ").append(code.toString());
    for (ExpressionContext expression : ctx.expression()) {
        SegmentCode c = (SegmentCode) expression.accept(this);
        if (!ClassUtils.isAssignable(Integer.TYPE, c.getKlass())) {
            throw reportError("Type mismatch: cannot convert from " + c.getKlassName() + " to int.", expression);
        }
        source.append('[').append(c.toString()).append(']');
        typeSource.append("[]");
    }
    source.append(')');
    TypedKlass resultKlass = resolver.resolveTypedKlass(typeSource.toString());
    return new SegmentCode(resultKlass, source.toString(), ctx);
}
Also used : TypedKlass(jetbrick.template.parser.support.TypedKlass) SegmentCode(jetbrick.template.parser.code.SegmentCode) ExpressionContext(jetbrick.template.parser.grammer.JetTemplateParser.ExpressionContext)

Example 3 with TypedKlass

use of jetbrick.template.parser.support.TypedKlass 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 4 with TypedKlass

use of jetbrick.template.parser.support.TypedKlass 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 5 with TypedKlass

use of jetbrick.template.parser.support.TypedKlass in project jetbrick-template-1x by subchen.

the class JetTemplateCodeVisitor method visitType.

@Override
public Code visitType(TypeContext ctx) {
    StringBuilder name = new StringBuilder();
    for (TerminalNode node : ctx.IDENTIFIER()) {
        if (name.length() > 0) {
            name.append('.');
        }
        name.append(node.getText());
    }
    // 查找 klass
    Class<?> klass = resolver.resolveClass(name.toString());
    if (klass == null) {
        StringBuilder sb = new StringBuilder(128);
        sb.append("java.lang.ClassNotFoundException: ").append(name);
        sb.append("\n advise: Please define package in 'import.packages' or use full qualified class name.");
        throw reportError(sb.toString(), ctx);
    }
    if (securityManager != null) {
        securityManager.checkMemberAccess(klass);
    }
    // 查找泛型类型 typeArgs
    TypedKlass[] typeArgs = TypedKlass.EMPTY_TYPE_ARGS;
    Type_argumentsContext type_arguments = ctx.type_arguments();
    if (type_arguments != null) {
        SegmentListCode c = (SegmentListCode) type_arguments.accept(this);
        typeArgs = new TypedKlass[c.size()];
        for (int i = 0; i < typeArgs.length; i++) {
            typeArgs[i] = c.getChild(i).getTypedKlass();
        }
    }
    // 如果是数组类型,则把 klass 转成数组
    String array_suffix = "";
    List<Type_array_suffixContext> type_array_suffix = ctx.type_array_suffix();
    for (Type_array_suffixContext c : type_array_suffix) {
        Code code = c.accept(this);
        array_suffix = array_suffix + code.toString();
    }
    if (array_suffix.length() > 0) {
        // 转换成 Array Class, 重新 resolve
        String klassName = name.toString() + array_suffix;
        klass = resolver.resolveClass(klassName);
        if (klass == null) {
            throw reportError("java.lang.ClassNotFoundException: " + klassName, ctx);
        }
    }
    // 返回带有的泛型信息的 Class
    TypedKlass typedKlass = TypedKlass.create(klass, typeArgs);
    return new SegmentCode(typedKlass, typedKlass.toString(), ctx);
}
Also used : SegmentListCode(jetbrick.template.parser.code.SegmentListCode) ScopeCode(jetbrick.template.parser.code.ScopeCode) BlockCode(jetbrick.template.parser.code.BlockCode) SegmentListCode(jetbrick.template.parser.code.SegmentListCode) TemplateClassCode(jetbrick.template.parser.code.TemplateClassCode) TextCode(jetbrick.template.parser.code.TextCode) ForExpressionCode(jetbrick.template.parser.code.ForExpressionCode) SegmentCode(jetbrick.template.parser.code.SegmentCode) MacroCode(jetbrick.template.parser.code.MacroCode) Code(jetbrick.template.parser.code.Code) DefineExpressionCode(jetbrick.template.parser.code.DefineExpressionCode) TagCode(jetbrick.template.parser.code.TagCode) Type_argumentsContext(jetbrick.template.parser.grammer.JetTemplateParser.Type_argumentsContext) TypedKlass(jetbrick.template.parser.support.TypedKlass) SegmentCode(jetbrick.template.parser.code.SegmentCode) TerminalNode(org.antlr.v4.runtime.tree.TerminalNode) Type_array_suffixContext(jetbrick.template.parser.grammer.JetTemplateParser.Type_array_suffixContext)

Aggregations

TypedKlass (jetbrick.template.parser.support.TypedKlass)13 SegmentCode (jetbrick.template.parser.code.SegmentCode)12 Method (java.lang.reflect.Method)4 SegmentListCode (jetbrick.template.parser.code.SegmentListCode)4 HashMap (java.util.HashMap)3 Map (java.util.Map)3 Expression_listContext (jetbrick.template.parser.grammer.JetTemplateParser.Expression_listContext)3 Field (java.lang.reflect.Field)2 BlockCode (jetbrick.template.parser.code.BlockCode)2 ForExpressionCode (jetbrick.template.parser.code.ForExpressionCode)2 MacroCode (jetbrick.template.parser.code.MacroCode)2 Expr_identifierContext (jetbrick.template.parser.grammer.JetTemplateParser.Expr_identifierContext)2 TypeContext (jetbrick.template.parser.grammer.JetTemplateParser.TypeContext)2 Member (java.lang.reflect.Member)1 Code (jetbrick.template.parser.code.Code)1 DefineExpressionCode (jetbrick.template.parser.code.DefineExpressionCode)1 ScopeCode (jetbrick.template.parser.code.ScopeCode)1 TagCode (jetbrick.template.parser.code.TagCode)1 TemplateClassCode (jetbrick.template.parser.code.TemplateClassCode)1 TextCode (jetbrick.template.parser.code.TextCode)1