package edu.mit.ai.psg.jeva.examples;

import edu.mit.ai.psg.jeva.*;
import java.io.PrintWriter;

/** <tt><a href="TraceAllEvalHook.java.html">TraceAllEvalHook.java</a></tt>
    traces evaluation by printing out the source of each java construct
    and the values of its free variables.
    This version only works on single threaded programs. 
    Output defaults to System.err.
    (note: requires {@link edu.mit.ai.psg.strings}).

    It produce traces of the following form:
    <pre>
    ->for (int i = 0; i < 1; i++) {
    |   break;
    | }
    | ->i < 1
    | | {i=0}
    | | 0 < 1
    | <-true
    | for (int i = 0; true; i++) {
    |   break;
    | }
    | ->{
    | |   break;
    | | }
    | | ->break;
    | | <-break
    | <-break
    <-
    </pre> 
    @author CarlManning, caroma@ai.mit.edu<br>
    Copyright (c) 1999 Massachusetts Institute of Technology **/ 
public class TraceAllEvalHook extends TraceEvalHookBase {
  // --- constructors ---
  public TraceAllEvalHook() {
    super();
  }
  public TraceAllEvalHook(PrintWriter pw) {
    super(pw);
  }
  /** An override to avoid tracing literals **/
  public Object visit(JNELiteralExpression node, Object data) {
    return data;
  }
  /** An override to avoid tracing simple names, 
      but still trace field accesses **/
  public Object visit(JNName node, Object data) {
    if (node.jjtGetNumChildren() == 0)
      return data;
    else return visit( (IJevaNode) node, data);
  }
  /** Calls {@link TraceMethods#traceSource} and
      {@link TraceMethods#traceFreeNames} before node is evaluated,
      {@link TraceMethods#traceApplications} after subexpressions are 
      evaluated, and {@link TraceMethods#tracePostData}
      after node completes. **/
  public Object indentedTrace(PrintWriter iw, IJevaNode node, Object data) {
    if (data instanceof EvalMethods.EvalHookPreData) {
      TraceMethods.traceSource(iw, node, data);
      if (! (node instanceof JNName) &&
	  ! (node instanceof JNELiteralExpression))
	TraceMethods.traceFreeNames(iw, node, data);
    } else if (data instanceof EvalMethods.PreApplyData) {
      TraceMethods.traceApplications(iw, node, data);
    } else if (data instanceof EvalMethods.EvalHookPostData) {
      TraceMethods.tracePostData(iw, node, data);
    }
    iw.flush();
    return null;
  }

  /* test */
  public static void main(String[] ignore) {
    EvalMethods.setEvalHook(new TraceAllEvalHook());
    try { 
      String stmt = ("{\n"+
		     "boolean b = true;\n"+
		     "b = ! b;\n"+
		     "b = b == b;\n"+
		     "b = b != b;\n"+
		     "b = b & b;\n"+
		     "b = b ^ b;\n"+
		     "b = b | b;\n"+
		     "b = b ? b : b;\n"+
		     "int i = 1;\n"+
		     "i = -i;\n"+
		     "i = +i;\n"+
		     "i = i*i;\n"+
		     "i = i/i;\n"+
		     "i = i-i;\n"+
		     "i = i+i;\n"+
		     "b = i < i;\n"+
		     "b = i <= i;\n"+
		     "b = i > i;\n"+		   
		     "b = i >= i;\n"+
		     "String s = \"s\";\n"+
		     "s += s;\n"+
		     "s = s.substring(0,1);\n"+
		     "i = System.identityHashCode(s);\n"+
		     "Object o = System.out;\n"+
		     "java.awt.Dimension d = new java.awt.Dimension(i,20);\n"+
		     "i = d.width;\n"+
		     "d.width += d.height;\n"+
		     "int[] a = {10,20,30};\n"+
		     "i = a[1];\n"+
		     "a[1] += i;\n"+
		     "a = new int[]{11,22,33};\n"+
		     "b = d instanceof java.awt.Dimension;\n"+
		     "d = (java.awt.Dimension) d;\n"+
		     "i++;\n"+
		     "i--;\n"+
		     "++i;\n"+
		     "--i;\n"+
		     "if (b) { b = false; } else { b = true; }\n"+
		     "do { b = ! b; } while (b);\n"+
		     "for (int j = 0; j < 1; j++) { continue; }\n"+
		     "label: switch(i) { case 0: break label; }\n"+
		     "synchronized(d) { d.width = i; }\n"+
		     "try { throw new Error(); } catch (Error e) {}\n"+
		     "while(b) { b=false; }\n"+
		     "}\n");
    /*
    String stmt = ("for (int i = 0; i < 2; i += 1 + i + i) {\n"+
		   "  if (i % 2 == 1) break;\n"+
 		   "}");
    */
      Jeva.parseEvalStringStatement(stmt); 
    } catch (Throwable e) { e.printStackTrace(); }
  }
}
