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