diff options
author | paltherr <paltherr@epfl.ch> | 2004-02-26 16:41:25 +0000 |
---|---|---|
committer | paltherr <paltherr@epfl.ch> | 2004-02-26 16:41:25 +0000 |
commit | 5b778f324f0f6ad0cc656afa7b951589e771a41d (patch) | |
tree | 5ade5c963c00943247012a1a9ec1feb86683425b | |
parent | 2fae19f844c7645895ed89a2f30de924ece401a2 (diff) | |
download | scala-5b778f324f0f6ad0cc656afa7b951589e771a41d.tar.gz scala-5b778f324f0f6ad0cc656afa7b951589e771a41d.tar.bz2 scala-5b778f324f0f6ad0cc656afa7b951589e771a41d.zip |
- Added History.java and Promise.java
-rw-r--r-- | config/list/compiler.lst | 3 | ||||
-rw-r--r-- | sources/scalac/framework/History.java | 277 | ||||
-rw-r--r-- | sources/scalac/framework/Promise.java | 70 |
3 files changed, 350 insertions, 0 deletions
diff --git a/config/list/compiler.lst b/config/list/compiler.lst index 50868c219f..65c2710ebf 100644 --- a/config/list/compiler.lst +++ b/config/list/compiler.lst @@ -68,6 +68,9 @@ checkers/CheckTypes.java checkers/Checker.java checkers/TreeChecker.java +framework/History.java +framework/Promise.java + symtab/classfile/AttributeParser.java symtab/classfile/CLRPackageParser.java symtab/classfile/CLRClassParser.java diff --git a/sources/scalac/framework/History.java b/sources/scalac/framework/History.java new file mode 100644 index 0000000000..ce0800358d --- /dev/null +++ b/sources/scalac/framework/History.java @@ -0,0 +1,277 @@ +/* ____ ____ ____ ____ ______ *\ +** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** +** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** +** /_____/\____/\___/\____/____/ ** +\* */ + +// $Id$ + +package scalac.framework; + +import scalac.Global; +import scalac.Phase; +import scalac.util.Debug; + +/** + * This class implements a value history. It stores phase dependent + * values. + * + * Implementation: the value "values[n]" is valid from start of phase + * "starts[n]" to end of phase "(n == 0 ? limit : starts[n-1].prev)" + * and the promised value "next" is valid from start of phase + * "limit.next". + */ +public class History { + + //######################################################################## + // Private Constants + + /** An empty array of objects */ + private static final Object[] NO_VALUES = new Object[0]; + + /** An empty array of phases */ + private static final Phase[] NO_STARTS = new Phase[0]; + + //######################################################################## + // Private Fields + + /** The global environment */ + private final Global global; + + /** The successive values of this history */ + private Object[] values; + + /** The start phases of the successive values */ + private Phase[] starts; + + /** The last known valid phase of the last value */ + private Phase limit; + + /** A promise of the next value (may be null) */ + private Promise next; + + //######################################################################## + // Public Constructors + + /** Initializes this instance with current phase as first one. */ + public History() { + this(Global.instance); + } + + /** Initializes this instance with current phase as first one. */ + public History(Global global) { + this(global, global.currentPhase); + } + + /** Initializes this instance with given first phase. */ + public History(Phase first) { + this(first.global, first); + } + + /** Initializes this instance with given first phase. */ + public History(Global global, Phase first) { + this.global = global; + reset(first); + } + + //######################################################################## + // Public Methods + + /** Returns the first phase of this history. */ + public final Phase getFirstPhase() { + return starts.length > 0 ? starts[starts.length - 1] : limit.next; + } + + /** Returns the value at current phase. */ + public final Object getValue(Object owner) { + return getValueAt(owner, getPhase()); + } + + /** Returns the value at next phase. */ + public final Object getNextValue(Object owner) { + return getValueAt(owner, getNextPhase()); + } + + /** Returns the value at given phase. */ + public final Object getValueAt(Object owner, Phase phase) { + assert phase != null: show(owner, phase); + while (limit.id < phase.id) incrementLimit(owner); + for (int i = 0; i < starts.length; i++) + if (starts[i].id <= phase.id) return values[i]; + throw Debug.abort("prehistoric phase", show(owner, phase)); + } + + /** Sets the value at current phase. */ + public final History setValue(Object owner, Object value) { + return setValueAt(owner, getPhase(), value); + } + + /** Sets the value at next phase. */ + public final History setNextValue(Object owner, Object value) { + return setValueAt(owner, getNextPhase(), value); + } + + /** Sets the value at given phase. */ + public final History setValueAt(Object owner, Phase phase, Object value) { + assert phase != null: show(owner, phase); + assert phase == limit.next && next == null: show(owner, phase); + if (values.length == 0 || values[0] != value) { + this.values = append(value, values); + this.starts = append(phase, starts); + } + this.limit = phase; + return this; + } + + /** Sets a value promise at current phase. */ + public final History setPromise(Object owner, Promise promise) { + return setPromiseAt(owner, getPhase(), promise); + } + + /** Sets a value promise at next phase. */ + public final History setNextPromise(Object owner, Promise promise) { + return setPromiseAt(owner, getNextPhase(), promise); + } + + /** Sets a value promise at given phase. */ + public final History setPromiseAt(Object owner, Phase phase, + Promise promise) + { + assert phase != null: show(owner, phase); + assert phase == limit.next && next == null: show(owner, phase); + this.next = promise; + return this; + } + + /** Erases all values. */ + public final void reset() { + reset(getFirstPhase()); + } + + /** Erases all values and sets first phase to given one. */ + public final void reset(Phase first) { + assert first != null && first.prev != null: this + " - " + first; + this.values = NO_VALUES; + this.starts = NO_STARTS; + this.limit = first.prev; + this.next = null; + } + + /** Returns a string representation of this history. */ + public String toString() { + StringBuffer buffer = new StringBuffer("["); + for (int i = 0; i < values.length; i++) { + buffer.append(starts[i]).append(" -> "); + buffer.append(Debug.show(values[i])).append(", "); + } + buffer.append(limit); + if (next != null) buffer.append(" - ").append(next); + return buffer.append("]").toString(); + } + + //######################################################################## + // Protected Methods + + /** + * Computes the value at phase following given one by transforming + * the given value (which is the value at given phase). The + * default implementation changes the current phase to given one + * and then forwards the call to method "transformValue". + */ + protected Object transformValueAt(Object owner, Phase phase, Object value){ + Phase current = global.currentPhase; + global.currentPhase = phase; + Object result = transformValue(owner, value); + global.currentPhase = current; + return result; + } + + /** + * Computes the value at next phase by transforming the given + * value (which is the value at current phase). The default + * implementation forwards the call to method "computeValueAt". + */ + protected Object transformValue(Object owner, Object value) { + return computeValueAt(owner, global.currentPhase.next); + } + + /** + * Computes the value at given phase. The default implementation + * changes the current phase to given one and then forwards the + * call to method "computeValue". + */ + protected Object computeValueAt(Object owner, Phase phase) { + Phase current = global.currentPhase; + global.currentPhase = phase; + Object result = computeValue(owner); + global.currentPhase = current; + return result; + } + + /** + * Computes the value at current phase. The default implementation + * throws an exception. + */ + protected Object computeValue(Object owner) { + throw Debug.abort("undefined value", show(owner, getPhase())); + } + + //######################################################################## + // Private Methods + + /** Returns the current phase. */ + private Phase getPhase() { + return global.currentPhase; + } + + /** Returns the next phase. */ + private Phase getNextPhase() { + return getPhase().next; + } + + /** Increments the limit of this history. */ + private void incrementLimit(Object owner) { + Phase phase = limit; + Object value; + if (next != null) { + value = next.forceAt(owner, global, phase.next); + if (limit == phase) next = null; + } else if (values.length > 0) { + value = transformValueAt(owner, phase, values[0]); + } else { + value = computeValueAt(owner, phase.next); + } + if (limit == phase) setValueAt(owner, phase.next, value); + } + + /** Returns a string of this history and given owner. */ + private String show(Object owner) { + return this + " @ " + Debug.show(owner); + } + + /** Returns a string of this history and given owner and phase. */ + private String show(Object owner, Phase phase) { + return show(owner) + " - " + phase; + } + + //######################################################################## + // Private Functions + + /** Returns the concatenation of given values. */ + private static Object[] append(Object value, Object[] values) { + Object[] array = new Object[1 + values.length]; + array[0] = value; + for (int i = 1; i < array.length; i++) array[i] = values[i - 1]; + return array; + } + + /** Returns the concatenation of given phases. */ + private static Phase[] append(Phase phase, Phase[] phases) { + Phase[] array = new Phase[1 + phases.length]; + array[0] = phase; + for (int i = 1; i < array.length; i++) array[i] = phases[i - 1]; + return array; + } + + //######################################################################## +} diff --git a/sources/scalac/framework/Promise.java b/sources/scalac/framework/Promise.java new file mode 100644 index 0000000000..7a1a521512 --- /dev/null +++ b/sources/scalac/framework/Promise.java @@ -0,0 +1,70 @@ +/* ____ ____ ____ ____ ______ *\ +** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** +** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** +** /_____/\____/\___/\____/____/ ** +\* */ + +// $Id$ + +package scalac.framework; + +import scalac.Global; +import scalac.Phase; + +/** + * This abstract class represents a value promise (a lazy value). The + * promised value is obtained by invoking the method "force" which + * will detect any cyclic definition. Note that this class does not + * store evaluated values. Therefore, successive calls to "force" will + * trigger successive evaluations of the promise. + */ +public abstract class Promise { + + //######################################################################## + // Private Fields + + /** The current number of evaluation cycles */ + private int cycles; + + //######################################################################## + // Public Methods + + /** Forces this promise and returns its value. */ + public final Object force(Object owner) { + int cycles = this.cycles; + this.cycles++; + Object value = cycles > 0 + ? evaluate(owner) + : getCyclicValue(owner, cycles); + this.cycles--; + return value; + } + + /** Forces this promise at given phase and returns its value. */ + public final Object forceAt(Object owner, Global global, Phase phase) { + Phase current = global.currentPhase; + global.currentPhase = phase; + Object value = force(owner); + global.currentPhase = current; + return value; + } + + //######################################################################## + // Protected Methods + + /** + * Evaluates this promise. This method is invoked by non-cyclic + * calls to the method "force". + */ + protected abstract Object evaluate(Object owner); + + /** + * Returns the value to use in case of a cyclic definition. This + * method is invoked by cyclic calls to the method "force". The + * current (strictly positive) number of cycles is passed as an + * argument. + */ + protected abstract Object getCyclicValue(Object owner, int cycles); + + //######################################################################## +} |