Advertisement
Guest User

Untitled

a guest
Nov 22nd, 2016
45
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 20.33 KB | None | 0 0
  1. package com.skiwi.bfcompiler.generators;
  2.  
  3. import com.skiwi.bfcompiler.ast.AST;
  4. import com.skiwi.bfcompiler.ast.ASTNode;
  5. import com.skiwi.bfcompiler.expression.Expression;
  6. import com.skiwi.bfcompiler.expression.IntegerExpression;
  7. import com.skiwi.bfcompiler.expression.RootExpression;
  8. import com.skiwi.bfcompiler.expression.StringExpression;
  9. import com.skiwi.bfcompiler.expression.intermediate.MemoryInputExpression;
  10. import com.skiwi.bfcompiler.expression.intermediate.MemoryLoopExpression;
  11. import com.skiwi.bfcompiler.expression.intermediate.MemoryOutputExpression;
  12. import com.skiwi.bfcompiler.expression.intermediate.MemoryPointerChangeExpression;
  13. import com.skiwi.bfcompiler.expression.intermediate.MemoryValueChangeExpression;
  14. import com.skiwi.bfcompiler.expression.target.AddExpression;
  15. import com.skiwi.bfcompiler.expression.target.BssSectionExpression;
  16. import com.skiwi.bfcompiler.expression.target.CallExpression;
  17. import com.skiwi.bfcompiler.expression.target.DataSectionExpression;
  18. import com.skiwi.bfcompiler.expression.target.DefineByteExpression;
  19. import com.skiwi.bfcompiler.expression.target.DefineLabelExpression;
  20. import com.skiwi.bfcompiler.expression.target.DwordExpression;
  21. import com.skiwi.bfcompiler.expression.target.ExternExpression;
  22. import com.skiwi.bfcompiler.expression.target.FunctionExpression;
  23. import com.skiwi.bfcompiler.expression.target.GlobalExpression;
  24. import com.skiwi.bfcompiler.expression.target.IdentifierExpression;
  25. import com.skiwi.bfcompiler.expression.target.JmpExpression;
  26. import com.skiwi.bfcompiler.expression.target.JnzExpression;
  27. import com.skiwi.bfcompiler.expression.target.JzExpression;
  28. import com.skiwi.bfcompiler.expression.target.LabelExpression;
  29. import com.skiwi.bfcompiler.expression.target.MemoryAddressExpression;
  30. import com.skiwi.bfcompiler.expression.target.MovExpression;
  31. import com.skiwi.bfcompiler.expression.target.OperandExpression;
  32. import com.skiwi.bfcompiler.expression.target.PushExpression;
  33. import com.skiwi.bfcompiler.expression.target.Register;
  34. import com.skiwi.bfcompiler.expression.target.RegisterExpression;
  35. import com.skiwi.bfcompiler.expression.target.ReserveDoubleExpression;
  36. import com.skiwi.bfcompiler.expression.target.JmpShortExpression;
  37. import com.skiwi.bfcompiler.expression.target.RetExpression;
  38. import com.skiwi.bfcompiler.expression.target.TestExpression;
  39. import com.skiwi.bfcompiler.expression.target.TextSectionExpression;
  40. import com.skiwi.bfcompiler.expression.target.ValueExpression;
  41. import com.skiwi.bfcompiler.expression.target.ValueListExpression;
  42. import com.skiwi.bfcompiler.options.BFOptions;
  43.  
  44. import java.util.Arrays;
  45. import java.util.stream.IntStream;
  46. import java.util.stream.Stream;
  47.  
  48. /**
  49.  * @author Frank van Heeswijk
  50.  */
  51. public class TargetCodeGenerator {
  52.     private final BFOptions bfOptions;
  53.  
  54.     public TargetCodeGenerator(final BFOptions bfOptions) {
  55.         this.bfOptions = bfOptions;
  56.     }
  57.  
  58.     public AST generateAST(final AST intermediateAST) {
  59.         int stderr = 2;
  60.         int bfMemoryCellAmount = bfOptions.getMemoryCellAmount();
  61.  
  62.         ASTNode rootNode = new ASTNode(new RootExpression());
  63.         AST ast = new AST(rootNode);
  64.  
  65.         // Header of the BF.exe program -do not modify-
  66.         ASTNode externNode = new ASTNode(new ExternExpression());
  67.         externNode.addChild(ASTNode.newWithChild(new FunctionExpression(), new ASTNode(new StringExpression("_calloc"))));
  68.         externNode.addChild(ASTNode.newWithChild(new FunctionExpression(), new ASTNode(new StringExpression("_fdopen"))));
  69.         externNode.addChild(ASTNode.newWithChild(new FunctionExpression(), new ASTNode(new StringExpression("_fprintf"))));
  70.         externNode.addChild(ASTNode.newWithChild(new FunctionExpression(), new ASTNode(new StringExpression("_getchar"))));
  71.         externNode.addChild(ASTNode.newWithChild(new FunctionExpression(), new ASTNode(new StringExpression("_putchar"))));
  72.         rootNode.addChild(externNode);
  73.  
  74.         ASTNode dataSectionNode = new ASTNode(new DataSectionExpression());
  75.         dataSectionNode.addChild(ASTNode.newWithChildren(new DefineByteExpression(), Arrays.asList(
  76.             ASTNode.newWithChild(new IdentifierExpression(), new ASTNode(new StringExpression("write_mode"))),
  77.             ASTNode.newWithChild(new ValueExpression(), ASTNode.newWithChildren(new ValueListExpression(), Arrays.asList(
  78.                 new ASTNode(new StringExpression("w")),
  79.                 new ASTNode(new IntegerExpression(0))
  80.             )))
  81.         )));
  82.         dataSectionNode.addChild(ASTNode.newWithChildren(new DefineByteExpression(), Arrays.asList(
  83.             ASTNode.newWithChild(new IdentifierExpression(), new ASTNode(new StringExpression("error_outofmemory"))),
  84.             ASTNode.newWithChild(new ValueExpression(), ASTNode.newWithChildren(new ValueListExpression(), Arrays.asList(
  85.                 new ASTNode(new StringExpression("Fatal: The Operating System does not have enough memory available.")),
  86.                 new ASTNode(new IntegerExpression(0))
  87.             )))
  88.         )));
  89.         rootNode.addChild(dataSectionNode);
  90.  
  91.         ASTNode bssSectionNode = new ASTNode(new BssSectionExpression());
  92.         bssSectionNode.addChild(ASTNode.newWithChildren(new ReserveDoubleExpression(), Arrays.asList(
  93.             ASTNode.newWithChild(new IdentifierExpression(), new ASTNode(new StringExpression("bf_memory"))),
  94.             ASTNode.newWithChild(new ValueExpression(), new ASTNode(new IntegerExpression(1)))
  95.         )));
  96.         rootNode.addChild(bssSectionNode);
  97.  
  98.         ASTNode textSectionNode = new ASTNode(new TextSectionExpression());
  99.         textSectionNode.addChild(ASTNode.newWithChild(new GlobalExpression(),
  100.             ASTNode.newWithChild(new LabelExpression(), new ASTNode(new StringExpression("_main")))));
  101.         textSectionNode.addChild(ASTNode.newWithChild(new DefineLabelExpression(),
  102.             ASTNode.newWithChild(new LabelExpression(), new ASTNode(new StringExpression("_main")))));
  103.         textSectionNode.addChild(ASTNode.newWithChildren(new MovExpression(), Arrays.asList(
  104.             ASTNode.newWithChild(new OperandExpression(), new ASTNode(new RegisterExpression(Register.EBP))),
  105.             ASTNode.newWithChild(new OperandExpression(), new ASTNode(new RegisterExpression(Register.ESP)))
  106.         )));
  107.         textSectionNode.addChild(ASTNode.newWithChild(new PushExpression(),
  108.             ASTNode.newWithChild(new OperandExpression(),
  109.                 ASTNode.newWithChild(new DwordExpression(), new ASTNode(new IntegerExpression(1))))));
  110.         textSectionNode.addChild(ASTNode.newWithChild(new PushExpression(),
  111.             ASTNode.newWithChild(new OperandExpression(),
  112.                 ASTNode.newWithChild(new DwordExpression(), new ASTNode(new IntegerExpression(bfMemoryCellAmount))))));
  113.         textSectionNode.addChild(ASTNode.newWithChild(new CallExpression(),
  114.             ASTNode.newWithChild(new OperandExpression(),
  115.                 ASTNode.newWithChild(new FunctionExpression(), new ASTNode(new StringExpression("_calloc"))))));
  116.         textSectionNode.addChild(ASTNode.newWithChildren(new AddExpression(), Arrays.asList(
  117.             ASTNode.newWithChild(new OperandExpression(), new ASTNode(new RegisterExpression(Register.ESP))),
  118.             ASTNode.newWithChild(new OperandExpression(), new ASTNode(new IntegerExpression(8)))
  119.         )));
  120.         textSectionNode.addChild(ASTNode.newWithChildren(new TestExpression(), Arrays.asList(
  121.             ASTNode.newWithChild(new OperandExpression(), new ASTNode(new RegisterExpression(Register.EAX))),
  122.             ASTNode.newWithChild(new OperandExpression(), new ASTNode(new RegisterExpression(Register.EAX)))
  123.         )));
  124.         textSectionNode.addChild(ASTNode.newWithChild(new JzExpression(),
  125.             ASTNode.newWithChild(new OperandExpression(),
  126.                 ASTNode.newWithChild(new LabelExpression(), new ASTNode(new StringExpression("error_exit_outofmemory"))))));
  127.         textSectionNode.addChild(ASTNode.newWithChildren(new MovExpression(), Arrays.asList(
  128.             ASTNode.newWithChild(new OperandExpression(),
  129.                 ASTNode.newWithChild(new MemoryAddressExpression(),
  130.                     ASTNode.newWithChild(new IdentifierExpression(), new ASTNode(new StringExpression("bf_memory"))))),
  131.             ASTNode.newWithChild(new OperandExpression(), new ASTNode(new RegisterExpression(Register.EAX)))
  132.         )));
  133.         textSectionNode.addChild(ASTNode.newWithChildren(new MovExpression(), Arrays.asList(
  134.             ASTNode.newWithChild(new OperandExpression(), new ASTNode(new RegisterExpression(Register.EDI))),
  135.             ASTNode.newWithChild(new OperandExpression(), new ASTNode(new RegisterExpression(Register.EAX)))
  136.         )));
  137.  
  138.         // Code Generated from the Intermediate AST
  139.         convertIntermediateToTargetNodes(intermediateAST.getRoot(), "").forEach(textSectionNode::addChild);
  140.  
  141.         // Bottom of the BF.exe program -do not modify-
  142.         textSectionNode.addChild(ASTNode.newWithChild(new JmpExpression(),
  143.             ASTNode.newWithChild(new OperandExpression(),
  144.                 ASTNode.newWithChild(new LabelExpression(), new ASTNode(new StringExpression("normal_exit"))))));
  145.  
  146.         textSectionNode.addChild(ASTNode.newWithChild(new DefineLabelExpression(),
  147.             ASTNode.newWithChild(new LabelExpression(), new ASTNode(new StringExpression("error_exit_outofmemory")))));
  148.         textSectionNode.addChild(ASTNode.newWithChild(new PushExpression(),
  149.             ASTNode.newWithChild(new OperandExpression(),
  150.                 ASTNode.newWithChild(new IdentifierExpression(), new ASTNode(new StringExpression("write_mode"))))));
  151.         textSectionNode.addChild(ASTNode.newWithChild(new PushExpression(),
  152.             ASTNode.newWithChild(new OperandExpression(),
  153.                 ASTNode.newWithChild(new DwordExpression(), new ASTNode(new IntegerExpression(stderr))))));
  154.         textSectionNode.addChild(ASTNode.newWithChild(new CallExpression(),
  155.             ASTNode.newWithChild(new OperandExpression(),
  156.                 ASTNode.newWithChild(new FunctionExpression(), new ASTNode(new StringExpression("_fdopen"))))));
  157.         textSectionNode.addChild(ASTNode.newWithChildren(new AddExpression(), Arrays.asList(
  158.             ASTNode.newWithChild(new OperandExpression(), new ASTNode(new RegisterExpression(Register.ESP))),
  159.             ASTNode.newWithChild(new OperandExpression(), new ASTNode(new IntegerExpression(8)))
  160.         )));
  161.         textSectionNode.addChild(ASTNode.newWithChild(new PushExpression(),
  162.             ASTNode.newWithChild(new OperandExpression(),
  163.                 ASTNode.newWithChild(new IdentifierExpression(), new ASTNode(new StringExpression("error_outofmemory"))))));
  164.         textSectionNode.addChild(ASTNode.newWithChild(new PushExpression(),
  165.             ASTNode.newWithChild(new OperandExpression(), new ASTNode(new RegisterExpression(Register.EAX)))));
  166.         textSectionNode.addChild(ASTNode.newWithChild(new CallExpression(),
  167.             ASTNode.newWithChild(new OperandExpression(),
  168.                 ASTNode.newWithChild(new FunctionExpression(), new ASTNode(new StringExpression("_fprintf"))))));
  169.         textSectionNode.addChild(ASTNode.newWithChildren(new AddExpression(), Arrays.asList(
  170.             ASTNode.newWithChild(new OperandExpression(), new ASTNode(new RegisterExpression(Register.ESP))),
  171.             ASTNode.newWithChild(new OperandExpression(), new ASTNode(new IntegerExpression(8)))
  172.         )));
  173.         textSectionNode.addChild(ASTNode.newWithChildren(new MovExpression(), Arrays.asList(
  174.             ASTNode.newWithChild(new OperandExpression(), new ASTNode(new RegisterExpression(Register.EAX))),
  175.             ASTNode.newWithChild(new OperandExpression(), new ASTNode(new IntegerExpression(-1)))
  176.         )));
  177.         textSectionNode.addChild(ASTNode.newWithChild(new JmpShortExpression(),
  178.             ASTNode.newWithChild(new OperandExpression(),
  179.                 ASTNode.newWithChild(new LabelExpression(), new ASTNode(new StringExpression("exit"))))));
  180.  
  181.         textSectionNode.addChild(ASTNode.newWithChild(new DefineLabelExpression(),
  182.             ASTNode.newWithChild(new LabelExpression(), new ASTNode(new StringExpression("normal_exit")))));
  183.         textSectionNode.addChild(ASTNode.newWithChildren(new MovExpression(), Arrays.asList(
  184.             ASTNode.newWithChild(new OperandExpression(), new ASTNode(new RegisterExpression(Register.EAX))),
  185.             ASTNode.newWithChild(new OperandExpression(), new ASTNode(new IntegerExpression(0)))
  186.         )));
  187.  
  188.         textSectionNode.addChild(ASTNode.newWithChild(new DefineLabelExpression(),
  189.             ASTNode.newWithChild(new LabelExpression(), new ASTNode(new StringExpression("exit")))));
  190.         textSectionNode.addChild(new ASTNode(new RetExpression()));
  191.         rootNode.addChild(textSectionNode);
  192.  
  193.         return ast;
  194.     }
  195.  
  196.     private Stream<ASTNode> convertIntermediateToTargetNodes(final ASTNode node, final String uniqueIndex) {
  197.         Expression expression = node.getExpression();
  198.         if (expression instanceof RootExpression) {
  199.             return IntStream.range(0, node.getChildren().size())
  200.                 .boxed()
  201.                 .flatMap(i -> convertIntermediateToTargetNodes(node.getChildren().get(i), uniqueIndex + "_" + i));
  202.         }
  203.         if (expression instanceof MemoryLoopExpression) {
  204.             return Stream.concat(
  205.                 Stream.of(
  206.                     ASTNode.newWithChildren(new MovExpression(), Arrays.asList(
  207.                         ASTNode.newWithChild(new OperandExpression(), new ASTNode(new RegisterExpression(Register.AL))),
  208.                         ASTNode.newWithChild(new OperandExpression(),
  209.                             ASTNode.newWithChild(new MemoryAddressExpression(), new ASTNode(new RegisterExpression(Register.EDI))))
  210.                     )),
  211.                     ASTNode.newWithChildren(new TestExpression(), Arrays.asList(
  212.                         ASTNode.newWithChild(new OperandExpression(), new ASTNode(new RegisterExpression(Register.AL))),
  213.                         ASTNode.newWithChild(new OperandExpression(), new ASTNode(new RegisterExpression(Register.AL)))
  214.                     )),
  215.                     ASTNode.newWithChild(new JzExpression(),
  216.                         ASTNode.newWithChild(new OperandExpression(),
  217.                             ASTNode.newWithChild(new LabelExpression(), new ASTNode(new StringExpression("loop_end" + uniqueIndex))))),
  218.                     ASTNode.newWithChild(new DefineLabelExpression(),
  219.                         ASTNode.newWithChild(new LabelExpression(), new ASTNode(new StringExpression("loop_start" + uniqueIndex))))
  220.                 ),
  221.                 Stream.concat(
  222.                     IntStream.range(0, node.getChildren().size())
  223.                         .boxed()
  224.                         .flatMap(i -> convertIntermediateToTargetNodes(node.getChildren().get(i), uniqueIndex + "_" + i)),
  225.                     Stream.of(
  226.                         ASTNode.newWithChildren(new MovExpression(), Arrays.asList(
  227.                             ASTNode.newWithChild(new OperandExpression(), new ASTNode(new RegisterExpression(Register.AL))),
  228.                             ASTNode.newWithChild(new OperandExpression(),
  229.                                 ASTNode.newWithChild(new MemoryAddressExpression(), new ASTNode(new RegisterExpression(Register.EDI))))
  230.                         )),
  231.                         ASTNode.newWithChildren(new TestExpression(), Arrays.asList(
  232.                             ASTNode.newWithChild(new OperandExpression(), new ASTNode(new RegisterExpression(Register.AL))),
  233.                             ASTNode.newWithChild(new OperandExpression(), new ASTNode(new RegisterExpression(Register.AL)))
  234.                         )),
  235.                         ASTNode.newWithChild(new JnzExpression(),
  236.                             ASTNode.newWithChild(new OperandExpression(),
  237.                                 ASTNode.newWithChild(new LabelExpression(), new ASTNode(new StringExpression("loop_start" + uniqueIndex))))),
  238.                         ASTNode.newWithChild(new DefineLabelExpression(),
  239.                             ASTNode.newWithChild(new LabelExpression(), new ASTNode(new StringExpression("loop_end" + uniqueIndex))))
  240.                     )
  241.                 )
  242.             );
  243.         }
  244.         if (expression instanceof MemoryPointerChangeExpression) {
  245.             int changeValue = node.getChildren().get(0).getExpression(IntegerExpression.class).getInteger();
  246.             if (changeValue == 0) {
  247.                 return Stream.empty();
  248.             }
  249.             return Stream.of(
  250.                 ASTNode.newWithChildren(new AddExpression(), Arrays.asList(
  251.                     ASTNode.newWithChild(new OperandExpression(), new ASTNode(new RegisterExpression(Register.EDI))),
  252.                     ASTNode.newWithChild(new OperandExpression(), new ASTNode(new IntegerExpression(changeValue)))
  253.                 ))
  254.             );
  255.         }
  256.         if (expression instanceof MemoryValueChangeExpression) {
  257.             int changeValue = node.getChildren().get(0).getExpression(IntegerExpression.class).getInteger();
  258.             if (changeValue == 0) {
  259.                 return Stream.empty();
  260.             }
  261.             return Stream.of(
  262.                 ASTNode.newWithChildren(new MovExpression(), Arrays.asList(
  263.                     ASTNode.newWithChild(new OperandExpression(), new ASTNode(new RegisterExpression(Register.AL))),
  264.                     ASTNode.newWithChild(new OperandExpression(),
  265.                         ASTNode.newWithChild(new MemoryAddressExpression(), new ASTNode(new RegisterExpression(Register.EDI))))
  266.                 )),
  267.                 ASTNode.newWithChildren(new AddExpression(), Arrays.asList(
  268.                     ASTNode.newWithChild(new OperandExpression(), new ASTNode(new RegisterExpression(Register.AL))),
  269.                     ASTNode.newWithChild(new OperandExpression(), new ASTNode(new IntegerExpression(changeValue)))
  270.                 )),
  271.                 ASTNode.newWithChildren(new MovExpression(), Arrays.asList(
  272.                     ASTNode.newWithChild(new OperandExpression(),
  273.                         ASTNode.newWithChild(new MemoryAddressExpression(), new ASTNode(new RegisterExpression(Register.EDI)))),
  274.                     ASTNode.newWithChild(new OperandExpression(), new ASTNode(new RegisterExpression(Register.AL)))
  275.                 ))
  276.             );
  277.         }
  278.         if (expression instanceof MemoryInputExpression) {
  279.             return Stream.of(
  280.                 ASTNode.newWithChild(new CallExpression(),
  281.                     ASTNode.newWithChild(new OperandExpression(),
  282.                         ASTNode.newWithChild(new FunctionExpression(), new ASTNode(new StringExpression("_getchar"))))),
  283.                 ASTNode.newWithChildren(new MovExpression(), Arrays.asList(
  284.                     ASTNode.newWithChild(new OperandExpression(),
  285.                         ASTNode.newWithChild(new MemoryAddressExpression(), new ASTNode(new RegisterExpression(Register.EDI)))),
  286.                     ASTNode.newWithChild(new OperandExpression(), new ASTNode(new RegisterExpression(Register.AL)))
  287.                 ))
  288.             );
  289.         }
  290.         if (expression instanceof MemoryOutputExpression) {
  291.             return Stream.of(
  292.                 ASTNode.newWithChildren(new MovExpression(), Arrays.asList(
  293.                     ASTNode.newWithChild(new OperandExpression(), new ASTNode(new RegisterExpression(Register.AL))),
  294.                     ASTNode.newWithChild(new OperandExpression(),
  295.                         ASTNode.newWithChild(new MemoryAddressExpression(), new ASTNode(new RegisterExpression(Register.EDI))))
  296.                 )),
  297.                 ASTNode.newWithChild(new PushExpression(),
  298.                     ASTNode.newWithChild(new OperandExpression(), new ASTNode(new RegisterExpression(Register.EAX)))),
  299.                 ASTNode.newWithChild(new CallExpression(),
  300.                     ASTNode.newWithChild(new OperandExpression(),
  301.                         ASTNode.newWithChild(new FunctionExpression(), new ASTNode(new StringExpression("_putchar"))))),
  302.                 ASTNode.newWithChildren(new AddExpression(), Arrays.asList(
  303.                     ASTNode.newWithChild(new OperandExpression(), new ASTNode(new RegisterExpression(Register.ESP))),
  304.                     ASTNode.newWithChild(new OperandExpression(), new ASTNode(new IntegerExpression(4)))
  305.                 ))
  306.             );
  307.         }
  308.         throw new IllegalArgumentException("Node with unsupported expression type: " + expression);
  309.     }
  310. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement