| /* |
| * |
| * 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 |
| } |
| } |