/** * 将函数对象放入语句栈中,提供给LineFunction与BlockFunction使用。 * * @see com.ruixus.smarty4j.statement.LineFunction * @see com.ruixus.smarty4j.statement.BlockFunction * @param mv ASM方法操作者 * @param local ASM语句栈的局部变量起始位置 * @param index 函数在Template中保存的位置 */ protected String parseNode(MethodVisitorProxy mv, int local, int index) { String name = this.getClass().getName().replace('.', '/'); mv.visitVarInsn(ALOAD, TEMPLATE); mv.visitLdcInsn(index); mv.visitMethodInsn(INVOKEVIRTUAL, Template.NAME, "getNode", "(I)Ljava/lang/Object;"); mv.visitTypeInsn(CHECKCAST, name); return name; }
@Override public void parse(MethodVisitorProxy mv, int local, VariableManager vm) { for (LoopFunction block : blocks) { block.restore(mv, vm); } mv.visitJumpInsn(GOTO, lblContinue); }
/** * 参数代码转换,根据节点的信息将参数转换成数组放入JVM语句栈中。 * * @param mv ASM方法访问对象 * @param local ASM方法内部的语句栈局部变量起始位置 * @param vm 变量管理器 */ public void parseAllParameters(MethodVisitorProxy mv, int local, VariableManager vm) { int len = PARAMETERS != null ? PARAMETERS.length : 0; if (allDesc.get(this.getClass().getName()) != null) { if (len > 0) { for (int i = 0; i < len; i++) { if (PARAMETERS[i] == null) { mv.visitLdcInsn(null); } else { PARAMETERS[i].parse(mv, local, vm); } } } } else { if (len == 0) { // 没有参数 mv.visitLdcInsn(null); } else { mv.visitLdcInsn(PARAMETERS.length); mv.visitTypeInsn(ANEWARRAY, "java/lang/Object"); for (int i = 0; i < len; i++) { if (PARAMETERS[i] == null) { continue; } mv.visitInsn(DUP); mv.visitLdcInsn(i); PARAMETERS[i].parseObject(mv, local, vm); mv.visitInsn(AASTORE); } } } }
@Override public void parseSelf(MethodVisitorProxy mv, int local, VariableManager vm) { mv.visitTypeInsn(NEW, "java/util/HashMap"); mv.visitInsn(DUP); mv.visitMethodInsn(INVOKESPECIAL, "java/util/HashMap", "<init>", "()V"); for (Map.Entry<String, Expression> entry : value.entrySet()) { mv.visitInsn(DUP); mv.visitLdcInsn(entry.getKey()); entry.getValue().parseObject(mv, local, vm); mv.visitMethodInsn( INVOKEVIRTUAL, "java/util/HashMap", "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); mv.visitInsn(POP); } }