blob: 0437fec6a78e56434eaf750d8927a1bef0ca66c8 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2018 R.Dvorak and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Radek Dvorak - initial API and implementation
*******************************************************************************/
package org.eclipse.m2m.qvt.oml.debug.core.vm;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EParameter;
import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalEvaluationEnv;
import org.eclipse.m2m.internal.qvt.oml.ast.parser.QvtOperationalParserUtil;
import org.eclipse.m2m.internal.qvt.oml.expressions.ImperativeOperation;
import org.eclipse.m2m.internal.qvt.oml.expressions.Module;
public class VMStackFrame implements Serializable {
private static final long serialVersionUID = -9084603067226851028L;
private static class Loc implements VMLocation {
private static final long serialVersionUID = 6628362004248726386L;
private final VMStackFrame frame;
private Loc(VMStackFrame frame) {
this.frame = frame;
}
/* (non-Javadoc)
* @see org.eclipse.m2m.qvt.oml.debug.core.vm.VMLocation#getLineNum()
*/
public int getLineNum() {
return frame.lineNum;
}
/* (non-Javadoc)
* @see org.eclipse.m2m.qvt.oml.debug.core.vm.VMLocation#getURI()
*/
public String getURI() {
return frame.uri;
}
/* (non-Javadoc)
* @see org.eclipse.m2m.qvt.oml.debug.core.vm.VMLocation#getModule()
*/
public String getModule() {
return frame.module;
}
/* (non-Javadoc)
* @see org.eclipse.m2m.qvt.oml.debug.core.vm.VMLocation#getOperationSignature()
*/
public String getOperationSignature() {
return frame.operationSignature;
}
}
public long id;
private String uri;
private int lineNum;
public String module;
public String operationSignature;
public VMVariable[] visibleVariables;
private transient VMLocation location;
private VMStackFrame(long id, String uri, String module, String operationSignature, int line, VMVariable[] vars) {
if(vars != null && (vars.length == 0 || Arrays.asList(vars).contains(null))) {
throw new IllegalArgumentException();
}
this.id = id;
this.uri = uri;
this.module = module;
this.operationSignature = operationSignature;
this.visibleVariables = vars;
this.lineNum = line;
}
public synchronized VMLocation getLocation() {
if(location == null) {
location = new Loc(this);
}
return location;
}
public List<VMVariable> getVisibleVariables() {
if(visibleVariables == null) {
return Collections.emptyList();
}
return Arrays.asList(visibleVariables);
}
public static VMStackFrame createFrame(long frameID, List<UnitLocation> stack) {
UnitLocation location = lookupEnvironmentByID(frameID, stack);
if (location != null) {
return VMStackFrame.create(location);
}
// invalid stack frame
return null;
}
public static VMStackFrame create(UnitLocation location) {
return create(location, true);
}
public static VMStackFrame create(UnitLocation location, boolean includeVars) {
DebugEvaluationEnvironment evalEnv = (DebugEvaluationEnvironment) location.getEvalEnv();
Module module = location.getModule();
String moduleName = (module != null) ? module.getName() : "<null>"; //$NON-NLS-1$
ImperativeOperation operation = location.getOperation();
String operSignature = (operation != null) ? getOperationSignature(operation)
: MessageFormat.format("<{0}>", moduleName); //$NON-NLS-1$
List<VMVariable> vars = VariableFinder.getVariables(evalEnv);
VMStackFrame vmStackFrame = new VMStackFrame(evalEnv.getID(), location.getURI().toString(), moduleName,
operSignature, location.getLineNum(), vars.toArray(new VMVariable[vars.size()]));
return vmStackFrame;
}
static VMStackFrame[] create(List<UnitLocation> stack) {
List<VMStackFrame> result = new ArrayList<VMStackFrame>();
int i = 0;
for (UnitLocation location : stack) {
// include variables only for the current (top level) stack
result.add(create(location, i++ == 0));
}
return result.toArray(new VMStackFrame[result.size()]);
}
static UnitLocation lookupEnvironmentByID(long id, List<UnitLocation> stack) {
for (UnitLocation location : stack) {
QvtOperationalEvaluationEnv evalEnv = location.getEvalEnv();
if(evalEnv instanceof DebugEvaluationEnvironment) {
DebugEvaluationEnvironment debugEvalEnv = (DebugEvaluationEnvironment) evalEnv;
if(debugEvalEnv.getID() == id) {
return location;
}
}
}
return null;
}
private static String getOperationSignature(ImperativeOperation operation) {
StringBuffer buf = new StringBuffer();
EClassifier ctxType = QvtOperationalParserUtil.getContextualType(operation);
if (ctxType != null) {
buf.append(ctxType.getName()).append("::"); //$NON-NLS-1$
}
buf.append(operation.getName());
buf.append('(');
int i = 0, n = operation.getEParameters().size();
for (EParameter param : operation.getEParameters()) {
EClassifier type = param.getEType();
buf.append(type.getName());
if (i+1 < n) {
buf.append(", "); //$NON-NLS-1$
}
++i;
}
buf.append(')');
return buf.toString();
}
}