/*******************************************************************************
* Copyright (c) 2004 Vlad Dumitrescu and others.
* 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:
* Vlad Dumitrescu
*******************************************************************************/
package org.erlide.backend.debug.model;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IDebugTarget;
import org.eclipse.debug.core.model.IDropToFrame;
import org.eclipse.debug.core.model.IRegisterGroup;
import org.eclipse.debug.core.model.IStackFrame;
import org.eclipse.debug.core.model.IThread;
import org.eclipse.debug.core.model.IVariable;
import org.erlide.engine.ErlangEngine;
import org.erlide.engine.model.ErlModelException;
import org.erlide.engine.model.IErlElement;
import org.erlide.engine.model.erlang.ErlangFunction;
import org.erlide.engine.model.erlang.IErlFunction;
import org.erlide.engine.model.erlang.IErlFunctionClause;
import org.erlide.engine.model.root.IErlModule;
import org.erlide.util.ErlLogger;
import com.ericsson.otp.erlang.OtpErlangAtom;
import com.ericsson.otp.erlang.OtpErlangList;
import com.ericsson.otp.erlang.OtpErlangObject;
import com.ericsson.otp.erlang.OtpErlangTuple;
public class ErlangStackFrame extends ErlangDebugElement
implements IStackFrame, IDropToFrame {
private final String fModuleName;
private final ErlangProcess fParent;
private final int fLineNumber;
List<ErlangVariable> bindings;
int stackFrameNo;
private String clauseHead;
public ErlangStackFrame(final String moduleName, final ErlangProcess parent,
final IDebugTarget target, final int lineNumber0,
final ErlangFunction function, final OtpErlangList bindings,
final int stackFrameNo) {
super(target);
fParent = parent;
fModuleName = moduleName;
this.stackFrameNo = stackFrameNo;
final List<ErlangVariable> framesReversed = new ArrayList<>(
bindings.arity());
for (final OtpErlangObject o : bindings) {
if (o instanceof OtpErlangTuple) {
final OtpErlangTuple t = (OtpErlangTuple) o;
final OtpErlangAtom nameA = (OtpErlangAtom) t.elementAt(0);
final OtpErlangObject value = t.elementAt(1);
framesReversed.add(new ErlangVariable(target, nameA.atomValue(), false,
value, parent, moduleName, stackFrameNo));
}
}
final List<ErlangVariable> frames = new ArrayList<>(
framesReversed.size());
for (int i = framesReversed.size() - 1; i >= 0; --i) {
frames.add(framesReversed.get(i));
}
this.bindings = frames;
IErlModule module;
try {
module = ErlangEngine.getInstance().getModel().findModule(moduleName);
} catch (final ErlModelException e) {
ErlLogger.error(e);
module = null;
}
clauseHead = null;
int lineNumber = lineNumber0;
if (module != null) {
try {
module.open(null);
if (lineNumber != -1) {
final IErlElement e = module.getElementAtLine(lineNumber - 1);
if (e instanceof IErlFunctionClause) {
final IErlFunctionClause clause = (IErlFunctionClause) e;
clauseHead = clause.getFunctionName() + clause.getHead();
}
} else if (function != null) {
final IErlFunction f = module.findFunction(function);
if (f != null) {
lineNumber = f.getLineStart() + 1;
clauseHead = f.getFunctionName() + f.getHead();
}
}
} catch (final ErlModelException e1) {
ErlLogger.warn(e1);
}
}
fLineNumber = lineNumber;
}
public String getModule() {
return fModuleName;
}
@Override
public IThread getThread() {
return fParent;
}
@Override
public IVariable[] getVariables() throws DebugException {
return bindings.toArray(new IVariable[bindings.size()]);
}
@Override
public boolean hasVariables() throws DebugException {
return true;
}
@Override
public int getLineNumber() throws DebugException {
return fLineNumber;
}
@Override
public int getCharStart() throws DebugException {
return -1;
}
@Override
public int getCharEnd() throws DebugException {
return -1;
}
@Override
public String getName() throws DebugException {
return "<" + fModuleName + ">";
}
@Override
public IRegisterGroup[] getRegisterGroups() throws DebugException {
return null;
}
@Override
public boolean hasRegisterGroups() throws DebugException {
return false;
}
@Override
public boolean canStepInto() {
return fParent.canStepInto();
}
@Override
public boolean canStepOver() {
return fParent.canStepOver();
}
@Override
public boolean canStepReturn() {
return fParent.canStepReturn();
}
@Override
public boolean isStepping() {
return fParent.isStepping();
}
@Override
public void stepInto() throws DebugException {
fParent.stepInto();
}
@Override
public void stepOver() throws DebugException {
fParent.stepOver();
}
@Override
public void stepReturn() throws DebugException {
fParent.stepReturn();
}
@Override
public boolean canResume() {
return fParent.canResume();
}
@Override
public boolean canSuspend() {
return fParent.canSuspend();
}
@Override
public boolean isSuspended() {
return fParent.isSuspended();
}
@Override
public void resume() throws DebugException {
fParent.resume();
}
@Override
public void suspend() throws DebugException {
fParent.suspend();
}
@Override
public boolean canTerminate() {
return fParent.canTerminate();
}
@Override
public boolean isTerminated() {
return fParent.isTerminated();
}
@Override
public void terminate() throws DebugException {
fParent.terminate();
}
public String getClauseHead() {
return clauseHead;
}
@Override
public boolean canDropToFrame() {
return true;
}
@Override
public void dropToFrame() throws DebugException {
fParent.dropToFrame(stackFrameNo);
}
}