PageRenderTime 27ms CodeModel.GetById 12ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 1ms

/interpreter/tags/at2dist220411/src/edu/vub/at/eval/InvocationStack.java

http://ambienttalk.googlecode.com/
Java | 190 lines | 113 code | 24 blank | 53 comment | 10 complexity | 11131764605d99ddef01e74c197ecabb MD5 | raw file
  1/**
  2 * AmbientTalk/2 Project
  3 * InvocationStack.java created on 10-okt-2006 at 14:15:49
  4 * (c) Programming Technology Lab, 2006 - 2007
  5 * Authors: Tom Van Cutsem & Stijn Mostinckx
  6 * 
  7 * Permission is hereby granted, free of charge, to any person
  8 * obtaining a copy of this software and associated documentation
  9 * files (the "Software"), to deal in the Software without
 10 * restriction, including without limitation the rights to use,
 11 * copy, modify, merge, publish, distribute, sublicense, and/or
 12 * sell copies of the Software, and to permit persons to whom the
 13 * Software is furnished to do so, subject to the following
 14 * conditions:
 15 *
 16 * The above copyright notice and this permission notice shall be
 17 * included in all copies or substantial portions of the Software.
 18 *
 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 21 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 22 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 23 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 24 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 26 * OTHER DEALINGS IN THE SOFTWARE.
 27 */
 28package edu.vub.at.eval;
 29
 30import edu.vub.at.exceptions.InterpreterException;
 31import edu.vub.at.objects.ATAbstractGrammar;
 32import edu.vub.at.objects.ATClosure;
 33import edu.vub.at.objects.ATObject;
 34import edu.vub.at.objects.ATTable;
 35import edu.vub.at.parser.SourceLocation;
 36import edu.vub.at.trace.CallSite;
 37import edu.vub.at.trace.Trace;
 38
 39import java.io.PrintStream;
 40import java.io.PrintWriter;
 41import java.io.Serializable;
 42import java.util.Iterator;
 43import java.util.ListIterator;
 44import java.util.Set;
 45import java.util.Stack;
 46import java.util.Vector;
 47
 48/**
 49 * An InvocationStack instance represents the stack of method invocations and function applications
 50 * that are currently activated in an actor's thread. It is mainly used for debugging purposes
 51 * (e.g. generating stack trace information)
 52 * 
 53 * @author tvc
 54 */
 55public final class InvocationStack implements Cloneable, Serializable {
 56
 57	/**
 58	 * A thread-local variable is used to assign a unique invocation stack to
 59	 * each separate actor. Each actor that invokes the getInvocationStack()
 60	 * method receives its own separate copy of the invocation stack
 61	 */
 62	private static final ThreadLocal _INVOCATION_STACK_ = new ThreadLocal() {
 63	    protected synchronized Object initialValue() {
 64	        return new InvocationStack();
 65	    }
 66	};
 67	
 68	public static final InvocationStack getInvocationStack() {
 69		return (InvocationStack) _INVOCATION_STACK_.get();
 70	}
 71	
 72	public static final InvocationStack captureInvocationStack() {
 73		return (InvocationStack) getInvocationStack().clone();
 74	}
 75	
 76	private static class InvocationFrame implements Serializable {
 77		public final ATAbstractGrammar invocation;
 78		public final ATObject receiver;
 79		public final ATTable arguments;
 80		
 81		public InvocationFrame(ATAbstractGrammar inv, ATObject rcvr, ATTable args) {
 82			invocation = inv;
 83			receiver = rcvr;
 84			arguments = args;
 85		}
 86		
 87		public String toString() {
 88			SourceLocation loc = invocation.impl_getLocation();
 89			return Evaluator.toString(invocation) +
 90			         ((loc == null) ? "  (unknown source)" : "  (" + loc + ")");
 91		}
 92	}
 93	
 94	private final Stack invocationStack_;
 95	
 96	protected InvocationStack() {
 97		invocationStack_ = new Stack();
 98	}
 99	
100	private InvocationStack(Stack initstack) {
101		invocationStack_ = initstack;
102	}
103	
104	public void methodInvoked(ATAbstractGrammar methodInvocation, ATObject receiver, ATTable args) throws InterpreterException {
105		invocationStack_.push(new InvocationFrame(methodInvocation, receiver, args));
106	}
107	
108	public void functionCalled(ATAbstractGrammar funCall, ATClosure fun, ATTable evaluatedArgs) {
109		invocationStack_.push(new InvocationFrame(funCall, fun, evaluatedArgs));
110	}
111	
112	/**
113	 * @param result if null, the method invocation was aborted via an exception
114	 */
115	public void methodReturned(ATObject result) {
116		invocationStack_.pop();
117	}
118	
119	/**
120	 * @param result if null, the function call was aborted via an exception
121	 */
122	public void funcallReturned(ATObject result) {
123		invocationStack_.pop();
124	}
125	
126	public void printStackTrace(PrintStream s) {
127		if(!invocationStack_.isEmpty()) {
128			s.println("origin:");
129			// iterator loops from bottom to top by default
130			ListIterator i = invocationStack_.listIterator();
131			while (i.hasNext()) { i.next(); } // skip to last element
132			while(i.hasPrevious()) { // traverse stack top to bottom
133				InvocationFrame frame = (InvocationFrame) i.previous();
134				s.println("at "+frame);
135			}
136		}
137	}
138	
139	public void printStackTrace(PrintWriter s) {
140		if(!invocationStack_.isEmpty()) {
141			s.println("origin:");
142			// iterator loops from bottom to top by default
143			ListIterator i = invocationStack_.listIterator();
144			while (i.hasNext()) { i.next(); } // skip to last element
145			while(i.hasPrevious()) { // traverse stack top to bottom
146				InvocationFrame frame = (InvocationFrame) i.previous();
147				s.println("at "+frame);
148			}
149		}
150	}
151	
152	public Object clone() {
153		return new InvocationStack((Stack) invocationStack_.clone());
154	}
155	
156	/**
157	 * Generate a stack trace that can be processed by a post-mortem
158	 * debugger such as Causeway.
159	 */
160	public Trace generateTrace(Set sourceFilter) {
161		Vector callsites = new Vector(invocationStack_.size());
162		// iterator loops from bottom to top by default
163		ListIterator i = invocationStack_.listIterator();
164		
165		while (i.hasNext()) { i.next(); } // skip to last element
166		Loop: while(i.hasPrevious()) { // traverse stack top to bottom
167			InvocationFrame frame = (InvocationFrame) i.previous();
168			SourceLocation loc = frame.invocation.impl_getLocation();
169			String source = null;
170			int[][] span = null;
171			if (loc != null) {
172			  source = loc.fileName;
173			  
174			  // if (sourceFilter.contains(source)) { continue Loop; }
175			  for (Iterator filterIt = sourceFilter.iterator(); filterIt.hasNext();) {
176				String filteredFileName = (String) filterIt.next();
177				if (source.endsWith(filteredFileName)) {
178					continue Loop; // skip this file
179				}
180			}
181			  
182			  span = new int[][] { new int[] { loc.line, loc.column } };
183			}
184			String name = frame.invocation.toString();
185			callsites.add(new CallSite(name, source, span));
186		}
187		return new Trace((CallSite[]) callsites.toArray(new CallSite[callsites.size()]));
188	}
189	
190}