TracedProcedure.java 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. package kawa.standard;
  2. import gnu.mapping.*;
  3. import java.io.PrintWriter;
  4. import gnu.math.IntNum;
  5. import gnu.kawa.functions.ObjectFormat;
  6. import gnu.kawa.io.OutPort;
  7. /** A TracedProcedure is a Procedure wrapper that writes trace output. */
  8. public class TracedProcedure extends ProcedureN
  9. {
  10. public Procedure proc;
  11. boolean enabled;
  12. static int indentationStep = 2;
  13. static Symbol curIndentSym = Symbol.makeUninterned("current-indentation");
  14. public TracedProcedure (Procedure proc, boolean enable)
  15. {
  16. this.proc = proc;
  17. this.enabled = enable;
  18. String name = proc.getName();
  19. if (name != null)
  20. setName(name);
  21. }
  22. static void put(Object value, PrintWriter out)
  23. {
  24. try
  25. {
  26. if (! ObjectFormat.format(value, out, 50, true))
  27. out.print("...");
  28. }
  29. catch (java.io.IOException ex)
  30. {
  31. out.print("<caught ");
  32. out.print(ex);
  33. out.print('>');
  34. }
  35. }
  36. static void indent(int i, PrintWriter out)
  37. {
  38. while (--i >= 0)
  39. out.print(' ');
  40. }
  41. public Object applyN(Object[] args) throws Throwable
  42. {
  43. if (enabled)
  44. {
  45. Environment env = Environment.getCurrent();
  46. Location curIndentLoc = env.getLocation(curIndentSym);
  47. Object oldIndent = curIndentLoc.get(null);
  48. int curIndent;
  49. if (! (oldIndent instanceof IntNum))
  50. {
  51. curIndent = 0;
  52. curIndentLoc.set(IntNum.zero());
  53. }
  54. else
  55. curIndent = ((IntNum) oldIndent).intValue();
  56. PrintWriter out = OutPort.errDefault();
  57. String name = getName();
  58. if (name == null)
  59. name = "??";
  60. // Print the call arguments (indented).
  61. indent(curIndent, out);
  62. out.print("call to ");
  63. out.print(name);
  64. int len = args.length;
  65. out.print(" (");
  66. for (int i = 0; i < len; i++)
  67. {
  68. if (i > 0)
  69. out.print(' ');
  70. put(args[i], out);
  71. }
  72. out.println(")");
  73. // Now do the actual call, but with the indentation incremented.
  74. IntNum newIndentation = IntNum.make(curIndent+indentationStep);
  75. Object result;
  76. Object save = curIndentLoc.setWithSave(newIndentation);
  77. try
  78. {
  79. result = proc.applyN(args);
  80. }
  81. catch (RuntimeException e)
  82. {
  83. indent(curIndent, out);
  84. out.println("procedure " + name + " throws exception " + e);
  85. throw e;
  86. }
  87. finally
  88. {
  89. curIndentLoc.setRestore(save);
  90. }
  91. // Print the result (indented).
  92. indent(curIndent, out);
  93. out.print("return from ");
  94. out.print(name);
  95. out.print(" => ");
  96. put(result, out);
  97. out.println();
  98. return result;
  99. }
  100. return proc.applyN(args);
  101. }
  102. public static Procedure doTrace(Procedure proc, boolean enable)
  103. {
  104. if (proc instanceof TracedProcedure)
  105. {
  106. ((TracedProcedure) proc).enabled = enable;
  107. return proc;
  108. }
  109. else
  110. return new TracedProcedure(proc, enable);
  111. }
  112. public void print(java.io.PrintWriter ps)
  113. {
  114. ps.print ("#<procedure ");
  115. String n = getName();
  116. if (n == null)
  117. ps.print ("<unnamed>");
  118. else
  119. ps.print (n);
  120. ps.print(enabled? ", traced>" : ">");
  121. }
  122. }