summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpaltherr <paltherr@epfl.ch>2005-01-03 12:40:31 +0000
committerpaltherr <paltherr@epfl.ch>2005-01-03 12:40:31 +0000
commitbd170a6e74e5f4965442a17dab98b46c938491ca (patch)
treee6983cb391671df0651b88b90b05de32a242ffb2
parent89d9f33d8fd4adea0d643c129b6600e31ca8c0e2 (diff)
downloadscala-bd170a6e74e5f4965442a17dab98b46c938491ca.tar.gz
scala-bd170a6e74e5f4965442a17dab98b46c938491ca.tar.bz2
scala-bd170a6e74e5f4965442a17dab98b46c938491ca.zip
- Introduced new compilation loop
-rw-r--r--config/list/scalac.lst1
-rw-r--r--sources/scala/tools/scalac/Global.scala23
-rw-r--r--sources/scala/tools/scalac/typechecker/Analyzer.scala15
-rw-r--r--sources/scala/tools/scalac/typechecker/AnalyzerPhase.scala20
-rw-r--r--sources/scala/tools/scaladoc/ScalaSearch.java4
-rw-r--r--sources/scalac/CompilationLoop.java143
-rw-r--r--sources/scalac/Global.java46
-rw-r--r--sources/scalac/typechecker/AnalyzerPhase.java2
8 files changed, 186 insertions, 68 deletions
diff --git a/config/list/scalac.lst b/config/list/scalac.lst
index 1bbf495f71..284b884da1 100644
--- a/config/list/scalac.lst
+++ b/config/list/scalac.lst
@@ -9,6 +9,7 @@
../../../scalac/Global.java
../../../scalac/Phase.java
../../../scalac/PhaseDescriptor.java
+../../../scalac/CompilationLoop.java
../../../scalac/CompilationUnit.java
../../../scalac/ast/DefaultTreeFactory.java
diff --git a/sources/scala/tools/scalac/Global.scala b/sources/scala/tools/scalac/Global.scala
index 4ed46cfb22..d55a2ecafa 100644
--- a/sources/scala/tools/scalac/Global.scala
+++ b/sources/scala/tools/scalac/Global.scala
@@ -10,6 +10,8 @@ import scalac.{CompilationUnit, CompilerCommand, Global => scalac_Global};
import scalac.ast.printer.TreePrinter;
import scalac.backend.jvm.GenJVM;
import scalac.backend.msil.GenMSIL;
+import scalac.symtab.Symbol;
+import scalac.util.Debug;
import scala.tools.scalac.backend.GenJVMFromICode;
package scala.tools.scalac {
@@ -45,5 +47,26 @@ class Global(args: CompilerCommand, interpret: boolean) extends scalac_Global(ar
symdata.clear();
}
+
+ protected override def loadFunctions(): Unit = {
+ val mixinOnly = target != scalac_Global.TARGET_INT;
+ List.range(0, definitions.FUNCTION_COUNT).foreach(
+ i => loadCode(definitions.FUNCTION_CLASS(i), mixinOnly));
+ }
+
+ private def loadCode(clasz: Symbol, mixinOnly: boolean): unit = {
+ assert(clasz.isClass() && !clasz.isModuleClass(), Debug.show(clasz));
+ if (clasz.isExternal()) {
+ try {
+ compileLate(getSourceFile(clasz), mixinOnly);
+ } catch {
+ case exception: java.io.IOException =>
+ if (debug) exception.printStackTrace();
+ error(exception.getMessage() + "; source file for "
+ + clasz + " is needed");
+ }
+ }
+ }
+
}
}
diff --git a/sources/scala/tools/scalac/typechecker/Analyzer.scala b/sources/scala/tools/scalac/typechecker/Analyzer.scala
index aa15d05f9b..fdb292bc5f 100644
--- a/sources/scala/tools/scalac/typechecker/Analyzer.scala
+++ b/sources/scala/tools/scalac/typechecker/Analyzer.scala
@@ -78,7 +78,6 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
def lateEnter(unit: CompilationUnit): unit = {
enterUnit(unit);
- descr.newSources.add(unit);
}
def loadMixinCode(pos: Int, clasz: Symbol): unit = {
@@ -95,20 +94,6 @@ class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(
}
}
- def loadCode(clasz: Symbol, mixinOnly: boolean): unit = {
- assert(clasz.isClass() && !clasz.isModuleClass(), Debug.show(clasz));
- if (clasz.isExternal()) {
- try {
- global.compileLate(global.getSourceFile(clasz), mixinOnly);
- } catch {
- case exception: java.io.IOException =>
- if (global.debug) exception.printStackTrace();
- global.error(exception.getMessage() + "; source file for "
- + clasz + " is needed");
- }
- }
- }
-
override def apply(unit: CompilationUnit): unit = {
global.log("checking " + unit);
assert(this.unit == null, "start unit non null for " + unit);
diff --git a/sources/scala/tools/scalac/typechecker/AnalyzerPhase.scala b/sources/scala/tools/scalac/typechecker/AnalyzerPhase.scala
index 8da9db017d..288b2e0e3f 100644
--- a/sources/scala/tools/scalac/typechecker/AnalyzerPhase.scala
+++ b/sources/scala/tools/scalac/typechecker/AnalyzerPhase.scala
@@ -63,23 +63,6 @@ class AnalyzerPhase(global: scalac_Global, descriptor: PhaseDescriptor) extends
startContext);
val contexts = new HashMap/*<CompilationUnit,Context>*/();
- val newSources = new ArrayList/*<CompilationUnit>*/();
-
- override def getUnits(): Array[CompilationUnit] = {
- val analyzer = new Analyzer(global, this);
- val mixinOnly = global.target != Global.TARGET_INT;
- List.range(0, global.definitions.FUNCTION_COUNT).foreach(
- i => analyzer.loadCode(global.definitions.FUNCTION_CLASS(i), mixinOnly));
- var n = 0;
- while (n < newSources.size()) {
- analyzer.apply(newSources.get(n).asInstanceOf[CompilationUnit]);
- n = n + 1;
- }
- val array = new Array[CompilationUnit](newSources.size());
- newSources.toArray(array.asInstanceOf[Array[Object]]);
- newSources.clear();
- array
- }
override def addConsoleImport(module: Symbol): unit =
consoleContext = addImport(consoleContext, module);
@@ -93,7 +76,8 @@ class AnalyzerPhase(global: scalac_Global, descriptor: PhaseDescriptor) extends
c
}
- override def apply(unit: CompilationUnit): Unit = ();
+ override def apply(unit: CompilationUnit): Unit =
+ new Analyzer(global, this).apply(unit);
}
}
diff --git a/sources/scala/tools/scaladoc/ScalaSearch.java b/sources/scala/tools/scaladoc/ScalaSearch.java
index 1a2e741c7c..1d2f423eff 100644
--- a/sources/scala/tools/scaladoc/ScalaSearch.java
+++ b/sources/scala/tools/scaladoc/ScalaSearch.java
@@ -551,10 +551,8 @@ public class ScalaSearch {
SourceFile sourceFile = global.getSourceFile("tmp.scala", unitString);
CompilationUnit tmpUnit = new CompilationUnit(global, sourceFile, false);
tmpUnit.body = new Parser$class(tmpUnit).parse();
-
+ global.PHASE.NAMER.phase().apply(tmpUnit);
global.PHASE.ANALYZER.phase().apply(tmpUnit);
- ((scalac.typechecker.AnalyzerPhase)global.PHASE.ANALYZER.phase())
- .getUnits(); // force completion of type analysis
if (global.reporter.errors() == errorNumber) {
Scope tmpScope = tmpUnit.body[0].symbol().members();
Type res = tmpScope.lookup(Name.fromString("f")).type();
diff --git a/sources/scalac/CompilationLoop.java b/sources/scalac/CompilationLoop.java
new file mode 100644
index 0000000000..00cf6a576a
--- /dev/null
+++ b/sources/scalac/CompilationLoop.java
@@ -0,0 +1,143 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+\* */
+
+// $Id$
+
+package scalac;
+
+import java.util.ArrayList;
+
+import scalac.util.Debug;
+
+/** This class implements the scalac compilation loop. */
+public class CompilationLoop {
+
+ //########################################################################
+ // Private Fields
+
+ /** The global environment */
+ private final Global global;
+ /** The list of active phases */
+ private final Phase[] phases;
+ /** The units currently associated to each active phase. */
+ private final ArrayList/*<CompilationUnit>*/[] unitss;
+ /** The indexes of the first units that are not yet processed. */
+ private final int[] indexes;
+
+ //########################################################################
+ // Private Constructors
+
+ /** Initializes this instance. */
+ public CompilationLoop(Global global) {
+ this.global = global;
+ int count = 0;
+ for (Phase p = global.PHASE.INITIAL.phase(); p != null; p = p.next)
+ count++;
+ this.phases = new Phase[count];
+ this.unitss = new ArrayList[count];
+ this.indexes = new int[count];
+ Phase phase = global.PHASE.INITIAL.phase();
+ for (int i = 0; i < count; i++) {
+ phases[i] = phase;
+ unitss[i] = new ArrayList();
+ phase = phase.next;
+ }
+ }
+
+ //########################################################################
+ // Public Methods
+
+ /**
+ * Compiles the given units and returns list of all compiled units
+ * including those loaded automatically.
+ */
+ public CompilationUnit[] compile(CompilationUnit[] units) {
+ for (int i = 0; i < units.length; i++) unitss[0].add(units[i]);
+ int limit = phases.length - 1;
+ loop(limit, true);
+ return global.reporter.errors() != 0
+ ? new CompilationUnit[0]
+ : (CompilationUnit[])unitss[limit].toArray(
+ new CompilationUnit[unitss[limit].size()]);
+ }
+
+ /**
+ * Inserts the given unit and compiles it up to the current phase
+ * excluded.
+ */
+ public void insert(CompilationUnit unit) {
+ Phase backup = global.currentPhase;
+ unitss[0].add(unit);
+ // !!! This "false" may be dangerous; it may lead to crashes
+ // because phases might work on trees/symbol-tables that
+ // contain errors (however this occurs only if the newly
+ // loaded code may contain errors). On the other hand "true",
+ // might starve some phases; if a phase requests a compilation
+ // unit, it may never receive it.
+ loop(getPhaseIndex(backup), false);
+ global.currentPhase = backup;
+ }
+
+ //########################################################################
+ // Private Methods
+
+ /** Compiles all units up to phase "phases[limit]" excluded. */
+ private void loop(int limit, boolean main) {
+ assert limit < phases.length: Debug.show(""+limit, phases);
+ for (int current = getFirstNonEmptyIndex(); current < limit; ) {
+ // !!! remove NAMER test ?
+ if (main && global.reporter.errors() != 0
+ && global.currentPhase != global.PHASE.NAMER.phase()) break;
+ // Update the current phase pointer.
+ Phase phase = global.currentPhase = phases[current];
+ // If the phase is not yet started, start it.
+ if (indexes[current] == 0) global.start();
+ // Apply the phase to all available units. It's important
+ // to not cache the result of "size()" as new units may be
+ // added during the loop.
+ for (int i = indexes[current]; i < unitss[current].size(); i++)
+ phase.apply((CompilationUnit)unitss[current].get(i));
+ int next = getFirstNonEmptyIndex();
+ // If no new units were introduced, stop the phase.
+ if (next == current) {
+ PhaseDescriptor descriptor = phase.descriptor;
+ global.stop(descriptor.taskDescription());
+ CompilationUnit[] units =
+ (CompilationUnit[])unitss[current].toArray(
+ new CompilationUnit[unitss[current].size()]);
+ if (descriptor.hasPrintFlag()) global.print(units);
+ // if (descriptor.hasGraphFlag()); // !!!
+ // if (descriptor.hasCheckFlag()); // !!!
+ if (phase == global.PHASE.PARSER.phase()) global.fix1(units);
+ if (phase == global.PHASE.ANALYZER.phase()) global.fix2(units);
+ unitss[current + 1].addAll(unitss[current]);
+ unitss[current].clear();
+ next++;
+ }
+ indexes[current] = unitss[current].size();
+ current = next;
+ }
+ }
+
+ /**
+ * Returns the first index with a non-empty unit list. If there is
+ * no such index, returns "phases.length".
+ */
+ private int getFirstNonEmptyIndex() {
+ int index = 0;
+ while (index < phases.length && unitss[index].isEmpty()) index++;
+ return index;
+ }
+
+ /** Returns the index of the given phase. */
+ private int getPhaseIndex(Phase phase) {
+ for (int index = 0; index < phases.length; index++)
+ if (phases[index] == phase) return index;
+ throw Debug.abort("phase not found", Debug.show(phase, phases));
+ }
+
+ //########################################################################
+}
diff --git a/sources/scalac/Global.java b/sources/scalac/Global.java
index 426f59af59..b6c039c495 100644
--- a/sources/scalac/Global.java
+++ b/sources/scalac/Global.java
@@ -157,6 +157,9 @@ public abstract class Global {
*/
public final CompilerPhases PHASE;
+ /** The current compilation loop or null */
+ private CompilationLoop loop;
+
/** compilation targets
*/
public static final String TARGET_INT;
@@ -381,26 +384,12 @@ public abstract class Global {
/** compile all compilation units
*/
private CompilationUnit[] compile(CompilationUnit[] units) {
+ this.currentPhase = PHASE.INITIAL.phase();
treePrinter.begin();
-
- currentPhase = PHASE.INITIAL.phase();
- // apply successive phases and pray that it works
- // !!! remove NAMER test ?
- while (currentPhase.next != null && ((currentPhase == PHASE.NAMER.phase()) || (reporter.errors() == 0))) {
- currentPhase = currentPhase.next;
- start();
- // System.out.println("*** " + currentPhase.descriptor.description() + " ***");
- for (int i = 0; i < units.length; i++)
- currentPhase.apply(units[i]);
- if (currentPhase == PHASE.ANALYZER.phase())
- units = ((AnalyzerPhase)currentPhase).getUnits();
- stop(currentPhase.descriptor.taskDescription());
- if (currentPhase.descriptor.hasPrintFlag()) print(units);
- // if (currentPhase.descriptor.hasGraphFlag()) // !!!
- // if (currentPhase.descriptor.hasCheckFlag()) // !!!
- if (currentPhase == PHASE.PARSER.phase()) fix1(units);
- if (currentPhase == PHASE.ANALYZER.phase()) fix2(units);
- }
+ this.loop = new CompilationLoop(this);
+ loadFunctions();
+ units = loop.compile(units);
+ this.loop = null;
if (reporter.errors() != 0) {
imports.clear();
for (Iterator i = compiledNow.entrySet().iterator(); i.hasNext();) {
@@ -412,28 +401,25 @@ public abstract class Global {
}
compiledNow.clear();
treePrinter.end();
+ this.currentPhase = PHASE.TERMINAL.phase();
return units;
}
+ protected abstract void loadFunctions();
+
/** Compiles an additional source file. */
public void compileLate(SourceFile source, boolean mixinOnly) {
+ assert loop != null: source;
if (!compiledUnits.contains(source)) {
compiledUnits.add(source);
CompilationUnit unit = new CompilationUnit(this, source, false, mixinOnly);
- Phase backup = currentPhase;
- // !!! add code to print/skip/graph as in compile
- currentPhase = PHASE.PARSER.phase();
- PHASE.PARSER.phase().apply(unit);
- currentPhase = PHASE.NAMER.phase();
- PHASE.NAMER.phase().apply(unit);
- // !!! add code for later phases?
- currentPhase = backup;
+ loop.insert(unit);
}
}
public abstract void dump(CompilationUnit[] units);
- private void print(CompilationUnit[] units) {
+ void print(CompilationUnit[] units) {
if (currentPhase.id == PHASE.MAKEBOXINGEXPLICIT.id()) {
boolean html = args.printer.value.equals(PRINTER_HTML);
if (html) writer.println("<pre>");
@@ -503,7 +489,7 @@ public abstract class Global {
private List imports = new ArrayList();
public Symbol console;
- private void fix1(CompilationUnit[] units) {
+ void fix1(CompilationUnit[] units) {
for (int i = 0; i < units.length; i++) {
if (units[i].console) fix1(units[i]);
}
@@ -529,7 +515,7 @@ public abstract class Global {
module++;
}
- private void fix2(CompilationUnit[] units) {
+ void fix2(CompilationUnit[] units) {
for (int i = 0; i < units.length; i++) {
if (units[i].console) fix2(units[i]);
}
diff --git a/sources/scalac/typechecker/AnalyzerPhase.java b/sources/scalac/typechecker/AnalyzerPhase.java
index 0939806844..de47aae6c2 100644
--- a/sources/scalac/typechecker/AnalyzerPhase.java
+++ b/sources/scalac/typechecker/AnalyzerPhase.java
@@ -29,6 +29,4 @@ public abstract class AnalyzerPhase extends Phase {
public abstract void addConsoleImport(Symbol module);
- public abstract CompilationUnit[] getUnits();
-
}