001: /*
002: * @(#)DebugContext.java 1.3 05/03/18
003: *
004: * Copyright (c) 1997-2005 Sun Microsystems, Inc. All Rights Reserved.
005: *
006: * See the file "LICENSE.txt" for information on usage and redistribution
007: * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
008: */
009: package pnuts.tools;
010:
011: import java.util.Enumeration;
012: import java.util.Vector;
013:
014: import pnuts.lang.Context;
015: import pnuts.lang.Function;
016: import pnuts.lang.Package;
017: import pnuts.lang.PnutsImpl;
018: import pnuts.lang.SimpleNode;
019:
020: /**
021: * This class is a Context used in debug mode.
022: */
023: public class DebugContext extends Context {
024: private final static boolean DEBUG = false;
025: private Vector listeners = null;
026: private int callDepth = 0;
027: private int lastCallDepth = 0;
028: private Debugger debugger;
029:
030: public DebugContext() {
031: this .setImplementation(new PnutsImpl()); // force pure interpreter
032: }
033:
034: public DebugContext(Package pkg) {
035: super (pkg);
036: this .setImplementation(new PnutsImpl()); // force pure interpreter
037: }
038:
039: public DebugContext(Context context) {
040: super (context);
041: this .setImplementation(new PnutsImpl()); // force pure interpreter
042: }
043:
044: /**
045: * Registers the specified debugger as the controller of this debug context
046: */
047: public void setDebugger(Debugger debugger) {
048: this .debugger = debugger;
049: }
050:
051: /**
052: * Returns the debugger that controls this debug context
053: */
054: public Debugger getDebugger() {
055: return this .debugger;
056: }
057:
058: /**
059: * Tracks stack depth (function call) in pure interpreter.
060: * This method overrides Context.open().
061: */
062: protected void open(Function f, Object[] args) {
063: super .open(f, args);
064: ++callDepth;
065: fireCommandEvent(CommandEvent.OPEN_FRAME, new Object[] { f,
066: args });
067: }
068:
069: /**
070: * Tracks stack depth (function return) in pure interpreter.
071: * This method overrides Context.close().
072: */
073: protected void close(Function f, Object[] args) {
074: fireCommandEvent(CommandEvent.CLOSE_FRAME, new Object[] { f,
075: args });
076: super .close(f, args);
077: --callDepth;
078: }
079:
080: /**
081: * Get the depth of evaluation.
082: *
083: * This value increases when load(), loadFile(), or eval() is called.
084: */
085: public int getEvalDepth() {
086: return depth;
087: }
088:
089: /**
090: * Get the stack depth (in pure interpreter)
091: */
092: public int getCallDepth() {
093: return callDepth;
094: }
095:
096: protected int getBeginLine() {
097: return beginLine;
098: }
099:
100: protected int getEndLine() {
101: return beginLine;
102: }
103:
104: protected Object getScriptSource() {
105: return super .getScriptSource();
106: }
107:
108: /**
109: * This method is called when line number is changed.
110: */
111: protected void updateLine(SimpleNode node, int beginLine,
112: int beginColumn) {
113: int line = beginLine;
114: if (line > 0
115: && (this .beginLine != line || callDepth != lastCallDepth)) {
116: this .beginLine = line;
117: this .lastCallDepth = callDepth;
118: fireCommandEvent(CommandEvent.LINE_UPDATED, node);
119: }
120: }
121:
122: /**
123: * This method is called when some exception is thrown.
124: */
125: protected void onError(Throwable t) {
126: fireCommandEvent(CommandEvent.EXCEPTION, t);
127: }
128:
129: /**
130: * This method is called when an evaluation is terminated normally.
131: */
132: protected void onExit(Object arg) {
133: fireCommandEvent(CommandEvent.EXITED, arg);
134: }
135:
136: void fireCommandEvent(int type, Object arg) {
137: if (listeners != null) {
138: Vector vec = (Vector) listeners.clone();
139: CommandEvent event = new CommandEvent(this , type, arg);
140: for (Enumeration e = vec.elements(); e.hasMoreElements();) {
141: ((CommandListener) e.nextElement()).signal(event);
142: }
143: }
144: }
145:
146: public synchronized void addCommandListener(CommandListener listener) {
147: if (listeners == null) {
148: listeners = new Vector();
149: }
150: listeners.addElement(listener);
151: }
152:
153: public synchronized void removeCommandListener(
154: CommandListener listener) {
155: listeners.removeElement(listener);
156: if (listeners.size() == 0) {
157: listeners = null;
158: }
159: }
160:
161: public Object clone(boolean clear_attributes, boolean clear_locals,
162: boolean clear_listeners) {
163: DebugContext ret = (DebugContext) super.clone(clear_attributes,
164: clear_locals);
165: if (clear_listeners) {
166: ret.listeners = null;
167: }
168: return ret;
169: }
170: }
|