ASMで四則演算
なんというか、とつぜんですが、asm使って四則演算してみました。
そのうち解説を書きますが、とりあえず、ソースだけ。
javac -cp .;asm-3.1.jar A.java
java -cp .;asm-3.1.jar A 1+2*3
なかんじで試せます。
import org.objectweb.asm.ClassWriter; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; //import org.objectweb.asm.Type; //import org.objectweb.asm.Label; class A extends ClassLoader implements Opcodes { public A(ClassLoader parent) { super(parent); } public A() { super(); } int index; String str; char c; void getc() { if (index >= str.length()) c = 0; else c = str.charAt(index++); } final int INT = 256; int token; int val; void advance() { while (c == ' ' || c == '\r' || c == '\t' || c == '\n') { getc(); } if (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')') { token = c; getc(); return; } if (c >= '0' && c <= '9') { int v = 0; while(c >= '0' && c <= '9') { v = v * 10 + (c - '0'); getc(); } token = INT; val = v; return; } } int max(int m, int m2) { return m > m2 ? m : m2; } int stackm; int stackmax; void push(int n) { stackm += n; stackmax = max(stackmax, stackm); } void pop(int n) { stackm -= n; } void exp() throws Exception { term(); while(token=='+'||token=='-') { int t = token; advance(); term(); pop(1); switch(t) { case '+': mw.visitInsn(IADD); break; case '-': mw.visitInsn(ISUB); break; } } } void term() throws Exception { fact(); while(token=='*'||token=='/') { int t = token; advance(); fact(); pop(1); switch(t) { case '*': mw.visitInsn(IMUL); break; case '/': mw.visitInsn(IDIV); break; } } } void fact() throws Exception { if (token == INT) { mw.visitLdcInsn(new Integer(val)); push(1); advance(); } if (token == '(') { advance(); exp(); if (token != ')') throw new Exception("error"); advance(); } } ClassWriter cw; MethodVisitor mw; byte[] compile(String str) throws Exception { this.str = str; index = 0; stackm = stackmax = 0; getc(); advance(); cw = new ClassWriter(0); cw.visit(V1_1, ACC_PUBLIC, "a", null, "java/lang/Object", null); mw = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); mw.visitVarInsn(ALOAD, 0); mw.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V"); mw.visitInsn(RETURN); mw.visitMaxs(1, 1); mw.visitEnd(); mw = cw.visitMethod(ACC_PUBLIC, "n", "()I", null, null); exp(); mw.visitInsn(IRETURN); mw.visitMaxs(stackmax, 1); mw.visitEnd(); return cw.toByteArray(); } public static void main(String[] argv) throws Exception { A a = new A(); byte[] code = a.compile(argv[0]); Class ac = a.defineClass("a", code, 0, code.length); Object object = ac.newInstance(); System.out.println(ac.getMethod("n").invoke(object, (Object[])null)); } }