blob: 6c258eafe77dc42541942207987d0bfbedb6e1e1 [file] [log] [blame]
/*
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.flex.abc.semantics;
/**
* A Label represents the target of a branch instruction; it is not the ABC
* OP_Label instruction. Note: this class has a natural ordering that is
* inconsistent with equals.
*/
public final class Label implements Comparable<Label>, Cloneable
{
/**
* The inital offset of a label. This offset must be set to a known value
* before the Label can be active.
*/
public static final int NO_POSITION = -1;
public Label(String label_text)
{
this(label_text, LabelKind.EXECUTABLE_INSTRUCTION);
}
public Label(String label_text, LabelKind mustTargetExectuable)
{
this.labelText = label_text;
this.mustTargetExecutable = mustTargetExectuable;
}
public Label()
{
this.labelText = null;
}
/**
* copy constructor used by clone()
*/
private Label(Label src)
{
this.instructionPosition = src.instructionPosition;
this.labelText = src.labelText;
}
/**
* Descriptive text for a Label. This is a debugging aid that may be going
* away soon.
*/
private String labelText;
/**
* Does this label have to fall on an executable instruction, or can it fall
* on any old instruction (such as a OP_debugline).
*/
private LabelKind mustTargetExecutable;
/**
* The label's offset in its owning InstructionList.
*
* @see InstructionList#labelFirst()
* @see InstructionList#labelCurrent()
* @see InstructionList#labelNext()
* which does not explicitly set the
* position, but adds the label to the InstructionList's pendingLabels set,
* which will convert the label to an active state with a known position
* when the next instruction is added to the list.
*/
private int instructionPosition = NO_POSITION;
/**
* The natural sort order for a Label is its instruction's offset.
* <p>
* @note Comparison is only valid between two Labels in the same
* InstructionList.
*/
@Override
public int compareTo(Label o)
{
return this.instructionPosition - o.instructionPosition;
}
@Override
public String toString()
{
return labelText != null ? labelText : super.toString() + " => " + instructionPosition;
}
/**
* Set this Label's offset in its initial InstructionList.
*
* @see #adjustOffset
* , which the InstructionList keeps this position updated.
* @param pos - the Label's offset in the InstructionList.
*/
public void setPosition(int pos)
{
assert (this.instructionPosition == NO_POSITION) : "setPostition() after a position set: " + toString();
this.instructionPosition = pos;
}
/**
* @return this Label's offset in its owning InstructionList.
*/
public int getPosition()
{
return this.instructionPosition;
}
/**
* This Label has been inherited by a new InstructionList, so its offset
* must be adjusted to point to its new position within the inheriting
* InstructionList. (Or, the owning InstructionList's order was perturbed by
* a prepend() or similar ad-hoc adjustment.)
*
* @param base_offset - the amount to adjust the position. Think of the
* position as a displacement, and the inherting list's size as a base.
*/
public void adjustOffset(int base_offset)
{
assert (this.instructionPosition != NO_POSITION) : "adjustOffset() before any position set";
this.instructionPosition += base_offset;
}
/**
* Clone this label.
*
* @return a shallow copy of the label (it doesn't have any deep state).
*/
@Override
public Object clone()
{
return new Label(this);
}
/**
* Does this label have to fall on an executable instruction, or can it fall
* on any old instruction (such as a OP_debugline).
*/
public boolean targetMustBeExecutable()
{
return this.mustTargetExecutable == LabelKind.EXECUTABLE_INSTRUCTION;
}
public static enum LabelKind
{
// The label must label an executable instruction
EXECUTABLE_INSTRUCTION,
// the label may target any instruction, even a debug one
ANY_INSTRUCTION
}
}