/src/org/ooc/middle/hobgoblins/Resolver.java

http://github.com/nddrylliog/ooc · Java · 124 lines · 97 code · 21 blank · 6 comment · 18 complexity · e63d9c46118e606cc59de85bd1fc944d MD5 · raw file

  1. package org.ooc.middle.hobgoblins;
  2. import java.io.IOException;
  3. import org.ooc.frontend.BuildParams;
  4. import org.ooc.frontend.model.Module;
  5. import org.ooc.frontend.model.Node;
  6. import org.ooc.frontend.model.NodeList;
  7. import org.ooc.frontend.model.TypeDecl;
  8. import org.ooc.frontend.model.interfaces.MustBeResolved;
  9. import org.ooc.frontend.model.interfaces.MustBeResolved.Response;
  10. import org.ooc.frontend.model.tokens.Token;
  11. import org.ooc.middle.Hobgoblin;
  12. import org.ooc.middle.OocCompilationError;
  13. import org.ooc.middle.walkers.Opportunist;
  14. import org.ooc.middle.walkers.SketchyNosy;
  15. public class Resolver implements Hobgoblin {
  16. protected static final int MAX = 4, SAFE_MAX = 1024;
  17. boolean running = false;
  18. boolean restarted = false;
  19. public boolean fatal = false;
  20. static int restartCount = 0;
  21. public BuildParams params;
  22. public Module module;
  23. private int ghostingCount = 1;
  24. public boolean process(Module module, final BuildParams params) throws IOException {
  25. this.module = module;
  26. this.params = params;
  27. // FIXME this is a hack to allow early removal of ghost type-arguments
  28. // in TypeDecls. see their resolve() method. This is non-optimal, and due
  29. // to the fact that in j/ooc, things are resolved depth-first. It's not
  30. // the same in rock, where each node is responsible of resolving their
  31. // children nodes.
  32. if(ghostingCount-- > 0) {
  33. NodeList<Node> stack = new NodeList<Node>(Token.defaultToken);
  34. stack.push(module);
  35. for(TypeDecl typeDecl: module.getTypes().values()) {
  36. typeDecl.resolve(stack, this, false);
  37. }
  38. return true;
  39. }
  40. SketchyNosy nosy = SketchyNosy.get(new Opportunist<Node>() {
  41. public boolean take(Node node, NodeList<Node> stack) throws IOException {
  42. if(node instanceof MustBeResolved) {
  43. MustBeResolved must = (MustBeResolved) node;
  44. if(!must.isResolved()) {
  45. Response res = Response.OK;
  46. try {
  47. res = must.resolve(stack, Resolver.this, fatal);
  48. } catch(OocCompilationError e) {
  49. if(params.veryVerbose) {
  50. e.printStackTrace();
  51. } else {
  52. throw e;
  53. }
  54. }
  55. if(res == Response.LOOP) {
  56. if(fatal) {
  57. System.out.println(must+" has LOOPed in fatal round.");
  58. }
  59. //System.out.println(must+" has LOOPed.");
  60. running = true;
  61. } else if(res == Response.RESTART) {
  62. if(fatal) {
  63. System.out.println(must+" has RESTARTed in fatal round.");
  64. }
  65. if(params.veryVerbose) {
  66. restartCount++;
  67. System.out.println("("+restartCount+") [ "+must.getClass().getSimpleName()+" ]\t\t"+must+" has RESTARTed.");
  68. }
  69. restarted = true;
  70. running = true;
  71. return false;
  72. }
  73. }
  74. }
  75. return true;
  76. }
  77. });
  78. int count = 0, safeCount = 0;
  79. running = true;
  80. if(count > MAX || safeCount > SAFE_MAX) {
  81. fatal = true;
  82. nosy.start().visit(module);
  83. throw new OocCompilationError(module, module, "Resolver is running in circles. Abandoning. (count = "
  84. +count+"/"+MAX+", safeCount = "+safeCount+"/"+SAFE_MAX+")");
  85. }
  86. running = false;
  87. nosy.start().visit(module);
  88. safeCount++;
  89. if(restarted) {
  90. restarted = false;
  91. } else {
  92. count++;
  93. }
  94. return running;
  95. }
  96. @Override
  97. public String toString() {
  98. return module.getFullName();
  99. }
  100. public boolean isFatal() {
  101. return fatal;
  102. }
  103. }