From 90962407e72d88f8f3249ade0f6bd60ff15af5ce Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 6 Dec 2012 14:06:00 +0100 Subject: Initial commit --- src/dotty/tools/dotc/core/Periods.scala | 99 +++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 src/dotty/tools/dotc/core/Periods.scala (limited to 'src/dotty/tools/dotc/core/Periods.scala') diff --git a/src/dotty/tools/dotc/core/Periods.scala b/src/dotty/tools/dotc/core/Periods.scala new file mode 100644 index 000000000..61dedb015 --- /dev/null +++ b/src/dotty/tools/dotc/core/Periods.scala @@ -0,0 +1,99 @@ +package dotty.tools.dotc.core + +import Contexts._ + +/** Periods are the central "clock" of the compiler. + * A period consists of a run id and a phase id. + * run ids represent compiler runs + * phase ids represent compiler phases + */ +abstract class Periods { self: Context => + import Periods._ + + /** The current phase identifier */ + def phaseId = phaseIdOf(period) + + /** The current run identifier */ + def runId = runIdOf(period) + + /** A new context that differs from the current one in its period */ + def withPeriod(pd: Period): Context = + if (period == pd) this + else new SubContext(self) { + override val period = pd + } + + /** Execute `op` at given period */ + def atPeriod[T](pd: Period)(op: Context => T)(implicit ctx: Context) = + op(ctx withPeriod pd) + + /** Execute `op` at given phase id */ + def atPhase[T](pid: PhaseId)(op: Context => T)(implicit ctx: Context) = + op(ctx withPeriod periodOf(period, pid)) +} + +object Periods { + + /** A period is an ordinal number for a phase in a run. + * Phases in later runs have higher periods than phases in earlier runs. + * Later phases have higher periods than earlier phases in the same run. + * Periods are coded (in big endian) as: + * + * sign, always 0 1 bit + * runid 21 bits + * phase id: 5 bits + * unused: 5 bits + */ + type Period = Int + final val NoPeriod = 0 + + /** A period interval is an interval between two periods that share the same runid. + * It is coded as follows: + * + * sign, always 0 1 bit + * runid 21 bits + * last phase id: 5 bits + * #phases before last: 5 bits + */ + type Interval = Int + final val Nowhere = NoPeriod + + /** An ordinal number for compiler runs. First run has number 1. */ + type RunId = Int + final val NoRunId = 0 + + /** An ordinal number for phases. First phase has number 1. */ + type PhaseId = Int + final val NoPhaseId = 0 + final val FirstPhaseId = 1 + + /** The number of bits needed to encode a phase identifier. */ + final val PhaseWidth = 5 + final val PhaseMask = (1 << PhaseWidth) - 1 + + /** The run identifier of the given period. */ + final def runIdOf(period: Period): RunId = period >>> (PhaseWidth * 2) + + /** The phase identifier of the given period. */ + final def phaseIdOf(period: Period): PhaseId = (period >>> PhaseWidth) & PhaseMask + + /** The last phase of the given interval */ + final def lastPhaseIdOf(ivl: Interval) = phaseIdOf(ivl) + + /** The first phase of the given interval */ + final def firstPhaseIdOf(ivl: Interval) = lastPhaseIdOf(ivl) - (ivl & PhaseMask) + + /** Does given interval contain given period */ + final def containsPeriod(ivl: Interval, period: Period): Boolean = + ((ivl - period) >>> PhaseWidth) <= (ivl & PhaseMask) + + final def intervalsOverlap(ivl1: Interval, ivl2: Interval): Boolean = ??? + + /** The period consisting of given run id and phase id */ + final def periodOf(rid: RunId, pid: PhaseId): Period = + ((rid << PhaseWidth) | pid) << PhaseWidth + + /** The interval consisting of given run id, and lo/hi phase ids */ + final def intervalOf(rid: RunId, loPid: PhaseId, hiPid: PhaseId): Interval = + periodOf(rid, hiPid) | (hiPid - loPid) +} \ No newline at end of file -- cgit v1.2.3