!include once #1019934 // BCEL sclass MethodMaker { replace Type with org.apache.bcel.generic.Type. ClassGen cg; MethodGen mg; new InstructionList il; ConstantPoolGen cp; InstructionFactory factory; int frameSize; *(ClassMaker classMaker, Class returnType, S methodName, Class... argumentTypes) { this(classMaker.cg, returnType, methodName, argumentTypes); } *(ClassGen *cg, Class returnType, S methodName, Class... argumentTypes) { cp = cg.getConstantPool(); factory = new InstructionFactory(cg); Type[] argTypes = wrapTypes(argumentTypes); mg = new MethodGen(Const.ACC_PUBLIC, wrapType(returnType), argTypes, null /* argNames */, methodName, cg.getClassName(), il, cp); frameSize = l(argTypes)+1; // assume method is not static } Type[] wrapTypes(Class[] classes) { Type[] types = new[l(classes)]; for i over classes: types[i] = wrapType(classes[i]); ret types; } Type wrapType(Class c) { if (c == null) null; if (isPrimitiveType(c)) { if (c == byte.class) ret Type.BYTE; if (c == int.class) ret Type.INT; if (c == double.class) ret Type.DOUBLE; fail("TODO: wrapType " + c); } if (isArrayType(c)) { int dimensions = 0; while (c.isArray()) { ++dimensions; c = c.componentType(); } ret new ArrayType(wrapType(c), dimensions); } ret new ObjectType(className(c)); } // create local variable and return its index int newLocalVar() { ret frameSize++; } selfType newObject(Class c, Class... argTypes) { il.append(factory.createNew(className(c))); il.append(InstructionConst.DUP); Constructor ctor = findConstructor_precise_onTypes(c, argTypes); il.append(factory.createInvoke(className(c), "", Type.VOID, wrapTypes(ctor.getParameterTypes()), Const.INVOKESPECIAL)); this; } selfType dup() { il.append(InstructionConst.DUP); this; } // store object in local variable selfType astore(int var) { il.append(new ASTORE(var)); this; } selfType aload(int var) { il.append(new ALOAD(var)); this; } selfType stringConstant(S s) { il.append(new PUSH(cp, s)); this; } selfType classConstant(Class c) { var ldc = new LDC(classRef(c)); assertEquals("classConstant", ldc.getValue(cp), wrapType(c)); il.append(ldc); this; } selfType intConstant aka intConst(int i) { if (i >= -1 && i <= 5) ret add(new ICONST(i)); if (i == (byte) i) ret add(new BIPUSH((byte) i)); if (i == (short) i) ret add(new SIPUSH((short) i)); ret add(new LDC(cp.addInteger(i))); } selfType doubleConstant aka doubleConst(double d) { ret add(new LDC2_W(cp.addDouble(d))); } selfType invokeVirtual(Class c, Class returnType, S methodName, Class... argTypes) { Method m = findNonStaticMethod_precise_onTypes(c, methodName, argTypes); if (m == null) fail("Method not found: " + className(c) + "." + formatFunctionCall(methodName, argTypes) + " returning " + className(returnType)); il.append(factory.createInvoke(className(c), methodName, wrapType(m.getReturnType()), wrapTypes(m.getParameterTypes()), Const.INVOKEVIRTUAL)); this; } selfType invokeStatic(Class c, Class returnType, S methodName, Class... argTypes) { Method m = findMethod_precise_onTypes(c, methodName, argTypes); if (m == null) fail("Method not found: " + className(c) + "." + formatFunctionCall(methodName, argTypes) + " returning " + className(returnType)); il.append(factory.createInvoke(className(c), methodName, wrapType(m.getReturnType()), wrapTypes(m.getParameterTypes()), Const.INVOKESTATIC)); this; } selfType areturn() { il.append(InstructionConst.ARETURN); this; } selfType add(Instruction i) { il.append(i); this; } void done() { mg.stripAttributes(true); mg.setMaxStack(); mg.setMaxLocals(); cg.addMethod(mg.getMethod()); } void convertToObject(JVMStackCellType stackTop) { if (stackTop == JVMStackCellType.objValue) {} else if (stackTop == JVMStackCellType.intValue) invokeStatic(Int, Int, "valueOf", int.class); else if (stackTop == JVMStackCellType.doubleValue) invokeStatic(Double.class, Double.class, "valueOf", double.class); else if (stackTop == JVMStackCellType.none) add(new ACONST_NULL); else fail("TODO: add conversion for stack cell type: " + stackTop); } int classRef(Class c) { ret cp.addClass((ObjectType) wrapType(c)); } }