001: // Copyright (c) 1997, 2004 Per M.A. Bothner.
002: // This is free software; for terms and warranty disclaimer see ./COPYING.
003:
004: package gnu.bytecode;
005:
006: public class Scope {
007: /** The enclosing scope. */
008: Scope parent;
009: Scope nextSibling;
010: Scope firstChild, lastChild;
011:
012: /** If true, don't call freeLocal on our variables (yet). */
013: boolean preserved;
014:
015: Label start;
016: Label end;
017: Variable vars;
018: Variable last_var;
019:
020: public Scope() {
021: }
022:
023: public Scope(Label start, Label end) {
024: this .start = start;
025: this .end = end;
026: }
027:
028: // Variable lookup (String name);
029: public final Variable firstVar() {
030: return vars;
031: }
032:
033: public VarEnumerator allVars() {
034: return new VarEnumerator(this );
035: }
036:
037: /** Link this scope as the next child of its parent scope. */
038: public void linkChild(Scope parent) {
039: this .parent = parent;
040: if (parent == null)
041: return;
042: if (parent.lastChild == null)
043: parent.firstChild = this ;
044: else
045: parent.lastChild.nextSibling = this ;
046: parent.lastChild = this ;
047: }
048:
049: public Variable addVariable(CodeAttr code, Type type, String name) {
050: Variable var = new Variable(name, type);
051: addVariable(code, var);
052: return var;
053: }
054:
055: public void addVariable(Variable var) {
056: if (last_var == null)
057: vars = var;
058: else
059: last_var.next = var;
060: last_var = var;
061: var.scope = this ;
062: }
063:
064: /* Add a new Variable, linking it in after a given Variable, */
065: public void addVariableAfter(Variable prev, Variable var) {
066: if (prev == null) { // Put first
067: var.next = vars;
068: vars = var;
069: } else {
070: var.next = prev.next;
071: prev.next = var;
072: }
073: if (last_var == prev)
074: last_var = var;
075: if (var.next == var)
076: throw new Error("cycle");
077: var.scope = this ;
078: }
079:
080: public void addVariable(CodeAttr code, Variable var) {
081: addVariable(var);
082: if (var.isSimple() && code != null)
083: var.allocateLocal(code);
084: }
085:
086: /**
087: * Return a variable the scope, by numerical index.
088: * @param index the number of the variable
089: */
090: public Variable getVariable(int index) {
091: Variable var = vars;
092: while (--index >= 0)
093: var = var.next;
094: return var;
095: }
096:
097: static boolean equals(byte[] name1, byte[] name2) {
098: if (name1.length != name2.length)
099: return false;
100: if (name1 == name2)
101: return true;
102: for (int i = name1.length; --i >= 0;)
103: if (name1[i] != name2[i])
104: return false;
105: return true;
106: }
107:
108: public void setStartPC(CodeAttr code) {
109: start = code.getLabel();
110: }
111:
112: /**
113: * Search by name for a Variable in this Scope (only).
114: * @param name name to search for
115: * @return the Variable, or null if not found (in this scope).
116: */
117: public Variable lookup(String name) {
118: for (Variable var = vars; var != null; var = var.next) {
119: if (name.equals(var.name))
120: return var;
121: }
122: return null;
123: }
124:
125: /** Make local variable slots of this scope availabel for re-use.
126: * However, if the 'preserved' flag is set, defer doing so until
127: * we exit a non-preserved Scope. */
128: void freeLocals(CodeAttr code) {
129: if (preserved)
130: return;
131: for (Variable var = vars; var != null; var = var.next) {
132: if (var.isSimple() && !var.dead())
133: var.freeLocal(code);
134: }
135: for (Scope child = firstChild; child != null; child = child.nextSibling) {
136: if (child.preserved) {
137: child.preserved = false;
138: child.freeLocals(code);
139: }
140: }
141: }
142: };
|