package me.august.lumen.codegen;
import me.august.lumen.Util;
import me.august.lumen.common.BytecodeUtil;
import me.august.lumen.compile.parser.ast.expr.Expression;
import org.junit.Assert;
import org.junit.Test;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import java.util.ArrayList;
import java.util.List;
public class CodeGenerationTest {
@Test
public void testAdditive() {
Expression expr;
MethodVisitorRecorder method = new MethodVisitorRecorder();
expr = Util.parseExpression("2 + 2");
expr.generate(method, null);
Assert.assertArrayEquals(
new String[]{"ICONST_2", "ICONST_2", "IADD"},
method.events()
);
expr = Util.parseExpression("100 + 2000");
method.clear();
expr.generate(method, null);
Assert.assertArrayEquals(
new String[]{"BIPUSH 100", "SIPUSH 2000", "IADD"},
method.events()
);
expr = Util.parseExpression("10000000 - 20000000");
method.clear();
expr.generate(method, null);
Assert.assertArrayEquals(
new String[]{"LDC 10000000", "LDC 20000000", "ISUB"},
method.events()
);
}
@Test
public void testMultiplicative() {
Expression expr;
MethodVisitorRecorder method = new MethodVisitorRecorder();
expr = Util.parseExpression("2 * 2");
expr.generate(method, null);
Assert.assertArrayEquals(
new String[]{"ICONST_2", "ICONST_2", "IMUL"},
method.events()
);
expr = Util.parseExpression("100 / 200");
method.clear();
expr.generate(method, null);
Assert.assertArrayEquals(
new String[]{"BIPUSH 100", "SIPUSH 200", "IDIV"},
method.events()
);
expr = Util.parseExpression("10000000 % 20000000");
method.clear();
expr.generate(method, null);
Assert.assertArrayEquals(
new String[]{"LDC 10000000", "LDC 20000000", "IREM"},
method.events()
);
}
private static class MethodVisitorRecorder extends MethodVisitor {
private List<String> events = new ArrayList<>();
public String[] events() {
return events.toArray(new String[events.size()]);
}
public MethodVisitorRecorder() {
super(Opcodes.ASM5);
}
@Override
public void visitInsn(int i) {
events.add(BytecodeUtil.toOpcodeName(i));
}
@Override
public void visitLdcInsn(Object o) {
events.add("LDC " + o);
}
@Override
public void visitIntInsn(int i, int val) {
String opcode = BytecodeUtil.toOpcodeName(i);
events.add(opcode + " " + val);
}
public void clear() {
events.clear();
}
}
}