ASMSupport教程4.5 在Class中生成算术运算符

ASMSupport教程4.5 在Class中生成算术运算符

这节我们开始介绍ASMSupport如何生成算数运算符(+-*/%),依旧先看我们需要生成的java代码:

package generated.operators;

import java.io.PrintStream;
import java.util.Random;

public class ArithmeticOperatorGenerateExample
{
static void printInt(String s, int i)
{

System.out.println(s + " = " + i);

}

static void printFloat(String s, float f)
{

System.out.println(s + " = " + f);

}

public static void main(String[] args)
{

Random rand = new Random();
int j = rand.nextInt(100) + 1;
int k = rand.nextInt(100) + 1;
printInt("j", j);
printInt("k", k);
int i = j + k;
printInt("j + k", i);
i = j - k;
printInt("j - k", i);
i = k / j;
printInt("k / j", i);
i = k * j;
printInt("k * j", i);
i = k % j;
printInt("k % j", i);
j %= k;
printInt("j %= k", j);
float v = rand.nextFloat();
float w = rand.nextFloat();
printFloat("v", v);
printFloat("w", w);
float u = v + w;
printFloat("v + w", u);
u = v - w;
printFloat("v - w", u);
u = v * w;
printFloat("v * w", u);
u = v / w;
printFloat("v / w", u);
u += v;
printFloat("u += v", u);
u -= v;
printFloat("u -= v", u);
u *= v;
printFloat("u *= v", u);
u /= v;
printFloat("u /= v", u);

}
}

对应的代码如下,由于代码比较多,我们将对应的java代码写在asmsupport代码之上,便于对比。

package example.operators;

import java.util.Random;

import org.objectweb.asm.Opcodes;


import jw.asmsupport.block.method.common.StaticMethodBody;
import jw.asmsupport.clazz.AClass;
import jw.asmsupport.clazz.AClassFactory;
import jw.asmsupport.creator.ClassCreator;
import jw.asmsupport.definition.value.Value;
import jw.asmsupport.definition.variable.LocalVariable;
import jw.asmsupport.operators.method.MethodInvoker;
import jw.asmsupport.operators.numerical.arithmetic.Addition;


import example.AbstractExample;

public class ArithmeticOperatorGenerate extends AbstractExample {

    /**
     * @param args
     */
    public static void main(String[] args) {
        ClassCreator creator = new ClassCreator(Opcodes.V1_5, Opcodes.ACC_PUBLIC, "generated.operators.ArithmeticOperatorGenerateExample", null, null);

        //printIn方法
        creator.createStaticMethod("printInt", new AClass[]{AClass.STRING_ACLASS, AClass.INT_ACLASS}, new String[]{"s", "i"}, null, null, 0, new StaticMethodBody(){

            @Override
            public void generateBody(LocalVariable... argus) {
                invoke(systemOut, "println", append(argus[0], Value.value(" = "), argus[1]));
                runReturn();
            }

        });

        //printIn方法
        creator.createStaticMethod("printFloat", new AClass[]{AClass.STRING_ACLASS, AClass.FLOAT_ACLASS}, new String[]{"s", "f"}, null, null, 0, new StaticMethodBody(){

            @Override
            public void generateBody(LocalVariable... argus) {
                invoke(systemOut, "println", append(argus[0], Value.value(" = "), argus[1]));
                runReturn();
            }

        });        

        creator.createStaticMethod("main", new AClass[] { AClassFactory.getProductClass(String[].class) }, new String[] { "args" }, null, null, Opcodes.ACC_PUBLIC +

                Opcodes.ACC_STATIC, new StaticMethodBody() {

                    @Override
                    public void generateBody(LocalVariable... argus) {
                        //Random rand = new Random();
                        LocalVariable rand = createVariable("rand", AClassFactory.getProductClass(Random.class), false, invokeConstructor(AClassFactory.getProductClass(Random.class)));

                        //rand.nextInt(100) + 1
                        Addition add1 = add(invoke(rand, "nextInt", Value.value(100)), Value.value(1));

                        //int j = rand.nextInt(100) + 1;
                        LocalVariable j = createVariable("j", AClass.INT_ACLASS, false, add1);

                        //int k = rand.nextInt(100) + 1;
                        LocalVariable k = createVariable("k", AClass.INT_ACLASS, false, add1);

                        //printInt("j", j);
                        invokeStatic(getMethodOwner(), "printInt", Value.value("j"), j);

                        //printInt("k", k);
                        invokeStatic(getMethodOwner(), "printInt", Value.value("k"), k);

                        //j + k
                        Addition add2 = add(j, k);
                        //int i = j + k;
                        LocalVariable i = createVariable("i", AClass.INT_ACLASS, false, add2);

                        //printInt("j + k", i);
                        invokeStatic(getMethodOwner(), "printInt", Value.value("j + k"), i);

                        //i = j - k;
                        assign(i, sub(j, k));

                        //printInt("j - k", i);
                        invokeStatic(getMethodOwner(), "printInt", Value.value("j - k"), i);

                        //i = k / j;
                        assign(i, div(k, j));

                        //printInt("k / j", i);
                        invokeStatic(getMethodOwner(), "printInt", Value.value("k / j"), i);

                        //i = k * j;
                        assign(i, mul(k, j));

                        //printInt("k * j", i);
                        invokeStatic(getMethodOwner(), "printInt", Value.value("k * j"), i);

                        //i = k % j;
                        assign(i, mod(k, j));

                        //printInt("k % j", i);
                        invokeStatic(getMethodOwner(), "printInt", Value.value("k % j"), i);

                        //j %= k;
                        assign(j, mod(j, k));

                        //printInt("j %= k", j);
                        invokeStatic(getMethodOwner(), "printInt", Value.value("j %= k"), j);


                        //rand.nextFloat()
                        MethodInvoker nextFloat = invoke(rand, "nextFloat");

                        //v = rand.nextFloat();
                        LocalVariable v = createVariable("v", AClass.FLOAT_ACLASS, false, nextFloat);

                        //w = rand.nextFloat();
                        LocalVariable w = createVariable("w", AClass.FLOAT_ACLASS, false, nextFloat);

                        //printFloat("v", v);
                        invokeStatic(getMethodOwner(), "printFloat", Value.value("v"), v);

                        //printFloat("w", w);
                        invokeStatic(getMethodOwner(), "printFloat", Value.value("w"), w);

                        //u = v + w;
                        LocalVariable u = createVariable("u", AClass.FLOAT_ACLASS, false, add(v,w));

                        //printFloat("v + w", u);
                        invokeStatic(getMethodOwner(), "printFloat", Value.value("v + w"), u);

                        //u = v - w;
                        assign(u, sub(v, w));

                        //printFloat("v - w", u);
                        invokeStatic(getMethodOwner(), "printFloat", Value.value("v - w"), u);

                        //u = v * w;
                        assign(u, mul(v, w));

                        //printFloat("v * w", u);
                        invokeStatic(getMethodOwner(), "printFloat", Value.value("v * w"), u);

                        //u = v / w;
                        assign(u, div(v, w));

                        //printFloat("v / w", u);
                        invokeStatic(getMethodOwner(), "printFloat", Value.value("v / w"), u);

                        //u += v;
                        assign(u, add(u, v));

                        //printFloat("u += v", u);
                        invokeStatic(getMethodOwner(), "printFloat", Value.value("u += v"), u);

                        //u -= v;
                        assign(u, sub(u, v));

                        //printFloat("u -= v", u);
                        invokeStatic(getMethodOwner(), "printFloat", Value.value("u -= v"), u);

                        //u *= v;
                        assign(u, mul(u, v));

                        //printFloat("u *= v", u);
                        invokeStatic(getMethodOwner(), "printFloat", Value.value("u *= v"), u);

                        //u /= v;
                        assign(u, div(u, v));

                        //printFloat("u /= v", u);
                        invokeStatic(getMethodOwner(), "printFloat", Value.value("u /= v"), u);

                        runReturn();
                    }
                });
        generate(creator);
    }

}

这里我们不逐行解释,只对生成算术操作的方法进行解释:

  • jw.asmsupport.block.ProgramBlock.add(Parameterized factor1, Parameterized factor2) : 生成加法操作,生成的代码是factor1+factor2,返回类型jw.asmsupport.operators.numerical.arithmetic.Addition
  • jw.asmsupport.block.ProgramBlock.sub(Parameterized factor1, Parameterized factor2) : 生成减法操作,生成的代码是factor1-factor2 , 返回类型jw.asmsupport.operators.numerical.arithmetic.Subtraction
  • jw.asmsupport.block.ProgramBlock.mul(Parameterized factor1, Parameterized factor2): 生成乘法操作,生成的代码是factor1*factor2 , 返回类型jw.asmsupport.operators.numerical.arithmetic.Multiplication
  • jw.asmsupport.block.ProgramBlock.div(Parameterized factor1, Parameterized factor2):  生成除法操作,生成的代码是factor1/factor2 , 返回类型jw.asmsupport.operators.numerical.arithmetic.Division
  • jw.asmsupport.block.ProgramBlock.mod(Parameterized factor1, Parameterized factor2):生成取模操作,生成的代码是factor1%factor2 , 返回类型jw.asmsupport.operators.numerical.arithmetic.Modulus

这些方法的返回值都是继承自jw.asmsupport.Parameterized接口的,这个接口意味着这个类还可以被其他的操作所使用,这个很容易理解,我可以将a+b这个运算作为参数传入某个方法,比如有个方法是c(int a),我们可以这样调用:c(a+b)。

你可能感兴趣的:(ASMSupport教程4.5 在Class中生成算术运算符)