From bd170a6e74e5f4965442a17dab98b46c938491ca Mon Sep 17 00:00:00 2001 From: paltherr Date: Mon, 3 Jan 2005 12:40:31 +0000 Subject: - Introduced new compilation loop --- config/list/scalac.lst | 1 + sources/scala/tools/scalac/Global.scala | 23 ++++ .../scala/tools/scalac/typechecker/Analyzer.scala | 15 --- .../tools/scalac/typechecker/AnalyzerPhase.scala | 20 +-- sources/scala/tools/scaladoc/ScalaSearch.java | 4 +- sources/scalac/CompilationLoop.java | 143 +++++++++++++++++++++ sources/scalac/Global.java | 46 +++---- sources/scalac/typechecker/AnalyzerPhase.java | 2 - 8 files changed, 186 insertions(+), 68 deletions(-) create mode 100644 sources/scalac/CompilationLoop.java 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/**/(); - val newSources = new ArrayList/**/(); - - 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/**/[] 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("
");
@@ -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();
-
 }
-- 
cgit v1.2.3