Java tutorial
/* * Copyright (C) 2015 Francis Galiegue <fgaliegue@gmail.com> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.github.fge.grappa.transform; import me.qmx.jitescript.VisibleAnnotation; import org.objectweb.asm.Handle; import org.objectweb.asm.Label; import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.*; import javax.annotation.Nullable; import java.io.PrintStream; import java.util.ArrayList; import java.util.List; import static me.qmx.jitescript.util.CodegenUtils.*; public final class CodeBlock implements Opcodes { private final InsnList instructionList = new InsnList(); private final List<TryCatchBlockNode> tryCatchBlockList = new ArrayList<>(); private final List<LocalVariableNode> localVariableList = new ArrayList<>(); private final List<VisibleAnnotation> annotations = new ArrayList<>(); private int arity = 0; private boolean returns = false; public CodeBlock() { } public CodeBlock(CodeBlock block) { arity = block.arity(); prepend(block); } public CodeBlock(int arity) { this.arity = arity; } public static CodeBlock newCodeBlock() { return new CodeBlock(); } public static CodeBlock newCodeBlock(int arity) { return new CodeBlock(arity); } public static CodeBlock newCodeBlock(CodeBlock block) { return new CodeBlock(block); } /** * Short-hand for specifying a set of aloads * * @param indices list of aloads you want */ public CodeBlock aloadMany(int... indices) { for (int index : indices) aload(index); return this; } public CodeBlock aload(int index) { instructionList.add(new VarInsnNode(ALOAD, index)); return this; } public CodeBlock iload(int index) { instructionList.add(new VarInsnNode(ILOAD, index)); return this; } public CodeBlock lload(int index) { instructionList.add(new VarInsnNode(LLOAD, index)); return this; } public CodeBlock fload(int index) { instructionList.add(new VarInsnNode(FLOAD, index)); return this; } public CodeBlock dload(int index) { instructionList.add(new VarInsnNode(DLOAD, index)); return this; } public CodeBlock astore(int index) { instructionList.add(new VarInsnNode(ASTORE, index)); return this; } public CodeBlock istore(int index) { instructionList.add(new VarInsnNode(ISTORE, index)); return this; } public CodeBlock lstore(int index) { instructionList.add(new VarInsnNode(LSTORE, index)); return this; } public CodeBlock fstore(int index) { instructionList.add(new VarInsnNode(FSTORE, index)); return this; } public CodeBlock dstore(int index) { instructionList.add(new VarInsnNode(DSTORE, index)); return this; } public CodeBlock ldc(Object value) { instructionList.add(new LdcInsnNode(value)); return this; } public CodeBlock bipush(int byteValue) { instructionList.add(new IntInsnNode(BIPUSH, byteValue)); return this; } public CodeBlock sipush(int shortValue) { instructionList.add(new IntInsnNode(SIPUSH, shortValue)); return this; } public CodeBlock pushInt(int value) { if (value <= Byte.MAX_VALUE && value >= Byte.MIN_VALUE) { switch (value) { case -1: iconst_m1(); break; case 0: iconst_0(); break; case 1: iconst_1(); break; case 2: iconst_2(); break; case 3: iconst_3(); break; case 4: iconst_4(); break; case 5: iconst_5(); break; default: bipush(value); break; } } else if (value <= Short.MAX_VALUE && value >= Short.MIN_VALUE) { sipush(value); } else { ldc(value); } return this; } public CodeBlock pushBoolean(boolean bool) { if (bool) iconst_1(); else iconst_0(); return this; } public CodeBlock invokestatic(String className, String methodName, String methodDesc) { instructionList.add(new MethodInsnNode(INVOKESTATIC, className, methodName, methodDesc, false)); return this; } public CodeBlock invokespecial(String className, String methodName, String methodDesc) { instructionList.add(new MethodInsnNode(INVOKESPECIAL, className, methodName, methodDesc, false)); return this; } public CodeBlock invokevirtual(String className, String methodName, String methodDesc) { instructionList.add(new MethodInsnNode(INVOKEVIRTUAL, className, methodName, methodDesc, false)); return this; } public CodeBlock invokeinterface(String className, String methodName, String methodDesc) { instructionList.add(new MethodInsnNode(INVOKEINTERFACE, className, methodName, methodDesc, true)); return this; } public CodeBlock invokedynamic(String name, String descriptor, Handle bootstrapMethod, Object... bootstrapArguments) { instructionList.add(new InvokeDynamicInsnNode(name, descriptor, bootstrapMethod, bootstrapArguments)); return this; } public CodeBlock aprintln() { dup(); getstatic(p(System.class), "out", ci(PrintStream.class)); swap(); invokevirtual(p(PrintStream.class), "println", sig(void.class, params(Object.class))); return this; } public CodeBlock iprintln() { dup(); getstatic(p(System.class), "out", ci(PrintStream.class)); swap(); invokevirtual(p(PrintStream.class), "println", sig(void.class, params(int.class))); return this; } public CodeBlock rawReturn() { returns = true; instructionList.add(new InsnNode(RETURN)); return this; } public CodeBlock areturn() { returns = true; instructionList.add(new InsnNode(ARETURN)); return this; } public CodeBlock ireturn() { instructionList.add(new InsnNode(IRETURN)); return this; } public CodeBlock freturn() { instructionList.add(new InsnNode(FRETURN)); return this; } public CodeBlock lreturn() { instructionList.add(new InsnNode(LRETURN)); return this; } public CodeBlock dreturn() { instructionList.add(new InsnNode(DRETURN)); return this; } public CodeBlock newobj(String desc) { instructionList.add(new TypeInsnNode(NEW, desc)); return this; } public CodeBlock dup() { instructionList.add(new InsnNode(DUP)); return this; } public CodeBlock swap() { instructionList.add(new InsnNode(SWAP)); return this; } public CodeBlock swap2() { dup2_x2(); pop2(); return this; } public CodeBlock getstatic(String className, String fieldName, String fieldDesc) { instructionList.add(new FieldInsnNode(GETSTATIC, className, fieldName, fieldDesc)); return this; } public CodeBlock putstatic(String className, String fieldName, String fieldDesc) { instructionList.add(new FieldInsnNode(PUTSTATIC, className, fieldName, fieldDesc)); return this; } public CodeBlock getfield(String className, String fieldName, String fieldDesc) { instructionList.add(new FieldInsnNode(GETFIELD, className, fieldName, fieldDesc)); return this; } public CodeBlock putfield(String className, String fieldName, String fieldDesc) { instructionList.add(new FieldInsnNode(PUTFIELD, className, fieldName, fieldDesc)); return this; } public CodeBlock voidreturn() { instructionList.add(new InsnNode(RETURN)); return this; } public CodeBlock anewarray(String arrayDesc) { instructionList.add(new TypeInsnNode(ANEWARRAY, arrayDesc)); return this; } public CodeBlock multianewarray(String arrayDesc, int dims) { instructionList.add(new MultiANewArrayInsnNode(arrayDesc, dims)); return this; } public CodeBlock newarray(int size) { instructionList.add(new IntInsnNode(NEWARRAY, size)); return this; } public CodeBlock iconst_m1() { instructionList.add(new InsnNode(Opcodes.ICONST_M1)); return this; } public CodeBlock iconst_0() { instructionList.add(new InsnNode(Opcodes.ICONST_0)); return this; } public CodeBlock iconst_1() { instructionList.add(new InsnNode(Opcodes.ICONST_1)); return this; } public CodeBlock iconst_2() { instructionList.add(new InsnNode(Opcodes.ICONST_2)); return this; } public CodeBlock iconst_3() { instructionList.add(new InsnNode(Opcodes.ICONST_3)); return this; } public CodeBlock iconst_4() { instructionList.add(new InsnNode(Opcodes.ICONST_4)); return this; } public CodeBlock iconst_5() { instructionList.add(new InsnNode(Opcodes.ICONST_5)); return this; } public CodeBlock lconst_0() { instructionList.add(new InsnNode(Opcodes.LCONST_0)); return this; } public CodeBlock aconst_null() { instructionList.add(new InsnNode(Opcodes.ACONST_NULL)); return this; } public CodeBlock label(LabelNode labelNode) { instructionList.add(labelNode); return this; } public CodeBlock nop() { instructionList.add(new InsnNode(Opcodes.NOP)); return this; } public CodeBlock pop() { instructionList.add(new InsnNode(POP)); return this; } public CodeBlock pop2() { instructionList.add(new InsnNode(POP2)); return this; } public CodeBlock arrayload() { instructionList.add(new InsnNode(AALOAD)); return this; } public CodeBlock arraystore() { instructionList.add(new InsnNode(AASTORE)); return this; } public CodeBlock iarrayload() { instructionList.add(new InsnNode(IALOAD)); return this; } public CodeBlock barrayload() { instructionList.add(new InsnNode(BALOAD)); return this; } public CodeBlock barraystore() { instructionList.add(new InsnNode(BASTORE)); return this; } public CodeBlock aaload() { instructionList.add(new InsnNode(AALOAD)); return this; } public CodeBlock aastore() { instructionList.add(new InsnNode(AASTORE)); return this; } public CodeBlock iaload() { instructionList.add(new InsnNode(IALOAD)); return this; } public CodeBlock iastore() { instructionList.add(new InsnNode(IASTORE)); return this; } public CodeBlock laload() { instructionList.add(new InsnNode(LALOAD)); return this; } public CodeBlock lastore() { instructionList.add(new InsnNode(LASTORE)); return this; } public CodeBlock baload() { instructionList.add(new InsnNode(BALOAD)); return this; } public CodeBlock bastore() { instructionList.add(new InsnNode(BASTORE)); return this; } public CodeBlock saload() { instructionList.add(new InsnNode(SALOAD)); return this; } public CodeBlock sastore() { instructionList.add(new InsnNode(SASTORE)); return this; } public CodeBlock caload() { instructionList.add(new InsnNode(CALOAD)); return this; } public CodeBlock castore() { instructionList.add(new InsnNode(CASTORE)); return this; } public CodeBlock faload() { instructionList.add(new InsnNode(FALOAD)); return this; } public CodeBlock fastore() { instructionList.add(new InsnNode(FASTORE)); return this; } public CodeBlock daload() { instructionList.add(new InsnNode(DALOAD)); return this; } public CodeBlock dastore() { instructionList.add(new InsnNode(DASTORE)); return this; } public CodeBlock fcmpl() { instructionList.add(new InsnNode(FCMPL)); return this; } public CodeBlock fcmpg() { instructionList.add(new InsnNode(FCMPG)); return this; } public CodeBlock dcmpl() { instructionList.add(new InsnNode(DCMPL)); return this; } public CodeBlock dcmpg() { instructionList.add(new InsnNode(DCMPG)); return this; } public CodeBlock dup_x2() { instructionList.add(new InsnNode(DUP_X2)); return this; } public CodeBlock dup_x1() { instructionList.add(new InsnNode(DUP_X1)); return this; } public CodeBlock dup2_x2() { instructionList.add(new InsnNode(DUP2_X2)); return this; } public CodeBlock dup2_x1() { instructionList.add(new InsnNode(DUP2_X1)); return this; } public CodeBlock dup2() { instructionList.add(new InsnNode(DUP2)); return this; } public CodeBlock trycatch(LabelNode scopeStart, LabelNode scopeEnd, LabelNode handler, @Nullable String exceptionType) { tryCatchBlockList.add(new TryCatchBlockNode(scopeStart, scopeEnd, handler, exceptionType)); return this; } public CodeBlock trycatch(String exceptionType, Runnable body, Runnable catchBody) { LabelNode before = new LabelNode(); LabelNode after = new LabelNode(); LabelNode catchStart = new LabelNode(); LabelNode done = new LabelNode(); trycatch(before, after, catchStart, exceptionType); label(before); body.run(); label(after); go_to(done); if (catchBody != null) { label(catchStart); catchBody.run(); } label(done); return this; } public CodeBlock go_to(LabelNode label) { instructionList.add(new JumpInsnNode(GOTO, label)); return this; } public CodeBlock lookupswitch(LabelNode defaultHandler, int[] keys, LabelNode[] handlers) { instructionList.add(new LookupSwitchInsnNode(defaultHandler, keys, handlers)); return this; } public CodeBlock athrow() { instructionList.add(new InsnNode(ATHROW)); return this; } public CodeBlock instance_of(String typeDesc) { instructionList.add(new TypeInsnNode(INSTANCEOF, typeDesc)); return this; } public CodeBlock ifeq(LabelNode jumpLabel) { instructionList.add(new JumpInsnNode(IFEQ, jumpLabel)); return this; } public CodeBlock iffalse(LabelNode jumpLabel) { ifeq(jumpLabel); return this; } public CodeBlock ifne(LabelNode jumpLabel) { instructionList.add(new JumpInsnNode(IFNE, jumpLabel)); return this; } public CodeBlock iftrue(LabelNode jumpLabel) { ifne(jumpLabel); return this; } public CodeBlock if_acmpne(LabelNode jumpLabel) { instructionList.add(new JumpInsnNode(IF_ACMPNE, jumpLabel)); return this; } public CodeBlock if_acmpeq(LabelNode jumpLabel) { instructionList.add(new JumpInsnNode(IF_ACMPEQ, jumpLabel)); return this; } public CodeBlock if_icmple(LabelNode jumpLabel) { instructionList.add(new JumpInsnNode(IF_ICMPLE, jumpLabel)); return this; } public CodeBlock if_icmpgt(LabelNode jumpLabel) { instructionList.add(new JumpInsnNode(IF_ICMPGT, jumpLabel)); return this; } public CodeBlock if_icmplt(LabelNode jumpLabel) { instructionList.add(new JumpInsnNode(IF_ICMPLT, jumpLabel)); return this; } public CodeBlock if_icmpne(LabelNode jumpLabel) { instructionList.add(new JumpInsnNode(IF_ICMPNE, jumpLabel)); return this; } public CodeBlock if_icmpeq(LabelNode jumpLabel) { instructionList.add(new JumpInsnNode(IF_ICMPEQ, jumpLabel)); return this; } public CodeBlock if_icmpge(LabelNode jumpLabel) { instructionList.add(new JumpInsnNode(IF_ICMPGE, jumpLabel)); return this; } public CodeBlock checkcast(String typeDesc) { instructionList.add(new TypeInsnNode(CHECKCAST, typeDesc)); return this; } public CodeBlock line(int line) { visitLineNumber(line, new LabelNode()); return this; } public CodeBlock line(int line, LabelNode label) { visitLineNumber(line, label); return this; } public CodeBlock ifnonnull(LabelNode jumpLabel) { instructionList.add(new JumpInsnNode(IFNONNULL, jumpLabel)); return this; } public CodeBlock ifnull(LabelNode jumpLabel) { instructionList.add(new JumpInsnNode(IFNULL, jumpLabel)); return this; } public CodeBlock iflt(LabelNode jumpLabel) { instructionList.add(new JumpInsnNode(IFLT, jumpLabel)); return this; } public CodeBlock ifle(LabelNode jumpLabel) { instructionList.add(new JumpInsnNode(IFLE, jumpLabel)); return this; } public CodeBlock ifgt(LabelNode jumpLabel) { instructionList.add(new JumpInsnNode(IFGT, jumpLabel)); return this; } public CodeBlock ifge(LabelNode jumpLabel) { instructionList.add(new JumpInsnNode(IFGE, jumpLabel)); return this; } public CodeBlock arraylength() { instructionList.add(new InsnNode(ARRAYLENGTH)); return this; } public CodeBlock ishr() { instructionList.add(new InsnNode(ISHR)); return this; } public CodeBlock ishl() { instructionList.add(new InsnNode(ISHL)); return this; } public CodeBlock iushr() { instructionList.add(new InsnNode(IUSHR)); return this; } public CodeBlock lshr() { instructionList.add(new InsnNode(LSHR)); return this; } public CodeBlock lshl() { instructionList.add(new InsnNode(LSHL)); return this; } public CodeBlock lushr() { instructionList.add(new InsnNode(LUSHR)); return this; } public CodeBlock lcmp() { instructionList.add(new InsnNode(LCMP)); return this; } public CodeBlock iand() { instructionList.add(new InsnNode(IAND)); return this; } public CodeBlock ior() { instructionList.add(new InsnNode(IOR)); return this; } public CodeBlock ixor() { instructionList.add(new InsnNode(IXOR)); return this; } public CodeBlock land() { instructionList.add(new InsnNode(LAND)); return this; } public CodeBlock lor() { instructionList.add(new InsnNode(LOR)); return this; } public CodeBlock lxor() { instructionList.add(new InsnNode(LXOR)); return this; } public CodeBlock iadd() { instructionList.add(new InsnNode(IADD)); return this; } public CodeBlock ladd() { instructionList.add(new InsnNode(LADD)); return this; } public CodeBlock fadd() { instructionList.add(new InsnNode(FADD)); return this; } public CodeBlock dadd() { instructionList.add(new InsnNode(DADD)); return this; } public CodeBlock isub() { instructionList.add(new InsnNode(ISUB)); return this; } public CodeBlock lsub() { instructionList.add(new InsnNode(LSUB)); return this; } public CodeBlock fsub() { instructionList.add(new InsnNode(FSUB)); return this; } public CodeBlock dsub() { instructionList.add(new InsnNode(DSUB)); return this; } public CodeBlock idiv() { instructionList.add(new InsnNode(IDIV)); return this; } public CodeBlock irem() { instructionList.add(new InsnNode(IREM)); return this; } public CodeBlock ineg() { instructionList.add(new InsnNode(INEG)); return this; } public CodeBlock i2d() { instructionList.add(new InsnNode(I2D)); return this; } public CodeBlock i2l() { instructionList.add(new InsnNode(I2L)); return this; } public CodeBlock i2f() { instructionList.add(new InsnNode(I2F)); return this; } public CodeBlock i2s() { instructionList.add(new InsnNode(I2S)); return this; } public CodeBlock i2c() { instructionList.add(new InsnNode(I2C)); return this; } public CodeBlock i2b() { instructionList.add(new InsnNode(I2B)); return this; } public CodeBlock ldiv() { instructionList.add(new InsnNode(LDIV)); return this; } public CodeBlock lrem() { instructionList.add(new InsnNode(LREM)); return this; } public CodeBlock lneg() { instructionList.add(new InsnNode(LNEG)); return this; } public CodeBlock l2d() { instructionList.add(new InsnNode(L2D)); return this; } public CodeBlock l2i() { instructionList.add(new InsnNode(L2I)); return this; } public CodeBlock l2f() { instructionList.add(new InsnNode(L2F)); return this; } public CodeBlock fdiv() { instructionList.add(new InsnNode(FDIV)); return this; } public CodeBlock frem() { instructionList.add(new InsnNode(FREM)); return this; } public CodeBlock fneg() { instructionList.add(new InsnNode(FNEG)); return this; } public CodeBlock f2d() { instructionList.add(new InsnNode(F2D)); return this; } public CodeBlock f2i() { instructionList.add(new InsnNode(F2D)); return this; } public CodeBlock f2l() { instructionList.add(new InsnNode(F2L)); return this; } public CodeBlock ddiv() { instructionList.add(new InsnNode(DDIV)); return this; } public CodeBlock drem() { instructionList.add(new InsnNode(DREM)); return this; } public CodeBlock dneg() { instructionList.add(new InsnNode(DNEG)); return this; } public CodeBlock d2f() { instructionList.add(new InsnNode(D2F)); return this; } public CodeBlock d2i() { instructionList.add(new InsnNode(D2I)); return this; } public CodeBlock d2l() { instructionList.add(new InsnNode(D2L)); return this; } public CodeBlock imul() { instructionList.add(new InsnNode(IMUL)); return this; } public CodeBlock lmul() { instructionList.add(new InsnNode(LMUL)); return this; } public CodeBlock fmul() { instructionList.add(new InsnNode(FMUL)); return this; } public CodeBlock dmul() { instructionList.add(new InsnNode(DMUL)); return this; } public CodeBlock iinc(int varIndex, int increment) { instructionList.add(new IincInsnNode(varIndex, increment)); return this; } public CodeBlock monitorenter() { instructionList.add(new InsnNode(MONITORENTER)); return this; } public CodeBlock monitorexit() { instructionList.add(new InsnNode(MONITOREXIT)); return this; } public CodeBlock jsr(LabelNode branch) { instructionList.add(new JumpInsnNode(JSR, branch)); return this; } public CodeBlock ret(int value) { instructionList.add(new IntInsnNode(RET, value)); return this; } public CodeBlock visitInsn(int opcode) { instructionList.add(new InsnNode(opcode)); return this; } public CodeBlock visitIntInsn(int opcode, int operand) { instructionList.add(new IntInsnNode(opcode, operand)); return this; } public CodeBlock visitInsnNode(int opcode, int operand) { instructionList.add(new IntInsnNode(opcode, operand)); return this; } public CodeBlock visitTypeInsn(int opcode, String desc) { instructionList.add(new TypeInsnNode(opcode, desc)); return this; } public CodeBlock visitFieldInsn(int opcode, String className, String fieldName, String fieldDesc) { instructionList.add(new FieldInsnNode(opcode, className, fieldName, fieldDesc)); return this; } public CodeBlock visitMethodInsn(int opcode, String className, String methodName, String methodDesc) { boolean intf = opcode == INVOKEINTERFACE; instructionList.add(new MethodInsnNode(opcode, className, methodName, methodDesc, intf)); return this; } public CodeBlock visitInvokeDynamicInsn(String name, String desc, Handle bootstrapMethod, Object... bootstrapArguments) { instructionList.add(new InvokeDynamicInsnNode(name, desc, bootstrapMethod, bootstrapArguments)); return this; } public CodeBlock visitJumpInsn(int opcode, LabelNode node) { instructionList.add(new JumpInsnNode(opcode, node)); return this; } public CodeBlock visitLabel(Label label) { instructionList.add(new LabelNode(label)); return this; } public CodeBlock visitLdcInsn(Object value) { instructionList.add(new LdcInsnNode(value)); return this; } public CodeBlock visitIincInsn(int varIndex, int increment) { instructionList.add(new IincInsnNode(varIndex, increment)); return this; } public CodeBlock visitTableSwitchInsn(int min, int max, LabelNode defaultHandler, LabelNode[] handlers) { instructionList.add(new TableSwitchInsnNode(min, max, defaultHandler, handlers)); return this; } public CodeBlock visitLookupSwitchInsn(LabelNode defaultHandler, int[] keys, LabelNode[] handlers) { instructionList.add(new LookupSwitchInsnNode(defaultHandler, keys, handlers)); return this; } public CodeBlock visitMultiANewArrayInsn(String desc, int dims) { instructionList.add(new MultiANewArrayInsnNode(desc, dims)); return this; } public CodeBlock visitTryCatchBlock(LabelNode scopeStart, LabelNode scopeEnd, LabelNode handler, @Nullable String exceptionType) { tryCatchBlockList.add(new TryCatchBlockNode(scopeStart, scopeEnd, handler, exceptionType)); return this; } public CodeBlock visitLocalVariable(String varName, String varDesc, @Nullable String signature, LabelNode scopeStart, LabelNode scopeEnd, int varIndex) { localVariableList.add(new LocalVariableNode(varName, varDesc, signature, scopeStart, scopeEnd, varIndex)); return this; } public CodeBlock visitLineNumber(int lineNumber, LabelNode start) { instructionList.add(new LineNumberNode(lineNumber, start)); return this; } public CodeBlock tableswitch(int min, int max, LabelNode defaultLabel, LabelNode[] cases) { instructionList.add(new TableSwitchInsnNode(min, max, defaultLabel, cases)); return this; } public CodeBlock visitFrame(int opcode, int nrLocals, Object[] localTypes, int nrStackElements, Object[] stackElements) { instructionList.add(new FrameNode(opcode, nrLocals, localTypes, nrStackElements, stackElements)); return this; } public InsnList getInstructionList() { return instructionList; } public List<TryCatchBlockNode> getTryCatchBlockList() { return tryCatchBlockList; } public List<LocalVariableNode> getLocalVariableList() { return localVariableList; } public List<VisibleAnnotation> getAnnotations() { return annotations; } /** * adds a compressed frame to the stack * * @param stackArguments the argument types on the stack, represented as * "class path names" e.g java/lang/RuntimeException */ public CodeBlock frame_same(Object... stackArguments) { int type; switch (stackArguments.length) { case 0: type = Opcodes.F_SAME; break; case 1: type = Opcodes.F_SAME1; break; default: throw new IllegalArgumentException("same frame should have 0" + " or 1 arguments on stack"); } instructionList.add(new FrameNode(type, 0, null, stackArguments.length, stackArguments)); return this; } public CodeBlock prepend(CodeBlock codeBlock) { if (codeBlock.returns()) returns = true; annotations.addAll(codeBlock.annotations); instructionList.insert(codeBlock.instructionList); return this; } public CodeBlock append(CodeBlock codeBlock) { if (codeBlock.returns()) returns = true; instructionList.add(codeBlock.instructionList); tryCatchBlockList.addAll(codeBlock.tryCatchBlockList); annotations.addAll(codeBlock.annotations); return this; } public VisibleAnnotation annotation(Class<?> type) { VisibleAnnotation annotation = new VisibleAnnotation(ci(type)); addAnnotation(annotation); return annotation; } public CodeBlock addAnnotation(VisibleAnnotation annotation) { annotations.add(annotation); return this; } public CodeBlock addAll(InsnList insnList) { instructionList.add(insnList); return this; } public int arity() { return arity; } public boolean returns() { return returns; } public CodeBlock clear() { instructionList.clear(); tryCatchBlockList.clear(); localVariableList.clear(); annotations.clear(); arity = 0; returns = false; return this; } }