blob: 5dc84be1bb668191ea65a7fa709f1eb1acd6f48e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011-2012 Vrije Universiteit Brussel.
* 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
* https://www.eclipse.org/legal/epl-2.0/
*
* Contributors:
* Dennis Wagelaar, Vrije Universiteit Brussel - initial API and
* implementation and/or initial documentation
*******************************************************************************/
package org.eclipse.m2m.atl.emftvm.impl;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.NotificationChain;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.m2m.atl.emftvm.CodeBlock;
import org.eclipse.m2m.atl.emftvm.EmftvmPackage;
import org.eclipse.m2m.atl.emftvm.Instruction;
import org.eclipse.m2m.atl.emftvm.LocalVariable;
/**
* <!-- begin-user-doc -->
* An implementation of the model object '<em><b>Local Variable</b></em>'.
* @author <a href="mailto:dennis.wagelaar@vub.ac.be">Dennis Wagelaar</a>
* <!-- end-user-doc -->
* <p>
* The following features are implemented:
* </p>
* <ul>
* <li>{@link org.eclipse.m2m.atl.emftvm.impl.LocalVariableImpl#getSlot <em>Slot</em>}</li>
* <li>{@link org.eclipse.m2m.atl.emftvm.impl.LocalVariableImpl#getOwningBlock <em>Owning Block</em>}</li>
* <li>{@link org.eclipse.m2m.atl.emftvm.impl.LocalVariableImpl#getStartInstruction <em>Start Instruction</em>}</li>
* <li>{@link org.eclipse.m2m.atl.emftvm.impl.LocalVariableImpl#getEndInstruction <em>End Instruction</em>}</li>
* <li>{@link org.eclipse.m2m.atl.emftvm.impl.LocalVariableImpl#getStartInstructionIndex <em>Start Instruction Index</em>}</li>
* <li>{@link org.eclipse.m2m.atl.emftvm.impl.LocalVariableImpl#getEndInstructionIndex <em>End Instruction Index</em>}</li>
* </ul>
*
* @generated
*/
public class LocalVariableImpl extends TypedElementImpl implements LocalVariable {
/**
* The default value of the '{@link #getSlot() <em>Slot</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getSlot()
* @generated
* @ordered
*/
protected static final int SLOT_EDEFAULT = -1;
/**
* The cached value of the '{@link #getSlot() <em>Slot</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getSlot()
* @generated NOT
* @ordered
*/
protected int slot = SLOT_EDEFAULT;
/**
* The cached value of the '{@link #getStartInstruction() <em>Start Instruction</em>}' reference.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getStartInstruction()
* @generated NOT
* @ordered
*/
protected Instruction startInstruction;
/**
* The cached value of the '{@link #getEndInstruction() <em>End Instruction</em>}' reference.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getEndInstruction()
* @generated NOT
* @ordered
*/
protected Instruction endInstruction;
/**
* The default value of the '{@link #getStartInstructionIndex() <em>Start Instruction Index</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getStartInstructionIndex()
* @generated
* @ordered
*/
protected static final int START_INSTRUCTION_INDEX_EDEFAULT = -1;
/**
* The default value of the '{@link #getEndInstructionIndex() <em>End Instruction Index</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getEndInstructionIndex()
* @generated
* @ordered
*/
protected static final int END_INSTRUCTION_INDEX_EDEFAULT = -1;
/**
* The cached value of the '{@link #getStartInstructionIndex() <em>Start Instruction Index</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getStartInstructionIndex()
* @generated NOT
* @ordered
*/
protected int startInstructionIndex = START_INSTRUCTION_INDEX_EDEFAULT;
/**
* The cached value of the '{@link #getEndInstructionIndex() <em>End Instruction Index</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getEndInstructionIndex()
* @generated NOT
* @ordered
*/
protected int endInstructionIndex = END_INSTRUCTION_INDEX_EDEFAULT;
/**
* <!-- begin-user-doc -->
* Creates a new {@link LocalVariableImpl}.
* <!-- end-user-doc -->
* @generated
*/
protected LocalVariableImpl() {
super();
}
/**
* <!-- begin-user-doc -->
* Returns the {@link EClass} that correspond to this metaclass.
* @return the {@link EClass} that correspond to this metaclass.
* <!-- end-user-doc -->
* @generated
*/
@Override
protected EClass eStaticClass() {
return EmftvmPackage.Literals.LOCAL_VARIABLE;
}
/**
* <!-- begin-user-doc. -->
* {@inheritDoc}
* <!-- end-user-doc -->
* @generated NOT
*/
public int getSlot() {
if (slot == SLOT_EDEFAULT) {
final CodeBlock cb = getOwningBlock();
if (cb != null) {
// Retrieve occupied slots of previous overlapping local variables
final EList<LocalVariable> locals = cb.getLocalVariables();
final int maxIndex = locals.indexOf(this);
assert maxIndex > -1;
if (maxIndex == 0) {
slot = 0;
} else {
final Set<Integer> localSlots = new HashSet<Integer>(maxIndex);
final int startIndex = getStartInstructionIndex();
final int endIndex = getEndInstructionIndex();
for (int lvIndex = 0; lvIndex < maxIndex; lvIndex++) {
LocalVariable lv = locals.get(lvIndex);
int start = lv.getStartInstructionIndex();
int end = lv.getEndInstructionIndex();
assert startIndex < 0 || start > -1;
assert endIndex < 0 || end > -1;
if (startIndex < 0 || endIndex < 0 || (start <= endIndex && end >= startIndex)) {
int slot = lv.getSlot();
if (slot < 0) {
throw new RuntimeException(String.format(
"Cannot calculate slot for %s; missing slot for %s",
this, lv));
}
if (localSlots.contains(slot)) {
throw new RuntimeException(String.format(
"Code block %s has more than one local variable occupying slot %d at instruction %d",
cb, slot, startIndex));
}
localSlots.add(slot);
}
}
// Pick first free slot and assign
int freeSlot = 0;
while (localSlots.contains(freeSlot)) {
freeSlot++;
}
slot = freeSlot;
}
}
}
return slot;
}
/**
* <!-- begin-user-doc. -->
* {@inheritDoc}
* <!-- end-user-doc -->
* @generated NOT
*/
public void setSlot(int newSlot) {
int oldSlot = slot;
slot = newSlot;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, EmftvmPackage.LOCAL_VARIABLE__SLOT, oldSlot, slot));
}
/**
* <!-- begin-user-doc. -->
* {@inheritDoc}
* <!-- end-user-doc -->
* @generated NOT
*/
public Instruction getStartInstruction() {
if (startInstruction == null) {
final CodeBlock cb = getOwningBlock();
final int startInstructionIndex = getStartInstructionIndex();
if (cb != null && startInstructionIndex != START_INSTRUCTION_INDEX_EDEFAULT
&& startInstructionIndex < cb.getCode().size()) {
startInstruction = cb.getCode().get(startInstructionIndex);
}
}
if (startInstruction != null && startInstruction.eIsProxy()) {
InternalEObject oldStartInstruction = (InternalEObject)startInstruction;
startInstruction = (Instruction)eResolveProxy(oldStartInstruction);
if (startInstruction != oldStartInstruction) {
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.RESOLVE, EmftvmPackage.LOCAL_VARIABLE__START_INSTRUCTION, oldStartInstruction, startInstruction));
}
}
return startInstruction;
}
/**
* <!-- begin-user-doc. -->
* {@inheritDoc}
* <!-- end-user-doc -->
* @generated NOT
*/
public Instruction basicGetStartInstruction() {
if (startInstruction == null) {
final CodeBlock cb = getOwningBlock();
final int startInstructionIndex = getStartInstructionIndex();
if (cb != null && startInstructionIndex != START_INSTRUCTION_INDEX_EDEFAULT
&& startInstructionIndex < cb.getCode().size()) {
startInstruction = cb.getCode().get(startInstructionIndex);
}
}
return startInstruction;
}
/**
* <!-- begin-user-doc. -->
* {@inheritDoc}
* <!-- end-user-doc -->
* @generated NOT
*/
public void setStartInstruction(Instruction newStartInstruction) {
Instruction oldStartInstruction = startInstruction;
startInstruction = newStartInstruction;
startInstructionIndex = START_INSTRUCTION_INDEX_EDEFAULT;
slot = SLOT_EDEFAULT;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, EmftvmPackage.LOCAL_VARIABLE__START_INSTRUCTION, oldStartInstruction, startInstruction));
}
/**
* <!-- begin-user-doc. -->
* {@inheritDoc}
* <!-- end-user-doc -->
* @generated NOT
*/
public Instruction getEndInstruction() {
if (endInstruction == null) {
final CodeBlock cb = getOwningBlock();
final int endInstructionIndex = getEndInstructionIndex();
if (cb != null && endInstructionIndex != END_INSTRUCTION_INDEX_EDEFAULT
&& endInstructionIndex < cb.getCode().size()) {
endInstruction = cb.getCode().get(endInstructionIndex);
}
}
if (endInstruction != null && endInstruction.eIsProxy()) {
InternalEObject oldEndInstruction = (InternalEObject)endInstruction;
endInstruction = (Instruction)eResolveProxy(oldEndInstruction);
if (endInstruction != oldEndInstruction) {
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.RESOLVE, EmftvmPackage.LOCAL_VARIABLE__END_INSTRUCTION, oldEndInstruction, endInstruction));
}
}
return endInstruction;
}
/**
* <!-- begin-user-doc. -->
* @see #getEndInstruction()
* <!-- end-user-doc -->
* @generated NOT
*/
public Instruction basicGetEndInstruction() {
if (endInstruction == null) {
final CodeBlock cb = getOwningBlock();
final int endInstructionIndex = getEndInstructionIndex();
if (cb != null && endInstructionIndex != END_INSTRUCTION_INDEX_EDEFAULT
&& endInstructionIndex < cb.getCode().size()) {
endInstruction = cb.getCode().get(endInstructionIndex);
}
}
return endInstruction;
}
/**
* <!-- begin-user-doc. -->
* {@inheritDoc}
* <!-- end-user-doc -->
* @generated NOT
*/
public void setEndInstruction(Instruction newEndInstruction) {
Instruction oldEndInstruction = endInstruction;
endInstruction = newEndInstruction;
endInstructionIndex = END_INSTRUCTION_INDEX_EDEFAULT;
slot = SLOT_EDEFAULT;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, EmftvmPackage.LOCAL_VARIABLE__END_INSTRUCTION, oldEndInstruction, endInstruction));
}
/**
* <!-- begin-user-doc. -->
* {@inheritDoc}
* <!-- end-user-doc -->
* @generated NOT
*/
public int getStartInstructionIndex() {
if (startInstructionIndex == START_INSTRUCTION_INDEX_EDEFAULT) {
final CodeBlock cb = getOwningBlock();
if (cb != null) {
final EList<Instruction> code = cb.getCode();
if (startInstruction != null) {
startInstructionIndex = cb.getCode().indexOf(startInstruction);
if (startInstructionIndex < 0) {
throw new IllegalArgumentException(String.format(
"Start instruction %s not found in code block %s",
startInstruction, cb));
}
} else if (!code.isEmpty()) {
startInstructionIndex = 0;
}
}
}
return startInstructionIndex;
}
/**
* <!-- begin-user-doc. -->
* {@inheritDoc}
* <!-- end-user-doc -->
* @generated NOT
*/
public void setStartInstructionIndex(int newStartInstructionIndex) {
int oldStartInstructionIndex = startInstructionIndex;
startInstructionIndex = newStartInstructionIndex;
if (newStartInstructionIndex != START_INSTRUCTION_INDEX_EDEFAULT) { // this value is normally derived
startInstruction = null;
}
slot = SLOT_EDEFAULT;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, EmftvmPackage.LOCAL_VARIABLE__START_INSTRUCTION_INDEX, oldStartInstructionIndex, startInstructionIndex));
}
/**
* <!-- begin-user-doc. -->
* {@inheritDoc}
* <!-- end-user-doc -->
* @generated NOT
*/
public int getEndInstructionIndex() {
if (endInstructionIndex == END_INSTRUCTION_INDEX_EDEFAULT) {
final CodeBlock cb = getOwningBlock();
if (cb != null) {
final EList<Instruction> code = cb.getCode();
if (endInstruction != null) {
endInstructionIndex = cb.getCode().indexOf(endInstruction);
if (endInstructionIndex < 0) {
throw new IllegalArgumentException(String.format(
"End instruction %s not found in code block %s",
endInstruction, cb));
}
} else if (!code.isEmpty()) {
endInstructionIndex = code.size() - 1;
}
}
}
return endInstructionIndex;
}
/**
* <!-- begin-user-doc. -->
* {@inheritDoc}
* <!-- end-user-doc -->
* @generated NOT
*/
public void setEndInstructionIndex(int newEndInstructionIndex) {
int oldEndInstructionIndex = endInstructionIndex;
endInstructionIndex = newEndInstructionIndex;
if (newEndInstructionIndex != END_INSTRUCTION_INDEX_EDEFAULT) { // this value is normally derived
endInstruction = null;
}
slot = SLOT_EDEFAULT;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, EmftvmPackage.LOCAL_VARIABLE__END_INSTRUCTION_INDEX, oldEndInstructionIndex, endInstructionIndex));
}
/**
* <!-- begin-user-doc. -->
* {@inheritDoc}
* <!-- end-user-doc -->
* @generated
*/
@Override
public NotificationChain eInverseAdd(InternalEObject otherEnd, int featureID, NotificationChain msgs) {
switch (featureID) {
case EmftvmPackage.LOCAL_VARIABLE__OWNING_BLOCK:
if (eInternalContainer() != null)
msgs = eBasicRemoveFromContainer(msgs);
return basicSetOwningBlock((CodeBlock)otherEnd, msgs);
}
return super.eInverseAdd(otherEnd, featureID, msgs);
}
/**
* <!-- begin-user-doc. -->
* {@inheritDoc}
* <!-- end-user-doc -->
* @generated
*/
@Override
public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs) {
switch (featureID) {
case EmftvmPackage.LOCAL_VARIABLE__OWNING_BLOCK:
return basicSetOwningBlock(null, msgs);
}
return super.eInverseRemove(otherEnd, featureID, msgs);
}
/**
* <!-- begin-user-doc. -->
* {@inheritDoc}
* <!-- end-user-doc -->
* @generated
*/
@Override
public NotificationChain eBasicRemoveFromContainerFeature(NotificationChain msgs) {
switch (eContainerFeatureID()) {
case EmftvmPackage.LOCAL_VARIABLE__OWNING_BLOCK:
return eInternalContainer().eInverseRemove(this, EmftvmPackage.CODE_BLOCK__LOCAL_VARIABLES, CodeBlock.class, msgs);
}
return super.eBasicRemoveFromContainerFeature(msgs);
}
/**
* <!-- begin-user-doc. -->
* {@inheritDoc}
* <!-- end-user-doc -->
* @generated
*/
@Override
public Object eGet(int featureID, boolean resolve, boolean coreType) {
switch (featureID) {
case EmftvmPackage.LOCAL_VARIABLE__SLOT:
return getSlot();
case EmftvmPackage.LOCAL_VARIABLE__OWNING_BLOCK:
return getOwningBlock();
case EmftvmPackage.LOCAL_VARIABLE__START_INSTRUCTION:
if (resolve) return getStartInstruction();
return basicGetStartInstruction();
case EmftvmPackage.LOCAL_VARIABLE__END_INSTRUCTION:
if (resolve) return getEndInstruction();
return basicGetEndInstruction();
case EmftvmPackage.LOCAL_VARIABLE__START_INSTRUCTION_INDEX:
return getStartInstructionIndex();
case EmftvmPackage.LOCAL_VARIABLE__END_INSTRUCTION_INDEX:
return getEndInstructionIndex();
}
return super.eGet(featureID, resolve, coreType);
}
/**
* <!-- begin-user-doc. -->
* {@inheritDoc}
* <!-- end-user-doc -->
* @generated
*/
@Override
public void eSet(int featureID, Object newValue) {
switch (featureID) {
case EmftvmPackage.LOCAL_VARIABLE__SLOT:
setSlot((Integer)newValue);
return;
case EmftvmPackage.LOCAL_VARIABLE__OWNING_BLOCK:
setOwningBlock((CodeBlock)newValue);
return;
case EmftvmPackage.LOCAL_VARIABLE__START_INSTRUCTION:
setStartInstruction((Instruction)newValue);
return;
case EmftvmPackage.LOCAL_VARIABLE__END_INSTRUCTION:
setEndInstruction((Instruction)newValue);
return;
case EmftvmPackage.LOCAL_VARIABLE__START_INSTRUCTION_INDEX:
setStartInstructionIndex((Integer)newValue);
return;
case EmftvmPackage.LOCAL_VARIABLE__END_INSTRUCTION_INDEX:
setEndInstructionIndex((Integer)newValue);
return;
}
super.eSet(featureID, newValue);
}
/**
* <!-- begin-user-doc. -->
* {@inheritDoc}
* <!-- end-user-doc -->
* @generated
*/
@Override
public void eUnset(int featureID) {
switch (featureID) {
case EmftvmPackage.LOCAL_VARIABLE__SLOT:
setSlot(SLOT_EDEFAULT);
return;
case EmftvmPackage.LOCAL_VARIABLE__OWNING_BLOCK:
setOwningBlock((CodeBlock)null);
return;
case EmftvmPackage.LOCAL_VARIABLE__START_INSTRUCTION:
setStartInstruction((Instruction)null);
return;
case EmftvmPackage.LOCAL_VARIABLE__END_INSTRUCTION:
setEndInstruction((Instruction)null);
return;
case EmftvmPackage.LOCAL_VARIABLE__START_INSTRUCTION_INDEX:
setStartInstructionIndex(START_INSTRUCTION_INDEX_EDEFAULT);
return;
case EmftvmPackage.LOCAL_VARIABLE__END_INSTRUCTION_INDEX:
setEndInstructionIndex(END_INSTRUCTION_INDEX_EDEFAULT);
return;
}
super.eUnset(featureID);
}
/**
* <!-- begin-user-doc. -->
* {@inheritDoc}
* <!-- end-user-doc -->
* @generated
*/
@Override
public boolean eIsSet(int featureID) {
switch (featureID) {
case EmftvmPackage.LOCAL_VARIABLE__SLOT:
return getSlot() != SLOT_EDEFAULT;
case EmftvmPackage.LOCAL_VARIABLE__OWNING_BLOCK:
return getOwningBlock() != null;
case EmftvmPackage.LOCAL_VARIABLE__START_INSTRUCTION:
return startInstruction != null;
case EmftvmPackage.LOCAL_VARIABLE__END_INSTRUCTION:
return endInstruction != null;
case EmftvmPackage.LOCAL_VARIABLE__START_INSTRUCTION_INDEX:
return getStartInstructionIndex() != START_INSTRUCTION_INDEX_EDEFAULT;
case EmftvmPackage.LOCAL_VARIABLE__END_INSTRUCTION_INDEX:
return getEndInstructionIndex() != END_INSTRUCTION_INDEX_EDEFAULT;
}
return super.eIsSet(featureID);
}
/**
* <!-- begin-user-doc. -->
* {@inheritDoc}
* <!-- end-user-doc -->
* @generated
*/
public CodeBlock getOwningBlock() {
if (eContainerFeatureID() != EmftvmPackage.LOCAL_VARIABLE__OWNING_BLOCK) return null;
return (CodeBlock)eInternalContainer();
}
/**
* <!-- begin-user-doc. -->
* @see #setOwningBlock(CodeBlock)
* <!-- end-user-doc -->
* @generated
*/
public NotificationChain basicSetOwningBlock(CodeBlock newOwningBlock, NotificationChain msgs) {
msgs = eBasicSetContainer((InternalEObject)newOwningBlock, EmftvmPackage.LOCAL_VARIABLE__OWNING_BLOCK, msgs);
return msgs;
}
/**
* <!-- begin-user-doc. -->
* {@inheritDoc}
* <!-- end-user-doc -->
* @generated
*/
public void setOwningBlock(CodeBlock newOwningBlock) {
if (newOwningBlock != eInternalContainer() || (eContainerFeatureID() != EmftvmPackage.LOCAL_VARIABLE__OWNING_BLOCK && newOwningBlock != null)) {
if (EcoreUtil.isAncestor(this, newOwningBlock))
throw new IllegalArgumentException("Recursive containment not allowed for " + toString());
NotificationChain msgs = null;
if (eInternalContainer() != null)
msgs = eBasicRemoveFromContainer(msgs);
if (newOwningBlock != null)
msgs = ((InternalEObject)newOwningBlock).eInverseAdd(this, EmftvmPackage.CODE_BLOCK__LOCAL_VARIABLES, CodeBlock.class, msgs);
msgs = basicSetOwningBlock(newOwningBlock, msgs);
if (msgs != null) msgs.dispatch();
}
else if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, EmftvmPackage.LOCAL_VARIABLE__OWNING_BLOCK, newOwningBlock, newOwningBlock));
}
/**
* <!-- begin-user-doc. -->
* {@inheritDoc}
* <!-- end-user-doc -->
* @generated NOT
*/
@Override
public String toString() {
return super.toString();
}
} //LocalVariableImpl