/interpreter/tags/at2dist220411/src/edu/vub/at/eval/InvocationStack.java
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}