CompilerService.java 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. package in.ocsf.dialij.app.srv;/* kpmy 16.03.2017 */
  2. import co.paralleluniverse.fibers.Fiber;
  3. import co.paralleluniverse.fibers.SuspendExecution;
  4. import groovy.lang.GroovyShell;
  5. import in.ocsf.dialij.app.obj.Processor;
  6. import org.apache.log4j.Logger;
  7. import org.springframework.stereotype.Service;
  8. import java.io.StringReader;
  9. import java.lang.reflect.InvocationTargetException;
  10. import java.lang.reflect.Method;
  11. import java.lang.reflect.Proxy;
  12. import java.util.UUID;
  13. @Service
  14. public class CompilerService {
  15. public static class CompileFiber extends Fiber<Object> {
  16. private String source;
  17. @Override
  18. protected Object run() throws SuspendExecution, InterruptedException {
  19. try {
  20. BFctx ctx = new BFctx();
  21. for (int i = 0; i < source.length(); i++)
  22. ctx.parse(source.charAt(i));
  23. String code = ctx.close();
  24. GroovyShell groovyShell = new GroovyShell();
  25. return groovyShell.evaluate(new StringReader(code));
  26. } catch (Exception e) {
  27. return new RuntimeException(e);
  28. }
  29. }
  30. private CompileFiber(String source){
  31. this.source = source;
  32. }
  33. }
  34. private Logger log = Logger.getLogger(getClass());
  35. public Processor proxify(Object obj) {
  36. return (Processor) Proxy.newProxyInstance(obj.getClass().getClassLoader(),
  37. new Class[]{Processor.class},
  38. (proxy, method, args) -> {
  39. try {
  40. Method m = obj.getClass().getMethod(method.getName());
  41. return m.invoke(obj, args);
  42. } catch (InvocationTargetException e) {
  43. throw new RuntimeException(e.getTargetException());
  44. } catch (Exception e) {
  45. throw new RuntimeException(e);
  46. }
  47. });
  48. }
  49. public CompileFiber compile(String source) {
  50. return new CompileFiber(source);
  51. }
  52. private static class BFctx {
  53. private StringBuilder src = new StringBuilder();
  54. private int balance;
  55. BFctx() {
  56. src.append("package groovy.in.ocsf.dialij.script;\n");
  57. src.append("def String process(){\n");
  58. src.append("List<Integer> mem = new ArrayList<>();\n");
  59. src.append("for(int i = 0; i < 2048; i++) mem.add(0);\n");
  60. src.append("def int p = 0;\n");
  61. src.append("def int v = 0;\n");
  62. src.append("StringBuilder out = new StringBuilder();\n");
  63. }
  64. private String close() {
  65. src.append("return out.toString(); } \n");
  66. src.append("return this;");
  67. return src.toString();
  68. }
  69. private void parse(char c) {
  70. switch (c) {
  71. case '+':
  72. src.append("v = mem.get(p); v++;\n");
  73. src.append("mem.set(p, v <= 255 ? v : 0);\n");
  74. break;
  75. case '-':
  76. src.append("v = mem.get(p); v--;\n");
  77. src.append("mem.set(p, v >= 0 ? v : 255);\n");
  78. break;
  79. case '.':
  80. src.append("v = mem.get(p);\n");
  81. src.append("out.append((char) v);\n");
  82. break;
  83. case '[':
  84. src.append("v = mem.get(p);\n");
  85. src.append("while(v > 0){\n");
  86. balance++;
  87. break;
  88. case ']':
  89. src.append("v = mem.get(p);\n");
  90. src.append("}\n");
  91. if(balance >= 0)
  92. balance--;
  93. else
  94. throw new RuntimeException("unbalanced bf");
  95. break;
  96. case '>':
  97. src.append("p++;\n");
  98. src.append("if (p >= mem.size()) p = 0;\n");
  99. break;
  100. case '<':
  101. src.append("p--;\n");
  102. src.append("if (p < 0) p = mem.size() - 1;\n");
  103. break;
  104. default:
  105. }
  106. }
  107. }
  108. }