Advertisement
Guest User

Untitled

a guest
Sep 24th, 2014
1,110
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 5.88 KB | None | 0 0
  1. package edu.upol.paradise.tests.manual;
  2.  
  3.  
  4. import java.util.ArrayList;
  5. import java.util.LinkedList;
  6. import java.util.Queue;
  7.  
  8. import javassist.ClassPool;
  9. import javassist.CtClass;
  10. import javassist.CtConstructor;
  11. import javassist.CtField;
  12. import javassist.CtMethod;
  13. import javassist.CtNewConstructor;
  14. import javassist.CtNewMethod;
  15. import javassist.Modifier;
  16. import javassist.bytecode.Bytecode;
  17. import javassist.bytecode.CodeAttribute;
  18. import javassist.bytecode.ConstPool;
  19. import javassist.bytecode.InstructionPrinter;
  20. import javassist.bytecode.Opcode;
  21.  
  22.  
  23. public class Brainfuck {
  24.     private ClassPool cp = ClassPool.getDefault();
  25.     private int counter = 0;
  26.  
  27.     private class StoredJmpPoint {
  28.         public int jmpPoint;
  29.         public int bcodePoint;
  30.     }
  31.  
  32.     private String source;
  33.  
  34.     private Runnable compile() throws Throwable {
  35.         String className = "edu.upol.paradise.tests.manual.BrainFuck$" + counter++;
  36.         CtClass cls = cp.makeClass(className);
  37.         cls.addInterface(cp.getCtClass("java/lang/Runnable"));
  38.         CtField f = new CtField(CtClass.intType, "pointer", cls);
  39.         f.setModifiers(Modifier.PUBLIC);
  40.         cls.addField(f, "0");
  41.         f = new CtField(cp.get("[I"), "tape", cls);
  42.         f.setModifiers(Modifier.PUBLIC);
  43.         cls.addField(f, "new int[30000]");
  44.         CtMethod m = CtNewMethod.make("public void run(){}", cls);
  45.         ConstPool pool = m.getMethodInfo().getConstPool();
  46.        
  47.         Bytecode bc = new Bytecode(pool);
  48.        
  49.         compile(source, bc, pool, cls);
  50.        
  51.         CodeAttribute at = bc.toCodeAttribute();
  52.         at.computeMaxStack();
  53.         at.setMaxLocals(1);
  54.        
  55.         m.getMethodInfo().setCodeAttribute(at);
  56.         InstructionPrinter.print(m, System.err);
  57.        
  58.         cls.addMethod(m);
  59.         CtConstructor ct = CtNewConstructor.defaultConstructor(cls);
  60.         cls.addConstructor(ct);
  61.        
  62.         return (Runnable) cls.toClass().newInstance();
  63.     }
  64.  
  65.     private void compile(String src, Bytecode bc, ConstPool pool, CtClass cls) {
  66.         Queue<StoredJmpPoint> bq = new LinkedList<StoredJmpPoint>();
  67.        
  68.         for (char c : src.toCharArray()){
  69.             switch (c){
  70.             case '>':
  71.                 movePointerRight(bc, pool, cls);
  72.                 break;
  73.             case '<':
  74.                 movePointerLeft(bc, pool, cls);
  75.                 break;
  76.             case '+':
  77.                 addToPointed(bc, pool, cls);
  78.                 break;
  79.             case '-':
  80.                 subFromPointed(bc, pool, cls);
  81.                 break;
  82.             case '.':
  83.                 print(bc, pool, cls);
  84.                 break;
  85.             case ',':
  86.                 read(bc, pool, cls);
  87.                 break;
  88.             case '[':
  89.                 beginloop(bc, pool, cls, bq);
  90.                 break;
  91.             case ']':
  92.                 endloop(bc, pool, cls, bq);
  93.                 break;
  94.             }
  95.         }
  96.        
  97.         bc.addReturn(null);
  98.     }
  99.  
  100.     private void endloop(Bytecode bc, ConstPool pool, CtClass cls,
  101.             Queue<StoredJmpPoint> bq) {
  102.        
  103.         StoredJmpPoint jp = bq.poll();
  104.        
  105.         loadFromTape(bc, cls);
  106.         bc.addOpcode(Opcode.IFNE);
  107.         int point = bc.currentPc();
  108.         bc.add(0, 0);
  109.         bc.write16bit(bc.currentPc()-2, (jp.jmpPoint - point + 1));
  110.         point = bc.currentPc();
  111.         bc.write16bit(jp.bcodePoint, point-jp.bcodePoint+1);
  112.     }
  113.  
  114.     private void beginloop(Bytecode bc, ConstPool pool, CtClass cls,
  115.             Queue<StoredJmpPoint> bq) {
  116.        
  117.         StoredJmpPoint jp = new StoredJmpPoint();
  118.        
  119.         jp.jmpPoint = bc.currentPc();
  120.         loadFromTape(bc, cls);
  121.         bc.addOpcode(Opcode.IFEQ);
  122.         jp.bcodePoint = bc.currentPc();
  123.         bc.add(0, 0);
  124.        
  125.         bq.add(jp);
  126.     }
  127.    
  128.     private void read(Bytecode bc, ConstPool pool, CtClass cls) {
  129.         // store
  130.         bc.addAload(0);
  131.         bc.addGetfield(cls, "tape", "[I");
  132.         bc.addAload(0); // for pointer
  133.         bc.addGetfield(cls, "pointer", "I");
  134.        
  135.         bc.addGetstatic("java/lang/System", "in", "Ljava/io/InputStream;");
  136.         bc.addInvokevirtual("java/io/InputStream", "read", "()I");
  137.        
  138.         bc.addOpcode(Opcode.IASTORE);
  139.     }
  140.  
  141.     private void print(Bytecode bc, ConstPool pool, CtClass cls) {
  142.        
  143.         bc.addGetstatic("java/lang/System", "out", "Ljava/io/PrintStream;");
  144.         // load
  145.         loadFromTape(bc, cls);
  146.         // print
  147.         bc.addInvokevirtual("java/io/PrintStream", "print", "(C)V");
  148.        
  149.     }
  150.  
  151.     private void addToPointed(Bytecode bc, ConstPool pool, CtClass cls) {
  152.         // store
  153.         bc.addAload(0);
  154.         bc.addGetfield(cls, "tape", "[I");
  155.         bc.addAload(0); // for pointer
  156.         bc.addGetfield(cls, "pointer", "I");
  157.        
  158.         // load
  159.         loadFromTape(bc, cls);
  160.        
  161.         // inc
  162.         bc.addIconst(1);
  163.         bc.addOpcode(Opcode.IADD);
  164.         bc.addOpcode(Opcode.IASTORE);
  165.     }
  166.    
  167.     private void subFromPointed(Bytecode bc, ConstPool pool, CtClass cls) {
  168.         // store
  169.         bc.addAload(0);
  170.         bc.addGetfield(cls, "tape", "[I");
  171.         bc.addAload(0); // for pointer
  172.         bc.addGetfield(cls, "pointer", "I");
  173.        
  174.         // load
  175.         loadFromTape(bc, cls);
  176.        
  177.         // inc
  178.         bc.addIconst(1);
  179.         bc.addOpcode(Opcode.ISUB);
  180.         bc.addOpcode(Opcode.IASTORE);
  181.     }
  182.  
  183.  
  184.     private void loadFromTape(Bytecode bc, CtClass cls) {
  185.         bc.addAload(0);
  186.         bc.addGetfield(cls, "tape", "[I");
  187.         bc.addAload(0); // for pointer
  188.         bc.addGetfield(cls, "pointer", "I");
  189.         bc.addOpcode(Opcode.IALOAD);
  190.     }
  191.  
  192.     private void movePointerLeft(Bytecode bc, ConstPool pool, CtClass cls) {
  193.         bc.addAload(0); // for putfield
  194.         bc.addAload(0); // for pointer
  195.         bc.addGetfield(cls, "pointer", "I");
  196.         bc.addIconst(1);
  197.         bc.addOpcode(Opcode.ISUB);
  198.         bc.addIconst(0);
  199.         bc.addInvokestatic("java/lang/Math", "max", "(II)I");
  200.         bc.addPutfield(cls, "pointer", "I");
  201.     }
  202.  
  203.     private void movePointerRight(Bytecode bc, ConstPool pool, CtClass cls) {
  204.         bc.addAload(0); // for putfield
  205.         bc.addAload(0); // for pointer
  206.         bc.addGetfield(cls, "pointer", "I");
  207.         bc.addIconst(1);
  208.         bc.addOpcode(Opcode.IADD);
  209.         addTapeMax(bc, pool, cls);
  210.         bc.addInvokestatic("java/lang/Math", "min", "(II)I");
  211.         bc.addPutfield(cls, "pointer", "I");
  212.     }
  213.  
  214.     private void addTapeMax(Bytecode bc, ConstPool pool, CtClass cls) {
  215.         bc.addAload(0);
  216.         bc.addGetfield(cls, "tape", "[I");
  217.         bc.addOpcode(Opcode.ARRAYLENGTH);
  218.     }
  219.  
  220.     private void setSource(String code) {
  221.         this.source = code;
  222.     }
  223.    
  224.     public static void main(String[] arg) throws Throwable{
  225.         String code = ",>>[-]<<[->>+<<]";
  226.         Brainfuck bf = new Brainfuck();
  227.         bf.setSource(code);
  228.         Runnable r = bf.compile();
  229.         r.run();
  230.     }
  231. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement