/******************************************************************************* * Copyright (c) 2013 CWI * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * * * Anya Helene Bagge - UiB *******************************************************************************/ package org.rascalmpl.interpreter; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import org.rascalmpl.value.ISourceLocation; public class StackTrace implements Iterable<StackTraceEntry> { public static final StackTrace EMPTY_STACK_TRACE = new StackTrace().freeze(); protected List<StackTraceEntry> trace = new ArrayList<StackTraceEntry>(); /** * Add a new entry to the stack trace. * * Later added entries are shown below earlier entries, with the * first/top entry being the location where the exception was * thrown. * * @param loc A source code location, or null * @param funName The name of the containing function, or null * @return this */ public StackTrace add(ISourceLocation loc, String funName) { trace.add(new StackTraceEntry(loc, funName)); return this; } /** * Add all entries of another stack trace to this stack trace. * * The entries are added at the end of this trace. * * @param stackTrace Another stack trace * @return this */ public StackTrace addAll(Iterable<StackTraceEntry> stackTrace) { if(stackTrace != null) { for(StackTraceEntry e : stackTrace) { trace.add(e); } } return this; } /** * Format this stack trace using embedded links, suitable * for printing on a Rascal console. * * @return The stack trace as a string */ public String toLinkedString() { StringBuilder b = new StringBuilder(4096); for(StackTraceEntry e : trace) { e.format(b, true); } return b.toString(); } @Override public String toString() { StringBuilder b = new StringBuilder(4096); for(StackTraceEntry e : trace) { e.format(b, false); } return b.toString(); } /** * Make the stack trace unmodifiable. * * The current stack trace is destroyed in the process, avoid using * it after this method returns. Use the return stack trace instead. * * @return an unmodifiable stack trace */ public StackTrace freeze() { UnmodifiableStackTrace result = new UnmodifiableStackTrace(this); trace = null; return result; } @Override public Iterator<StackTraceEntry> iterator() { return trace.iterator(); } /** * @return Current entries in the stack trace */ public int size() { return trace.size(); } static class UnmodifiableStackTrace extends StackTrace { private UnmodifiableStackTrace(StackTrace original) { super.trace = Collections.unmodifiableList(original.trace); } @Override public StackTrace add(ISourceLocation loc, String funName) { throw new UnsupportedOperationException("This stack trace is unmodifiable"); } @Override public StackTrace addAll(Iterable<StackTraceEntry> stackTrace) { throw new UnsupportedOperationException("This stack trace is unmodifiable"); } @Override public StackTrace freeze() { return this; } } }