Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package edu.upol.paradise.tests.manual;
- import java.util.ArrayList;
- import java.util.LinkedList;
- import java.util.Queue;
- import javassist.ClassPool;
- import javassist.CtClass;
- import javassist.CtConstructor;
- import javassist.CtField;
- import javassist.CtMethod;
- import javassist.CtNewConstructor;
- import javassist.CtNewMethod;
- import javassist.Modifier;
- import javassist.bytecode.Bytecode;
- import javassist.bytecode.CodeAttribute;
- import javassist.bytecode.ConstPool;
- import javassist.bytecode.InstructionPrinter;
- import javassist.bytecode.Opcode;
- public class Brainfuck {
- private ClassPool cp = ClassPool.getDefault();
- private int counter = 0;
- private class StoredJmpPoint {
- public int jmpPoint;
- public int bcodePoint;
- }
- private String source;
- private Runnable compile() throws Throwable {
- String className = "edu.upol.paradise.tests.manual.BrainFuck$" + counter++;
- CtClass cls = cp.makeClass(className);
- cls.addInterface(cp.getCtClass("java/lang/Runnable"));
- CtField f = new CtField(CtClass.intType, "pointer", cls);
- f.setModifiers(Modifier.PUBLIC);
- cls.addField(f, "0");
- f = new CtField(cp.get("[I"), "tape", cls);
- f.setModifiers(Modifier.PUBLIC);
- cls.addField(f, "new int[30000]");
- CtMethod m = CtNewMethod.make("public void run(){}", cls);
- ConstPool pool = m.getMethodInfo().getConstPool();
- Bytecode bc = new Bytecode(pool);
- compile(source, bc, pool, cls);
- CodeAttribute at = bc.toCodeAttribute();
- at.computeMaxStack();
- at.setMaxLocals(1);
- m.getMethodInfo().setCodeAttribute(at);
- InstructionPrinter.print(m, System.err);
- cls.addMethod(m);
- CtConstructor ct = CtNewConstructor.defaultConstructor(cls);
- cls.addConstructor(ct);
- return (Runnable) cls.toClass().newInstance();
- }
- private void compile(String src, Bytecode bc, ConstPool pool, CtClass cls) {
- Queue<StoredJmpPoint> bq = new LinkedList<StoredJmpPoint>();
- for (char c : src.toCharArray()){
- switch (c){
- case '>':
- movePointerRight(bc, pool, cls);
- break;
- case '<':
- movePointerLeft(bc, pool, cls);
- break;
- case '+':
- addToPointed(bc, pool, cls);
- break;
- case '-':
- subFromPointed(bc, pool, cls);
- break;
- case '.':
- print(bc, pool, cls);
- break;
- case ',':
- read(bc, pool, cls);
- break;
- case '[':
- beginloop(bc, pool, cls, bq);
- break;
- case ']':
- endloop(bc, pool, cls, bq);
- break;
- }
- }
- bc.addReturn(null);
- }
- private void endloop(Bytecode bc, ConstPool pool, CtClass cls,
- Queue<StoredJmpPoint> bq) {
- StoredJmpPoint jp = bq.poll();
- loadFromTape(bc, cls);
- bc.addOpcode(Opcode.IFNE);
- int point = bc.currentPc();
- bc.add(0, 0);
- bc.write16bit(bc.currentPc()-2, (jp.jmpPoint - point + 1));
- point = bc.currentPc();
- bc.write16bit(jp.bcodePoint, point-jp.bcodePoint+1);
- }
- private void beginloop(Bytecode bc, ConstPool pool, CtClass cls,
- Queue<StoredJmpPoint> bq) {
- StoredJmpPoint jp = new StoredJmpPoint();
- jp.jmpPoint = bc.currentPc();
- loadFromTape(bc, cls);
- bc.addOpcode(Opcode.IFEQ);
- jp.bcodePoint = bc.currentPc();
- bc.add(0, 0);
- bq.add(jp);
- }
- private void read(Bytecode bc, ConstPool pool, CtClass cls) {
- // store
- bc.addAload(0);
- bc.addGetfield(cls, "tape", "[I");
- bc.addAload(0); // for pointer
- bc.addGetfield(cls, "pointer", "I");
- bc.addGetstatic("java/lang/System", "in", "Ljava/io/InputStream;");
- bc.addInvokevirtual("java/io/InputStream", "read", "()I");
- bc.addOpcode(Opcode.IASTORE);
- }
- private void print(Bytecode bc, ConstPool pool, CtClass cls) {
- bc.addGetstatic("java/lang/System", "out", "Ljava/io/PrintStream;");
- // load
- loadFromTape(bc, cls);
- // print
- bc.addInvokevirtual("java/io/PrintStream", "print", "(C)V");
- }
- private void addToPointed(Bytecode bc, ConstPool pool, CtClass cls) {
- // store
- bc.addAload(0);
- bc.addGetfield(cls, "tape", "[I");
- bc.addAload(0); // for pointer
- bc.addGetfield(cls, "pointer", "I");
- // load
- loadFromTape(bc, cls);
- // inc
- bc.addIconst(1);
- bc.addOpcode(Opcode.IADD);
- bc.addOpcode(Opcode.IASTORE);
- }
- private void subFromPointed(Bytecode bc, ConstPool pool, CtClass cls) {
- // store
- bc.addAload(0);
- bc.addGetfield(cls, "tape", "[I");
- bc.addAload(0); // for pointer
- bc.addGetfield(cls, "pointer", "I");
- // load
- loadFromTape(bc, cls);
- // inc
- bc.addIconst(1);
- bc.addOpcode(Opcode.ISUB);
- bc.addOpcode(Opcode.IASTORE);
- }
- private void loadFromTape(Bytecode bc, CtClass cls) {
- bc.addAload(0);
- bc.addGetfield(cls, "tape", "[I");
- bc.addAload(0); // for pointer
- bc.addGetfield(cls, "pointer", "I");
- bc.addOpcode(Opcode.IALOAD);
- }
- private void movePointerLeft(Bytecode bc, ConstPool pool, CtClass cls) {
- bc.addAload(0); // for putfield
- bc.addAload(0); // for pointer
- bc.addGetfield(cls, "pointer", "I");
- bc.addIconst(1);
- bc.addOpcode(Opcode.ISUB);
- bc.addIconst(0);
- bc.addInvokestatic("java/lang/Math", "max", "(II)I");
- bc.addPutfield(cls, "pointer", "I");
- }
- private void movePointerRight(Bytecode bc, ConstPool pool, CtClass cls) {
- bc.addAload(0); // for putfield
- bc.addAload(0); // for pointer
- bc.addGetfield(cls, "pointer", "I");
- bc.addIconst(1);
- bc.addOpcode(Opcode.IADD);
- addTapeMax(bc, pool, cls);
- bc.addInvokestatic("java/lang/Math", "min", "(II)I");
- bc.addPutfield(cls, "pointer", "I");
- }
- private void addTapeMax(Bytecode bc, ConstPool pool, CtClass cls) {
- bc.addAload(0);
- bc.addGetfield(cls, "tape", "[I");
- bc.addOpcode(Opcode.ARRAYLENGTH);
- }
- private void setSource(String code) {
- this.source = code;
- }
- public static void main(String[] arg) throws Throwable{
- String code = ",>>[-]<<[->>+<<]";
- Brainfuck bf = new Brainfuck();
- bf.setSource(code);
- Runnable r = bf.compile();
- r.run();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement