| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,354 @@ | ||
| /* ____ ____ ____ ____ ______ *\ | ||
| ** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** | ||
| ** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** | ||
| ** /_____/\____/\___/\____/____/ ** | ||
| ** ** | ||
| ** $Id$ | ||
| \* */ | ||
|
|
||
| package scalac; | ||
|
|
||
| import java.io.*; | ||
| import java.util.*; | ||
| import scalac.util.*; | ||
| import scalac.ast.*; | ||
| import scalac.ast.parser.*; | ||
| import scalac.symtab.Definitions; | ||
| import scalac.ast.printer.*; | ||
|
|
||
|
|
||
| /** The global environment of a compiler run | ||
| * | ||
| * @author Matthias Zenger | ||
| * @version 1.0 | ||
| */ | ||
| public class Global { | ||
|
|
||
| public static Global instance; | ||
|
|
||
| /** global options | ||
| */ | ||
| public final boolean noimports; | ||
| //public final boolean optimize; | ||
| public final boolean debug; | ||
| public final boolean uniqid; | ||
|
|
||
| public final boolean printtypes; | ||
| public final boolean printtokens; | ||
|
|
||
| public final String outpath; | ||
| public final String target; | ||
|
|
||
| public final String jacoDebug; | ||
|
|
||
| /** the message reporter | ||
| */ | ||
| public final Reporter reporter; | ||
|
|
||
| /** a stack for maintaining timestamps | ||
| */ | ||
| private final Stack startTimes = new Stack(); | ||
|
|
||
| /** all compilation units | ||
| */ | ||
| public Unit[] units; | ||
|
|
||
| /** the class path | ||
| */ | ||
| public final ClassPath classPath; | ||
|
|
||
| /** the global tree factory | ||
| */ | ||
| public final TreeFactory make; | ||
|
|
||
| /** the fresh name creator | ||
| */ | ||
| public final FreshNameCreator freshNameCreator; | ||
|
|
||
| /** the tree generator | ||
| */ | ||
| public final TreeGen treeGen; | ||
|
|
||
| /** the unique-id generator | ||
| */ | ||
| public final UniqueID uniqueID; | ||
|
|
||
| /** the global tree printer | ||
| */ | ||
| public final TreePrinter printer; | ||
| public OutputStream printStream; | ||
| public final TreePrinter debugPrinter; | ||
|
|
||
| /** the current phase | ||
| */ | ||
| public PhaseDescriptor currentPhase; | ||
|
|
||
| /** the global definitions | ||
| */ | ||
| public Definitions definitions; | ||
|
|
||
| /** the global primitives | ||
| */ | ||
| //public Primitives primitives; | ||
|
|
||
| /** compilation phases. | ||
| */ | ||
| public final PhaseRepository PHASE; | ||
| public final PhaseDescriptor[] phases; | ||
|
|
||
| public final int POST_ANALYZER_PHASE_ID = 3; | ||
|
|
||
| /** compilation targets | ||
| */ | ||
| public static final String TARGET_INT; | ||
| public static final String TARGET_JAVA; | ||
| public static final String TARGET_JVM; | ||
| public static final String TARGET_MSIL; | ||
|
|
||
| public static final String[] TARGETS = new String[] { | ||
| TARGET_INT = "int".intern(), | ||
| TARGET_JAVA = "java".intern(), | ||
| TARGET_JVM = "jvm".intern(), | ||
| TARGET_MSIL = "msil".intern(), | ||
| }; | ||
|
|
||
| /** tree printers | ||
| */ | ||
| public static final String PRINTER_TEXT; | ||
| public static final String PRINTER_HTML; | ||
|
|
||
| public static final String[] PRINTERS = new String[] { | ||
| PRINTER_TEXT = "text".intern(), | ||
| PRINTER_HTML = "html".intern(), | ||
| }; | ||
|
|
||
| public Global(CompilerCommand args) { | ||
| this(args, false); | ||
| } | ||
|
|
||
| public Global(CompilerCommand args, boolean interpret) { | ||
| if (Global.instance != null) { // jaco bug: can't use assert here | ||
| new Error("Duplicate creation of Global").printStackTrace(); | ||
| System.exit(1); | ||
| }; | ||
| Global.instance = this; | ||
| this.reporter = args.reporter(); | ||
| this.start(); // timestamp to compute the total time | ||
| this.noimports = args.noimports.value; | ||
| //this.optimize = args.optimize.optimize; | ||
| this.debug = args.debug.value; | ||
| this.uniqid = args.uniqid.value; | ||
| this.printtypes = args.types.value; | ||
| this.printtokens = args.print.tokens; | ||
| this.classPath = args.classpath(); | ||
| this.outpath = args.outpath(); | ||
| this.target = interpret ? TARGET_INT : args.target.value.intern(); | ||
| this.jacoDebug = args.jaco.value; | ||
| this.uniqueID = new UniqueID(); | ||
| String printFile = args.printfile.value; | ||
| try { | ||
| this.printStream = "-".equals(printFile) | ||
| ? System.out | ||
| : new FileOutputStream(printFile); | ||
| } catch (FileNotFoundException e) { | ||
| error("unable to open file " + printFile + ". Printing on console"); | ||
| this.printStream = System.out; | ||
| } | ||
| String printerName = args.printer.value.intern(); | ||
| if (printerName == PRINTER_TEXT) | ||
| this.printer = new TextTreePrinter(printStream); | ||
| else | ||
| this.printer = new HTMLTreePrinter(printStream); | ||
| this.debugPrinter = new TextTreePrinter(System.err); | ||
| this.freshNameCreator = new FreshNameCreator(); | ||
| this.make = new TreeCreator(); | ||
| this.currentPhase = PhaseDescriptor.INITIAL; | ||
| this.definitions = new Definitions(this); | ||
| //this.primitives = new Primitives(this); | ||
| this.treeGen = new TreeGen(this, make); | ||
| this.PHASE = args.phases; | ||
| List phases = new ArrayList(); | ||
| phases.add(PHASE.INITIAL); | ||
| phases.add(PHASE.PARSER); | ||
| phases.add(PHASE.ANALYZER); | ||
| phases.add(PHASE.REFCHECK); | ||
| phases.add(PHASE.UNCURRY); | ||
| /* | ||
| if (optimize) { | ||
| phases.add(PHASE.OPTIMIZE); | ||
| } | ||
| phases.add(PHASE.TRANSMATCH); | ||
| */ | ||
| //phases.add(PHASE.LAMBDALIFT); | ||
| /* | ||
| phases.add(PHASE.EXPLICITOUTER); | ||
| phases.add(PHASE.ADDACCESSORS); | ||
| phases.add(PHASE.ADDINTERFACES); | ||
| phases.add(PHASE.EXPANDMIXIN); | ||
| phases.add(PHASE.ERASURE); | ||
| if (target == TARGET_INT || target == TARGET_MSIL || target == TARGET_JVM) { | ||
| phases.add(PHASE.ADDCONSTRUCTORS); | ||
| } | ||
| if (target == TARGET_JAVA) phases.add(PHASE.GENJAVA); | ||
| if (target == TARGET_MSIL) phases.add(PHASE.GENMSIL); | ||
| if (target == TARGET_JVM) phases.add(PHASE.GENJVM); | ||
| */ | ||
| phases.add(PHASE.TERMINAL); | ||
| this.phases = new PhaseDescriptor[phases.size()]; | ||
| for (int i = 0; i < phases.size(); i++) { | ||
| PhaseDescriptor phase = (PhaseDescriptor)phases.get(i); | ||
| this.phases[i] = phase; | ||
| if (i > 0) this.phases[i - 1].flags |= phase.flags >>> 16; | ||
| phase.initialize(this, i); | ||
| assert phase.id == i; | ||
| } | ||
| assert PHASE.ANALYZER.id + 1 == POST_ANALYZER_PHASE_ID; | ||
| } | ||
|
|
||
| /** Move to next phase | ||
| */ | ||
| public void nextPhase() { | ||
| currentPhase = phases[currentPhase.id + 1]; | ||
| } | ||
|
|
||
| /** Move to previous phase | ||
| */ | ||
| public void prevPhase() { | ||
| currentPhase = phases[currentPhase.id - 1]; | ||
| } | ||
|
|
||
| /** the top-level compilation process | ||
| */ | ||
| public void compile(String[] files, boolean console) { | ||
| reporter.resetCounters(); | ||
| // parse files | ||
| List units = new ArrayList(files.length); | ||
| for (int i = 0; i < files.length; i++) { | ||
| String file = files[i]; | ||
| try { | ||
| units.add(new Unit(this, new Sourcefile(file, console))); | ||
| } catch (FileNotFoundException e) { | ||
| error("file " + file + " not found"); | ||
| } catch (IOException e) { | ||
| error(e.toString()); | ||
| } | ||
| } | ||
| this.units = (Unit[])units.toArray(new Unit[units.size()]); | ||
| compile(); | ||
| } | ||
|
|
||
| /** the top-level compilation process | ||
| */ | ||
| public void compile(String input, boolean console) { | ||
| reporter.resetCounters(); | ||
| Sourcefile source = new Sourcefile(input.getBytes(), console); | ||
| units = new Unit[]{new Unit(this, source)}; | ||
| compile(); | ||
| } | ||
|
|
||
| /** compile all compilation units | ||
| */ | ||
| private void compile() { | ||
| printer.begin(); | ||
|
|
||
| // apply successive phases and pray that it works | ||
| for (int i = 0; i < phases.length && reporter.errors() == 0; ++i) { | ||
| currentPhase = phases[i]; | ||
| if ((currentPhase.flags & PhaseDescriptor.SKIP) != 0) { | ||
| operation("skipping phase " + currentPhase.name()); | ||
| } else { | ||
| currentPhase.apply(this); | ||
| } | ||
| if ((currentPhase.flags & PhaseDescriptor.PRINT) != 0) | ||
| currentPhase.print(this); | ||
| if ((currentPhase.flags & PhaseDescriptor.GRAPH) != 0) | ||
| currentPhase.graph(this); | ||
| if ((currentPhase.flags & PhaseDescriptor.CHECK) != 0) | ||
| currentPhase.check(this); | ||
| if ((currentPhase.flags & PhaseDescriptor.STOP) != 0) { | ||
| operation("stopped after phase " + currentPhase.name()); | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| printer.end(); | ||
| } | ||
|
|
||
| /** stop the compilation process immediately | ||
| */ | ||
| public Error fail() { | ||
| throw new ApplicationError(); | ||
| } | ||
|
|
||
| /** stop the compilation process immediately | ||
| */ | ||
| public Error fail(String message) { | ||
| throw new ApplicationError(message); | ||
| } | ||
|
|
||
| /** stop the compilation process immediately | ||
| */ | ||
| public Error fail(String message, Object object) { | ||
| throw new ApplicationError(message, object); | ||
| } | ||
|
|
||
| /** stop the compilation process immediately | ||
| */ | ||
| public Error fail(Object value) { | ||
| throw new ApplicationError(value); | ||
| } | ||
|
|
||
| /** issue a global error | ||
| */ | ||
| public void error(String message) { | ||
| reporter.error("error: " + message); | ||
| } | ||
|
|
||
| /** issue a global warning | ||
| */ | ||
| public void warning(String message) { | ||
| reporter.warning("warning: " + message); | ||
| } | ||
|
|
||
| /** issue a global note (if in verbose mode) | ||
| */ | ||
| public void note(String message) { | ||
| reporter.note("note: " + message); | ||
| } | ||
|
|
||
| /** issue an operation note | ||
| */ | ||
| public void operation(String message) { | ||
| reporter.inform("[" + message + "]"); | ||
| } | ||
|
|
||
| /** issue a debug message from currentPhase | ||
| */ | ||
| // the boolean return value is here to let one write "assert log( ... )" | ||
| public boolean log(String message) { | ||
| if (log()) { | ||
| reporter.report("[log " + currentPhase.name() + "] " + message); | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| /** return true if logging is switched on for the current phase | ||
| */ | ||
| public boolean log() { | ||
| return (currentPhase.flags & PhaseDescriptor.LOG) != 0; | ||
| } | ||
|
|
||
| /** start a new timer | ||
| */ | ||
| public void start() { | ||
| startTimes.push(new Long(System.currentTimeMillis())); | ||
| } | ||
|
|
||
| /** issue timing information | ||
| */ | ||
| public void stop(String message) { | ||
| long start = ((Long)startTimes.pop()).longValue(); | ||
| reporter.inform("[" + message + " in " + | ||
| (System.currentTimeMillis() - start) + "ms]"); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| /* ____ ____ ____ ____ ______ *\ | ||
| ** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** | ||
| ** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** | ||
| ** /_____/\____/\___/\____/____/ ** | ||
| ** ** | ||
| ** $Id$ | ||
| \* */ | ||
|
|
||
| package scalac; | ||
|
|
||
| import scalac.util.Reporter; | ||
|
|
||
| /** The main class for SoCoS, a compiler for the programming | ||
| * language Scala. | ||
| * | ||
| * @author Matthias Zenger | ||
| * @version 1.0 | ||
| */ | ||
| public class Main { | ||
|
|
||
| public static final String PRODUCT = | ||
| System.getProperty("scala.product", "socos"); | ||
| public static final String VERSION = | ||
| System.getProperty("scala.version", "unknown version"); | ||
|
|
||
| public static void main(String[] args) { | ||
| Reporter reporter = new Reporter(); | ||
| CompilerCommand command = new CompilerCommand( | ||
| PRODUCT, VERSION, reporter, new PhaseRepository()); | ||
| if (command.parse(args) && command.files.list.size() > 0) { | ||
| Global global = new Global(command); | ||
| global.compile(command.files.toArray(), false); | ||
| global.stop("total"); | ||
| global.reporter.printSummary(); | ||
| } | ||
| System.exit((reporter.errors() > 0) ? -1 : 0); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| /* ____ ____ ____ ____ ______ *\ | ||
| ** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** | ||
| ** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** | ||
| ** /_____/\____/\___/\____/____/ ** | ||
| ** ** | ||
| ** $Id$ | ||
| \* */ | ||
|
|
||
| package scalac; | ||
|
|
||
| /** Representation of a compiler phase. PhaseDescriptors create | ||
| * phase. Phases operate subsequently on all compilation units. | ||
| * | ||
| * @author Matthias Zenger | ||
| * @version 1.0 | ||
| */ | ||
| public abstract class Phase { | ||
|
|
||
| /** the global environment | ||
| */ | ||
| public final Global global; | ||
|
|
||
| /** the descriptor for this phase | ||
| */ | ||
| public final PhaseDescriptor descr; | ||
|
|
||
| /** constructor | ||
| */ | ||
| public Phase(Global global, PhaseDescriptor descr) { | ||
| this.global = global; | ||
| this.descr = descr; | ||
| } | ||
|
|
||
| /** apply this phase to all compilation units | ||
| */ | ||
| public void apply() { | ||
| for (int i = 0; i < global.units.length; i++) { | ||
| apply(global.units[i]); | ||
| } | ||
| } | ||
|
|
||
| /** apply this phase to the given compilation unit | ||
| */ | ||
| public abstract void apply(Unit unit); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,169 @@ | ||
| /* ____ ____ ____ ____ ______ *\ | ||
| ** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** | ||
| ** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** | ||
| ** /_____/\____/\___/\____/____/ ** | ||
| ** ** | ||
| ** $Id$ | ||
| \* */ | ||
|
|
||
| package scalac; | ||
|
|
||
| import java.util.*; | ||
| import scalac.ast.printer.*; | ||
| import scalac.ast.*; | ||
| import scalac.symtab.*; | ||
| import scalac.checkers.*; | ||
| import java.io.PrintWriter; | ||
|
|
||
| /** | ||
| * Information about a compiler phase. | ||
| * | ||
| * @author Michel Schinz | ||
| */ | ||
|
|
||
| public abstract class PhaseDescriptor { | ||
|
|
||
| private static class InitialPhaseDescriptor extends PhaseDescriptor { | ||
|
|
||
| public String name() { | ||
| return "initial"; | ||
| } | ||
|
|
||
| public String description() { | ||
| return "initializing compiler"; | ||
| } | ||
|
|
||
| public Phase createPhase(Global global) { | ||
| return null; | ||
| } | ||
|
|
||
| /** apply phase to all compilation units | ||
| */ | ||
| public void apply(Global global) {} | ||
| } | ||
|
|
||
| private static class TerminalPhaseDescriptor extends PhaseDescriptor { | ||
|
|
||
| public String name() { | ||
| return "terminal"; | ||
| } | ||
|
|
||
| public String description() { | ||
| return "compilation terminated "; | ||
| } | ||
|
|
||
| public Phase createPhase(Global global) { | ||
| return null; | ||
| } | ||
|
|
||
| /** apply phase to all compilation units | ||
| */ | ||
| public void apply(Global global) {} | ||
| } | ||
|
|
||
| public static PhaseDescriptor INITIAL = new InitialPhaseDescriptor(); | ||
| public static PhaseDescriptor TERMINAL = new TerminalPhaseDescriptor(); | ||
|
|
||
| public static final int SKIP = 0x0001; | ||
| public static final int CHECK = 0x0002; | ||
| public static final int PRINT = 0x0004; | ||
| public static final int GRAPH = 0x0008; | ||
| public static final int STOP = 0x0010; | ||
| public static final int LOG = 0x0020; | ||
|
|
||
| public int flags; | ||
| public int id; | ||
|
|
||
| /** return a short, one-word name for the phase. | ||
| */ | ||
| public abstract String name(); | ||
|
|
||
| /** return a one-line description for the phase. | ||
| */ | ||
| public abstract String description(); | ||
|
|
||
| /** a one-line task description of this phase | ||
| */ | ||
| public String taskDescription() { | ||
| return description(); | ||
| } | ||
|
|
||
| /** initialize the phase | ||
| */ | ||
| public final void initialize(Global global) { | ||
| throw new Error(); | ||
| } | ||
| public void initialize(Global global, int id) { | ||
| this.id = id; | ||
| } | ||
|
|
||
| /** create a phase | ||
| */ | ||
| public abstract Phase createPhase(Global global); | ||
|
|
||
| /** Assume that `tp' is the info of symbol `sym' before this phase. | ||
| * Return the info of `sym' after the phase. | ||
| */ | ||
| public Type transformInfo(Symbol sym, Type tp) { | ||
| return tp; | ||
| } | ||
|
|
||
| /** apply phase to all compilation units | ||
| */ | ||
| public void apply(Global global) { | ||
| global.start(); | ||
| createPhase(global).apply(); | ||
| global.stop(taskDescription()); | ||
| } | ||
|
|
||
| /** check all compilation units | ||
| */ | ||
| public void check(Global global) { | ||
| for (int i = 0; i < global.units.length; i++) | ||
| check(global.units[i]); | ||
| } | ||
|
|
||
| /** print all compilation units | ||
| */ | ||
| public void print(Global global) { | ||
| TreePrinter printer = global.printer; | ||
|
|
||
| printer.beginSection(1, "Trees after phase " + name()); | ||
| for (int i = 0; i < global.units.length; i++) | ||
| printer.print(global.units[i]); | ||
| } | ||
|
|
||
| /** graph all compilation units | ||
| */ | ||
| public void graph(Global global) { | ||
| for (int i = 0; i < global.units.length; i++) | ||
| graph(global.units[i]); | ||
| } | ||
|
|
||
| /** return an array of checkers which can be applied after the phase | ||
| */ | ||
| public Checker[] postCheckers(Global global) { | ||
| return new Checker[0]; | ||
| } | ||
|
|
||
| /** check the result of this phase for the given compilation unit | ||
| */ | ||
| public void check(Unit unit) { | ||
| Checker[] checkers = postCheckers(unit.global); | ||
| for (int i = 0; i < checkers.length; i++) | ||
| checkers[i].traverse(unit); | ||
| } | ||
|
|
||
| /** graph the result of this phase for the given compilation unit | ||
| */ | ||
| public void graph(Unit unit) { | ||
| /* todo: uncomment | ||
| new scala.compiler.gdl.TreePrinter().printInFile( | ||
| unit, unit.source + "-" + name() + ".gdl"); | ||
| */ | ||
| } | ||
|
|
||
| public String toString() { | ||
| return name(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| /* ____ ____ ____ ____ ______ *\ | ||
| ** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** | ||
| ** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** | ||
| ** /_____/\____/\___/\____/____/ ** | ||
| \* */ | ||
|
|
||
| // $Id$ | ||
|
|
||
| package scalac; | ||
|
|
||
| import scalac.ast.parser.ParserPhase; | ||
| import scalac.typechecker.AnalyzerPhase; | ||
| import scalac.typechecker.RefCheckPhase; | ||
| import scalac.transformer.UnCurryPhase; | ||
| /* | ||
| import scalac.transformer.TransMatchPhase; | ||
| */ | ||
| import scalac.transformer.LambdaLiftPhase; | ||
| /* | ||
| import scalac.transformer.ExplicitOuterClassesPhase; | ||
| import scalac.transformer.AddInterfacesPhase; | ||
| import scalac.transformer.AddAccessorsPhase; | ||
| import scalac.transformer.ExpandMixinsPhase; | ||
| import scalac.transformer.ErasurePhase; | ||
| import scalac.optimizer.OptimizePhase; | ||
| import scalac.backend.AddConstructorsPhase; | ||
| import scalac.backend.msil.GenMSILPhase; | ||
| import scalac.backend.jvm.GenJVMPhase; | ||
| import scalac.jaco.GenJavaPhase; | ||
| */ | ||
|
|
||
| public class PhaseRepository { | ||
|
|
||
| //######################################################################## | ||
| // Private state | ||
|
|
||
| public final PhaseDescriptor[] phases; | ||
|
|
||
| //######################################################################## | ||
| // Reporter constructors | ||
|
|
||
| public PhaseRepository() { | ||
| this.phases = new PhaseDescriptor[] { | ||
| INITIAL = PhaseDescriptor.INITIAL, | ||
| PARSER = new ParserPhase(), | ||
| ANALYZER = new AnalyzerPhase(), | ||
| REFCHECK = new RefCheckPhase(), | ||
| UNCURRY = new UnCurryPhase(), | ||
| /* | ||
| OPTIMIZE = new OptimizePhase(), | ||
| TRANSMATCH = new TransMatchPhase(), | ||
| */ | ||
| LAMBDALIFT = new LambdaLiftPhase(), | ||
| /* | ||
| EXPLICITOUTER = new ExplicitOuterClassesPhase(), | ||
| ADDACCESSORS = new AddAccessorsPhase(), | ||
| ADDINTERFACES = new AddInterfacesPhase(), | ||
| EXPANDMIXIN = new ExpandMixinsPhase(), | ||
| ERASURE = new ErasurePhase(), | ||
| ADDCONSTRUCTORS = new AddConstructorsPhase(), | ||
| GENMSIL = new GenMSILPhase(), | ||
| GENJAVA = new GenJavaPhase(), | ||
| GENJVM = new GenJVMPhase(), | ||
| */ | ||
| TERMINAL = PhaseDescriptor.TERMINAL, | ||
| }; | ||
| } | ||
|
|
||
| //######################################################################## | ||
| // Reporter interface | ||
|
|
||
| public final PhaseDescriptor INITIAL; | ||
| public final ParserPhase PARSER; | ||
| public final AnalyzerPhase ANALYZER; | ||
| public final RefCheckPhase REFCHECK; | ||
| public final UnCurryPhase UNCURRY; | ||
| /* | ||
| public final OptimizePhase OPTIMIZE; | ||
| public final TransMatchPhase TRANSMATCH; | ||
| */ | ||
| public final LambdaLiftPhase LAMBDALIFT; | ||
| /* | ||
| public final ExplicitOuterClassesPhase EXPLICITOUTER; | ||
| public final AddAccessorsPhase ADDACCESSORS; | ||
| public final AddInterfacesPhase ADDINTERFACES; | ||
| public final ExpandMixinsPhase EXPANDMIXIN; | ||
| public final ErasurePhase ERASURE; | ||
| public final AddConstructorsPhase ADDCONSTRUCTORS; | ||
| public final GenMSILPhase GENMSIL; | ||
| public final GenJavaPhase GENJAVA; | ||
| public final GenJVMPhase GENJVM; | ||
| */ | ||
| public final PhaseDescriptor TERMINAL; | ||
|
|
||
| //######################################################################## | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,123 @@ | ||
| /* ____ ____ ____ ____ ______ *\ | ||
| ** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** | ||
| ** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** | ||
| ** /_____/\____/\___/\____/____/ ** | ||
| ** ** | ||
| ** $Id$ | ||
| \* */ | ||
|
|
||
| package scalac; | ||
|
|
||
| import scalac.util.*; | ||
| import scalac.symtab.NameMangler; | ||
| import scalac.ast.parser.Sourcefile; | ||
| import scalac.ast.Tree; | ||
| import scala.compiler.typechecker.*; | ||
| import java.io.*; | ||
| import java.util.*; | ||
|
|
||
|
|
||
| /** A representation for a compilation unit in scala | ||
| * | ||
| * @author Matthias Zenger | ||
| * @version 1.0 | ||
| */ | ||
| public class Unit { | ||
|
|
||
| /** the global compilation environment | ||
| */ | ||
| public Global global; | ||
|
|
||
| /** the associated source code file | ||
| */ | ||
| public Sourcefile source; | ||
|
|
||
| /** the content of the compilation unit in tree form | ||
| */ | ||
| public Tree[] body; | ||
|
|
||
| /** the generated symbol data; Symbol -> byte[] | ||
| public SymData symdata; | ||
| */ | ||
|
|
||
| /** the name mangler | ||
| */ | ||
| public NameMangler mangler = new NameMangler(); | ||
|
|
||
| /** number of errors issued for this compilation unit | ||
| */ | ||
| public int errors; | ||
|
|
||
| /** number of warnings issued for this compilation unit | ||
| */ | ||
| public int warnings; | ||
|
|
||
| /** number of notes issued for this compilation unit | ||
| */ | ||
| public int notes; | ||
|
|
||
| public Unit(Global global, Sourcefile source) { | ||
| this.global = global; | ||
| this.source = source; | ||
| } | ||
| /* | ||
| public void print(String message) { | ||
| print(System.out, message); | ||
| } | ||
| public void print(PrintStream out, String message) { | ||
| out.println("[[begin " + message + "]]"); | ||
| new Printer(out).printCompilationUnit(this); | ||
| out.println(); | ||
| out.println("[[end " + message + "]]"); | ||
| } | ||
| */ | ||
| /** issue an error in this compilation unit | ||
| */ | ||
| public void error(String message) { | ||
| error(Position.NOPOS, message); | ||
| } | ||
|
|
||
| /** issue an error in this compilation unit at a specific location | ||
| */ | ||
| public void error(int pos, String message) { | ||
| boolean hidden = source.testAndSetLog(pos, message); | ||
| if (!hidden) errors++; | ||
| global.reporter.error(source.getMessage(pos, message), hidden); | ||
| } | ||
|
|
||
| /** issue a warning in this compilation unit | ||
| */ | ||
| public void warning(String message) { | ||
| warning(Position.NOPOS, message); | ||
| } | ||
|
|
||
| /** issue a warning in this compilation unit at a specific location | ||
| */ | ||
| public void warning(int pos, String message) { | ||
| if (global.reporter.nowarn) return; | ||
| message = "warning: " + message; | ||
| boolean hidden = source.testAndSetLog(pos, message); | ||
| if (!hidden) warnings++; | ||
| global.reporter.warning(source.getMessage(pos, message), hidden); | ||
| } | ||
|
|
||
| /** issue a note in this compilation unit | ||
| */ | ||
| public void note(String message) { | ||
| note(Position.NOPOS, message); | ||
| } | ||
|
|
||
| /** issue a note in this compilation unit at a specific location | ||
| */ | ||
| public void note(int pos, String message) { | ||
| global.reporter.note(source.getMessage(pos, message)); | ||
| notes++; | ||
| } | ||
|
|
||
| /** return a string representation | ||
| */ | ||
| public String toString() { | ||
| return source.toString(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| /* ____ ____ ____ ____ ______ *\ | ||
| ** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** | ||
| ** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** | ||
| ** /_____/\____/\___/\____/____/ ** | ||
| ** ** | ||
| \* */ | ||
|
|
||
| // $Id$ | ||
|
|
||
| package scalac.ast; | ||
|
|
||
| import scalac.ast.*; | ||
|
|
||
| /** | ||
| * Abstract superclass for all TreeCopyFactories, which provides only | ||
| * the code to copy the attribution from the "old" to the "new" tree. | ||
| * | ||
| * @author Michel Schinz | ||
| * @version 1.0 | ||
| */ | ||
|
|
||
| public abstract class AbstractTreeCopyFactory implements TreeCopyFactory { | ||
| public void attribute(Tree newTree, Tree oldTree) { | ||
| if (newTree != oldTree) { | ||
| newTree.type = oldTree.type; | ||
| if (newTree.hasSymbol()) | ||
| newTree.setSymbol(oldTree.symbol()); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,215 @@ | ||
| /* ____ ____ ____ ____ ______ *\ | ||
| ** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** | ||
| ** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** | ||
| ** /_____/\____/\___/\____/____/ ** | ||
| ** ** | ||
| \* */ | ||
|
|
||
| // $Id$ | ||
|
|
||
| package scalac.ast; | ||
|
|
||
| import java.io.*; | ||
| import java.util.*; | ||
| import scalac.*; | ||
| import scalac.util.*; | ||
| import Tree.*; | ||
|
|
||
|
|
||
| /** Class to traverse a tree without modifying it. | ||
| * | ||
| * @author Michel Schinz | ||
| */ | ||
|
|
||
| public class Traverser { | ||
| public Traverser() {} | ||
|
|
||
| // this should be removed in the future | ||
| public Traverser(Global global) {} | ||
|
|
||
| public void traverse(Unit unit) { | ||
| traverse(unit.body); | ||
| } | ||
|
|
||
| public void traverse(Tree tree) { | ||
| switch (tree) { | ||
| case Bad(): | ||
| case Empty: | ||
| case Ident(_): | ||
| case Literal(_): | ||
| return; | ||
|
|
||
| case ClassDef(int mods, | ||
| Name name, | ||
| TypeDef[] tparams, | ||
| ValDef[][] vparams, | ||
| Tree tpe, | ||
| Template impl): | ||
| traverse(tparams); | ||
| traverse(vparams); | ||
| traverse(tpe); | ||
| traverse(impl); | ||
| return; | ||
|
|
||
| case PackageDef(Tree packaged, Template impl) : | ||
| traverse(packaged); | ||
| traverse(impl); | ||
| return; | ||
|
|
||
| case ModuleDef(int mods, Name name, Tree tpe, Template impl): | ||
| traverse(tpe); | ||
| traverse(impl); | ||
| return; | ||
|
|
||
| case ValDef(int mods, Name name, Tree tpe, Tree rhs): | ||
| traverse(tpe); | ||
| traverse(rhs); | ||
| return; | ||
|
|
||
| case PatDef(int mods, Tree pat, Tree rhs): | ||
| traverse(pat); | ||
| traverse(rhs); | ||
| return; | ||
|
|
||
| case DefDef(int mods, | ||
| Name name, | ||
| TypeDef[] tparams, | ||
| ValDef[][] vparams, | ||
| Tree tpe, | ||
| Tree rhs): | ||
| traverse(tparams); | ||
| traverse(vparams); | ||
| traverse(tpe); | ||
| traverse(rhs); | ||
| return; | ||
|
|
||
| case TypeDef(int mods, Name name, TypeDef[] tparams, Tree rhs): | ||
| traverse(tparams); | ||
| traverse(rhs); | ||
| return; | ||
|
|
||
| case Import(Tree expr, Name[] selectors): | ||
| traverse(expr); | ||
| return; | ||
|
|
||
| case CaseDef(Tree pat, Tree guard, Tree body): | ||
| traverse(pat); | ||
| traverse(guard); | ||
| traverse(body); | ||
| return; | ||
|
|
||
| case Template(Tree[] baseClasses, Tree[] body): | ||
| traverse(baseClasses); | ||
| traverse(body); | ||
| return; | ||
|
|
||
| case LabelDef(Tree[] params,Tree rhs): | ||
| traverse(params); | ||
| traverse(rhs); | ||
| return; | ||
|
|
||
| case Block(Tree[] stats): | ||
| traverse(stats); | ||
| return; | ||
|
|
||
| case Tuple(Tree[] trees): | ||
| traverse(trees); | ||
| return; | ||
|
|
||
| case Visitor(CaseDef[] cases): | ||
| traverse(cases); | ||
| return; | ||
|
|
||
| case Function(ValDef[] vparams, Tree body): | ||
| traverse(vparams); | ||
| traverse(body); | ||
| return; | ||
|
|
||
| case Assign(Tree lhs, Tree rhs): | ||
| traverse(lhs); | ||
| traverse(rhs); | ||
| return; | ||
|
|
||
| case If(Tree cond, Tree thenp, Tree elsep): | ||
| traverse(cond); | ||
| traverse(thenp); | ||
| traverse(elsep); | ||
| return; | ||
|
|
||
| case New(Template templ): | ||
| traverse(templ); | ||
| return; | ||
|
|
||
| case Typed(Tree expr, Tree tpe): | ||
| traverse(expr); | ||
| traverse(tpe); | ||
| return; | ||
|
|
||
| case TypeApply(Tree fun, Tree[] tparams): | ||
| traverse(fun); | ||
| traverse(tparams); | ||
| return; | ||
|
|
||
| case Apply(Tree fun, Tree[] vparam): | ||
| traverse(fun); | ||
| traverse(vparam); | ||
| return; | ||
|
|
||
| case Super(Tree tpe): | ||
| traverse(tpe); | ||
| return; | ||
|
|
||
| case This(Tree qualifier): | ||
| traverse(qualifier); | ||
| return; | ||
|
|
||
| case Select(Tree qualifier, Name selector): | ||
| traverse(qualifier); | ||
| return; | ||
|
|
||
| case SingletonType(Tree ref): | ||
| traverse(ref); | ||
| return; | ||
|
|
||
| case SelectFromType(Tree qualifier, Name selector): | ||
| traverse(qualifier); | ||
| return; | ||
|
|
||
| case FunType(Tree[] argtpes, Tree restpe): | ||
| traverse(argtpes); | ||
| traverse(restpe); | ||
| return; | ||
|
|
||
| case CompoundType(Tree[] baseTypes, Tree[] refinements): | ||
| traverse(baseTypes); | ||
| traverse(refinements); | ||
| return; | ||
|
|
||
| case TupleType(Tree[] types): | ||
| traverse(types); | ||
| return; | ||
|
|
||
| case AppliedType(Tree tpe, Tree[] args): | ||
| traverse(tpe); | ||
| traverse(args); | ||
| return; | ||
|
|
||
| case CovariantType(Tree tpe): | ||
| traverse(tpe); | ||
| return; | ||
|
|
||
| default: | ||
| throw new ApplicationError("unknown node " + tree); | ||
| } | ||
| } | ||
|
|
||
| public void traverse(Tree[] array) { | ||
| for (int i = 0; i < array.length; ++i) | ||
| traverse(array[i]); | ||
| } | ||
|
|
||
| public void traverse(Tree[][] array) { | ||
| for (int i = 0; i < array.length; ++i) | ||
| traverse(array[i]); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,165 @@ | ||
| /* ____ ____ ____ ____ ______ *\ | ||
| ** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** | ||
| ** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** | ||
| ** /_____/\____/\___/\____/____/ ** | ||
| ** ** | ||
| ** $Id$ | ||
| \* */ | ||
|
|
||
| package scalac.ast; | ||
|
|
||
| import scalac.util.Name; | ||
| import Tree.*; | ||
|
|
||
| /** | ||
| * Interface for a kind of factory which, for each node constructor, | ||
| * takes an original node from which some data will be copied or shared. | ||
| * | ||
| * @author Michel Schinz | ||
| * @version 1.1 | ||
| */ | ||
| public interface TreeCopyFactory { | ||
|
|
||
| public void attribute(Tree newTree, Tree oldTree); | ||
|
|
||
| public Tree Bad(Tree tree); | ||
|
|
||
| public Tree ClassDef(Tree tree, | ||
| int mods, | ||
| Name name, | ||
| TypeDef[] tparams, | ||
| ValDef[][] vparams, | ||
| Tree tpe, | ||
| Template impl); | ||
|
|
||
| public Tree PackageDef(Tree tree, | ||
| Tree packaged, | ||
| Template impl); | ||
|
|
||
| public Tree ModuleDef(Tree tree, | ||
| int mods, | ||
| Name name, | ||
| Tree tpe, | ||
| Template impl); | ||
|
|
||
| public Tree ValDef(Tree tree, | ||
| int mods, | ||
| Name name, | ||
| Tree tpe, | ||
| Tree rhs); | ||
|
|
||
| public Tree PatDef(Tree tree, | ||
| int mods, | ||
| Tree pat, | ||
| Tree rhs); | ||
|
|
||
| public Tree DefDef(Tree tree, | ||
| int mods, | ||
| Name name, | ||
| TypeDef[] tparams, | ||
| ValDef[][] vparams, | ||
| Tree tpe, | ||
| Tree rhs); | ||
|
|
||
| public Tree TypeDef(Tree tree, | ||
| int mods, | ||
| Name name, | ||
| TypeDef[] tparams, | ||
| Tree rhs); | ||
|
|
||
| public Tree Import(Tree tree, | ||
| Tree expr, | ||
| Name[] selectors); | ||
|
|
||
| public Tree CaseDef(Tree tree, | ||
| Tree pat, | ||
| Tree guard, | ||
| Tree body); | ||
|
|
||
| public Template Template(Tree tree, | ||
| Tree[] baseClasses, | ||
| Tree[] body); | ||
|
|
||
| public Tree LabelDef(Tree tree, | ||
| Tree[] params, | ||
| Tree rhs); | ||
|
|
||
| public Tree Block(Tree tree, | ||
| Tree[] stats); | ||
|
|
||
| public Tree Tuple(Tree tree, | ||
| Tree[] trees); | ||
|
|
||
| public Tree Visitor(Tree tree, | ||
| CaseDef[] cases); | ||
|
|
||
| public Tree Function(Tree tree, | ||
| ValDef[] vparams, | ||
| Tree body); | ||
|
|
||
| public Tree Assign(Tree tree, | ||
| Tree lhs, | ||
| Tree rhs); | ||
|
|
||
| public Tree If(Tree tree, | ||
| Tree cond, | ||
| Tree thenp, | ||
| Tree elsep); | ||
|
|
||
| public Tree New(Tree tree, | ||
| Template templ); | ||
|
|
||
| public Tree Typed(Tree tree, | ||
| Tree expr, | ||
| Tree tpe); | ||
|
|
||
| public Tree TypeApply(Tree tree, | ||
| Tree fun, | ||
| Tree[] args); | ||
|
|
||
| public Tree Apply(Tree tree, | ||
| Tree fun, | ||
| Tree[] args); | ||
|
|
||
| public Tree Super(Tree tree, | ||
| Tree tpe); | ||
|
|
||
| public Tree This(Tree tree, | ||
| Tree qualifier); | ||
|
|
||
| public Tree Select(Tree tree, | ||
| Tree qualifier, | ||
| Name selector); | ||
|
|
||
| public Tree Ident(Tree tree, | ||
| Name name); | ||
|
|
||
| public Tree Literal(Tree tree, | ||
| Object value); | ||
|
|
||
| public Tree SingletonType(Tree tree, | ||
| Tree ref); | ||
|
|
||
| public Tree SelectFromType(Tree tree, | ||
| Tree qualifier, | ||
| Name selector); | ||
|
|
||
| public Tree FunType(Tree tree, | ||
| Tree[] argtpes, | ||
| Tree restpe); | ||
|
|
||
| public Tree CompoundType(Tree tree, | ||
| Tree[] baseTypes, | ||
| Tree[] refinements); | ||
|
|
||
| public Tree TupleType(Tree tree, | ||
| Tree[] types); | ||
|
|
||
| public Tree AppliedType(Tree tree, | ||
| Tree tpe, | ||
| Tree[] args); | ||
|
|
||
| public Tree CovariantType(Tree tree, | ||
| Tree tpe); | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,293 @@ | ||
| /* ____ ____ ____ ____ ______ *\ | ||
| ** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** | ||
| ** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** | ||
| ** /_____/\____/\___/\____/____/ ** | ||
| ** ** | ||
| ** $Id$ | ||
| \* */ | ||
|
|
||
| package scalac.ast; | ||
|
|
||
| import Tree.*; | ||
| import scalac.util.Name; | ||
|
|
||
|
|
||
| public class TreeCreator implements TreeFactory { | ||
|
|
||
| public Tree Bad(int pos) { | ||
| Tree t = new ExtBad(); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
| public Tree ClassDef(int pos, | ||
| int mods, | ||
| Name name, | ||
| TypeDef[] tparams, | ||
| ValDef[][] vparams, | ||
| Tree tpe, | ||
| Template impl) { | ||
| Tree t = new ExtClassDef(mods, name, tparams, vparams, tpe, impl); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
| public Tree PackageDef(int pos, | ||
| Tree packaged, | ||
| Template impl) { | ||
| Tree t = new PackageDef(packaged, impl); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
| public Tree ModuleDef(int pos, | ||
| int mods, | ||
| Name name, | ||
| Tree tpe, | ||
| Template body) { | ||
| Tree t = new ExtModuleDef(mods, name, tpe, body); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
| public Tree ValDef(int pos, | ||
| int mods, | ||
| Name name, | ||
| Tree tpe, | ||
| Tree rhs) { | ||
| Tree t = new ExtValDef(mods, name, tpe, rhs); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
| public Tree PatDef(int pos, | ||
| int mods, | ||
| Tree pat, | ||
| Tree rhs) { | ||
| Tree t = new PatDef(mods, pat, rhs); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
| public Tree DefDef(int pos, | ||
| int mods, | ||
| Name name, | ||
| TypeDef[] tparams, | ||
| ValDef[][] vparams, | ||
| Tree tpe, | ||
| Tree rhs) { | ||
| Tree t = new ExtDefDef(mods, name, tparams, vparams, tpe, rhs); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
|
|
||
| public Tree TypeDef(int pos, | ||
| int mods, | ||
| Name name, | ||
| TypeDef[] tparams, | ||
| Tree rhs) { | ||
| Tree t = new ExtTypeDef(mods, name, tparams, rhs); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
| public Tree Import(int pos, | ||
| Tree expr, | ||
| Name[] selectors) { | ||
| Tree t = new ExtImport(expr, selectors); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
| public CaseDef CaseDef(int pos, | ||
| Tree pat, | ||
| Tree guard, | ||
| Tree body) { | ||
| CaseDef t = new CaseDef(pat, guard, body); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
| public Template Template(int pos, | ||
| Tree[] baseClasses, | ||
| Tree[] body) { | ||
| Template t = new ExtTemplate(baseClasses, body); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
| public Tree LabelDef(int pos, | ||
| Tree[] params, | ||
| Tree body) { | ||
| Tree t = new ExtLabelDef(params,body); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
| public Tree Block(int pos, | ||
| Tree[] stats) { | ||
| Tree t = new Block(stats); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
| public Tree Tuple(int pos, | ||
| Tree[] trees) { | ||
| Tree t = new Tuple(trees); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
| public Tree Visitor(int pos, | ||
| CaseDef[] cases) { | ||
| Tree t = new Visitor(cases); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
| public Tree Function(int pos, | ||
| ValDef[] vparams, | ||
| Tree body) { | ||
| Tree t = new Function(vparams, body); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
| public Tree Assign(int pos, | ||
| Tree lhs, | ||
| Tree rhs) { | ||
| Tree t = new Assign(lhs, rhs); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
| public Tree If(int pos, | ||
| Tree cond, | ||
| Tree thenp, | ||
| Tree elsep) { | ||
| Tree t = new If(cond, thenp, elsep); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
| public Tree New(int pos, | ||
| Template templ) { | ||
| Tree t = new New(templ); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
| public Tree Typed(int pos, | ||
| Tree expr, | ||
| Tree tpe) { | ||
| Tree t = new Typed(expr, tpe); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
| public Tree TypeApply(int pos, | ||
| Tree fun, | ||
| Tree[] tparams) { | ||
| Tree t = new TypeApply(fun, tparams); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
| public Tree Apply(int pos, | ||
| Tree fun, | ||
| Tree[] vparam) { | ||
| Tree t = new Apply(fun, vparam); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
| public Tree Super(int pos, | ||
| Tree tpe) { | ||
| Tree t = new Super(tpe); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
| public Tree This(int pos, | ||
| Tree qualifier) { | ||
| Tree t = new This(qualifier); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
| public Tree Select(int pos, | ||
| Tree qualifier, | ||
| Name selector) { | ||
| Tree t = new ExtSelect(qualifier, selector); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
| public Tree Ident(int pos, | ||
| Name name) { | ||
| Tree t = new ExtIdent(name); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
| public Tree Literal(int pos, | ||
| Object value) { | ||
| Tree t = new Literal(value); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
|
|
||
| public Tree SingletonType(int pos, Tree ref) { | ||
| Tree t = new SingletonType(ref); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
| public Tree SelectFromType(int pos, | ||
| Tree qualifier, | ||
| Name selector) { | ||
| Tree t = new ExtSelectFromType(qualifier, selector); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
| public Tree FunType(int pos, | ||
| Tree[] argtpes, | ||
| Tree restpe) { | ||
| Tree t = new FunType(argtpes, restpe); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
| public Tree CompoundType(int pos, | ||
| Tree[] mixins, | ||
| Tree[] fields) { | ||
| Tree t = new CompoundType(mixins, fields); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
| public Tree TupleType(int pos, | ||
| Tree[] types) { | ||
| Tree t = new TupleType(types); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
| public Tree AppliedType(int pos, | ||
| Tree tpe, | ||
| Tree[] args) { | ||
| Tree t = new AppliedType(tpe, args); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
|
|
||
| public Tree CovariantType(int pos, | ||
| Tree tpe) { | ||
| Tree t = new CovariantType(tpe); | ||
| t.pos = pos; | ||
| return t; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,155 @@ | ||
| /* ____ ____ ____ ____ ______ *\ | ||
| ** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** | ||
| ** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** | ||
| ** /_____/\____/\___/\____/____/ ** | ||
| ** ** | ||
| ** $Id$ | ||
| \* */ | ||
|
|
||
| package scalac.ast; | ||
|
|
||
| import scalac.util.Name; | ||
| import Tree.*; | ||
|
|
||
| public interface TreeFactory { | ||
|
|
||
| public Tree Bad(int pos); | ||
|
|
||
| public Tree ClassDef(int pos, | ||
| int mods, | ||
| Name name, | ||
| TypeDef[] tparams, | ||
| ValDef[][] vparams, | ||
| Tree tpe, | ||
| Template impl); | ||
|
|
||
| public Tree PackageDef(int pos, | ||
| Tree packaged, | ||
| Template impl); | ||
|
|
||
| public Tree ModuleDef(int pos, | ||
| int mods, | ||
| Name name, | ||
| Tree tpe, | ||
| Template impl); | ||
|
|
||
| public Tree ValDef(int pos, | ||
| int mods, | ||
| Name name, | ||
| Tree tpe, | ||
| Tree rhs); | ||
|
|
||
| public Tree PatDef(int pos, | ||
| int mods, | ||
| Tree pat, | ||
| Tree rhs); | ||
|
|
||
| public Tree DefDef(int pos, | ||
| int mods, | ||
| Name name, | ||
| TypeDef[] tparams, | ||
| ValDef[][] vparams, | ||
| Tree tpe, | ||
| Tree rhs); | ||
|
|
||
| public Tree TypeDef(int pos, | ||
| int mods, | ||
| Name name, | ||
| TypeDef[] tparams, | ||
| Tree rhs); | ||
|
|
||
| public Tree Import(int pos, | ||
| Tree expr, | ||
| Name[] selectors); | ||
|
|
||
| public CaseDef CaseDef(int pos, | ||
| Tree pat, | ||
| Tree guard, | ||
| Tree body); | ||
|
|
||
| public Template Template(int pos, | ||
| Tree[] baseClasses, | ||
| Tree[] body); | ||
|
|
||
| public Tree LabelDef(int pos, | ||
| Tree[] params, | ||
| Tree rhs); | ||
|
|
||
| public Tree Block(int pos, | ||
| Tree[] stats); | ||
|
|
||
| public Tree Tuple(int pos, | ||
| Tree[] trees); | ||
|
|
||
| public Tree Visitor(int pos, | ||
| CaseDef[] cases); | ||
|
|
||
| public Tree Function(int pos, | ||
| ValDef[] vparams, | ||
| Tree body); | ||
|
|
||
| public Tree Assign(int pos, | ||
| Tree lhs, | ||
| Tree rhs); | ||
|
|
||
| public Tree If(int pos, | ||
| Tree cond, | ||
| Tree thenp, | ||
| Tree elsep); | ||
|
|
||
| public Tree New(int pos, | ||
| Template templ); | ||
|
|
||
| public Tree Typed(int pos, | ||
| Tree expr, | ||
| Tree tpe); | ||
|
|
||
| public Tree TypeApply(int pos, | ||
| Tree fun, | ||
| Tree[] tparams); | ||
|
|
||
| public Tree Apply(int pos, | ||
| Tree fun, | ||
| Tree[] vparam); | ||
|
|
||
| public Tree Super(int pos, | ||
| Tree tpe); | ||
|
|
||
| public Tree This(int pos, | ||
| Tree qualifier); | ||
|
|
||
| public Tree Select(int pos, | ||
| Tree qualifier, | ||
| Name selector); | ||
|
|
||
| public Tree Ident(int pos, | ||
| Name name); | ||
|
|
||
| public Tree Literal(int pos, | ||
| Object value); | ||
|
|
||
| public Tree SingletonType(int pos, | ||
| Tree ref); | ||
|
|
||
| public Tree SelectFromType(int pos, | ||
| Tree qualifier, | ||
| Name selector); | ||
|
|
||
| public Tree FunType(int pos, | ||
| Tree[] argtpes, | ||
| Tree restpe); | ||
|
|
||
| public Tree CompoundType(int pos, | ||
| Tree[] baseTypes, | ||
| Tree[] refinements); | ||
|
|
||
| public Tree TupleType(int pos, | ||
| Tree[] types); | ||
|
|
||
| public Tree AppliedType(int pos, | ||
| Tree tpe, | ||
| Tree[] args); | ||
|
|
||
| public Tree CovariantType(int pos, | ||
| Tree tpe); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,136 @@ | ||
| /* ____ ____ ____ ____ ______ *\ | ||
| ** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** | ||
| ** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** | ||
| ** /_____/\____/\___/\____/____/ ** | ||
| ** ** | ||
| ** $Id$ | ||
| \* */ | ||
|
|
||
| package scalac.ast; | ||
|
|
||
| import scalac.ApplicationError; | ||
| import scalac.util.Name; | ||
| import scalac.symtab.Type; | ||
| import scalac.symtab.Symbol; | ||
| import scalac.symtab.Modifiers; | ||
|
|
||
| public class TreeInfo { | ||
|
|
||
| public static boolean isTerm(Tree tree) { | ||
| return tree.isTerm(); | ||
| } | ||
|
|
||
| public static boolean isType(Tree tree) { | ||
| return tree.isType(); | ||
| } | ||
|
|
||
| public static boolean isOwnerDefinition(Tree tree) { | ||
| switch (tree) { | ||
| case PackageDef(_, _): | ||
| case ClassDef(_, _, _, _, _, _): | ||
| case ModuleDef(_, _, _, _): | ||
| case DefDef(_, _, _, _, _, _): | ||
| case Import(_, _): | ||
| return true; | ||
| default: | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| public static boolean isDefinition(Tree tree) { | ||
| switch (tree) { | ||
| case PackageDef(_, _): | ||
| case ClassDef(_, _, _, _, _, _): | ||
| case ModuleDef(_, _, _, _): | ||
| case DefDef(_, _, _, _, _, _): | ||
| case ValDef(_, _, _, _): | ||
| case TypeDef(_, _, _, _): | ||
| case Import(_, _): | ||
| return true; | ||
| default: | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| public static boolean isDeclaration(Tree tree) { | ||
| switch (tree) { | ||
| case DefDef(_, _, _, _, _, Tree rhs): | ||
| return rhs == Tree.Empty; | ||
| case ValDef(_, _, _, Tree rhs): | ||
| return rhs == Tree.Empty; | ||
| case TypeDef(_, _, _, _): | ||
| return true; | ||
| default: | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| /** Is tree a pure definition? | ||
| */ | ||
| public static boolean isPureDef(Tree tree) { | ||
| switch (tree) { | ||
| case ClassDef(_, _, _, _, _, _): | ||
| case ModuleDef(_, _, _, _): | ||
| case DefDef(_, _, _, _, _, _): | ||
| case TypeDef(_, _, _, _): | ||
| case Import(_, _): | ||
| return true; | ||
| case ValDef(int mods, _, _, Tree rhs): | ||
| return (mods & Modifiers.MUTABLE) == 0 && isPureExpr(rhs); | ||
| default: | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| /** Is tree a stable & pure expression? | ||
| */ | ||
| public static boolean isPureExpr(Tree tree) { | ||
| switch (tree) { | ||
| case Empty: | ||
| case This(_): | ||
| case Super(_): | ||
| return true; | ||
| case Ident(_): | ||
| return tree.type.isStable(); | ||
| case Select(Tree qual, _): | ||
| return tree.type.isStable() && isPureExpr(qual); | ||
| case Typed(Tree expr, _): | ||
| return isPureExpr(expr); | ||
| case Literal(_): | ||
| return true; | ||
| default: | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| /** Is tree a pure constructor? | ||
| * //todo: update | ||
| */ | ||
| public static boolean isPureConstr(Tree tree) { | ||
| switch (tree) { | ||
| case Ident(_): | ||
| return tree.symbol() != null && tree.symbol().isPrimaryConstructor(); | ||
| case Select(Tree qual, _): | ||
| return isPureExpr(qual) && | ||
| tree.symbol() != null && tree.symbol().isPrimaryConstructor(); | ||
| case TypeApply(Tree constr, _): | ||
| return isPureConstr(constr); | ||
| default: | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| /** The method symbol of an application node, or Symbol.NONE, if none exists. | ||
| */ | ||
| public static Symbol methSymbol(Tree tree) { | ||
| switch (tree) { | ||
| case Apply(Tree fn, _): | ||
| return methSymbol(fn); | ||
| case TypeApply(Tree fn, _): | ||
| return methSymbol(fn); | ||
| default: | ||
| if (tree.hasSymbol()) return tree.symbol(); | ||
| else return Symbol.NONE; | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| /* ____ ____ ____ ____ ______ *\ | ||
| ** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** | ||
| ** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** | ||
| ** /_____/\____/\___/\____/____/ ** | ||
| ** ** | ||
| ** $Id | ||
| \* */ | ||
|
|
||
| package scalac.ast; | ||
|
|
||
|
|
||
| public final class TreeList { | ||
| Tree[] trees; | ||
| int len; | ||
|
|
||
| public TreeList(Tree[] ts) { | ||
| trees = ts; | ||
| len = ts.length; | ||
| } | ||
|
|
||
| public TreeList() { | ||
| this(new Tree[4]); | ||
| len = 0; | ||
| } | ||
|
|
||
| public void append(Tree tree) { | ||
| if (len == trees.length) { | ||
| Tree[] ts = new Tree[len * 2]; | ||
| System.arraycopy(trees, 0, ts, 0, len); | ||
| trees = ts; | ||
| } | ||
| trees[len++] = tree; | ||
| } | ||
|
|
||
| public void append(Tree[] ts) { | ||
| for (int j = 0; j < ts.length; j++) | ||
| append(ts[j]); | ||
| } | ||
|
|
||
| public void append(TreeList tl) { | ||
| for (int j = 0; j < tl.len; j++) | ||
| append(tl.trees[j]); | ||
| } | ||
|
|
||
| public int length() { | ||
| return len; | ||
| } | ||
|
|
||
| public Tree get(int i) { | ||
| return trees[i]; | ||
| } | ||
|
|
||
| public Tree first() { | ||
| return trees[0]; | ||
| } | ||
|
|
||
| public Tree removeLast() { | ||
| return trees[--len]; | ||
| } | ||
|
|
||
| public Tree[] toArray() { | ||
| Tree[] ts = new Tree[len]; | ||
| System.arraycopy(trees, 0, ts, 0, len); | ||
| return ts; | ||
| } | ||
|
|
||
| public Tree[] copyTo(Tree[] ts) { | ||
| System.arraycopy(trees, 0, ts, 0, len); | ||
| return ts; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| /* ____ ____ ____ ____ ______ *\ | ||
| ** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** | ||
| ** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** | ||
| ** /_____/\____/\___/\____/____/ ** | ||
| ** | ||
| ** $Id$ | ||
| \* */ | ||
|
|
||
| package scalac.ast.parser; | ||
|
|
||
| import java.io.*; | ||
| import scalac.*; | ||
|
|
||
| public class ParserPhase extends PhaseDescriptor { | ||
|
|
||
| public String name() { | ||
| return "parse"; | ||
| } | ||
|
|
||
| public String description () { | ||
| return "parse source files"; | ||
| } | ||
|
|
||
| public String taskDescription() { | ||
| return "parsed"; | ||
| } | ||
|
|
||
| public Phase createPhase(Global global) { | ||
| return new ParserWorker(global, this); | ||
| } | ||
| } | ||
|
|
||
| public class ParserWorker extends Phase { | ||
|
|
||
| /** constructor | ||
| */ | ||
| public ParserWorker(Global global, PhaseDescriptor descr) { | ||
| super(global, descr); | ||
| } | ||
|
|
||
| /** apply this phase to all compilation units | ||
| */ | ||
| public void apply() { | ||
| super.apply(); | ||
| int count = 0; | ||
| for (int i = 0; i < global.units.length; i++) { | ||
| if (global.units[i].body != null) count++; | ||
| } | ||
| Unit[] units = new Unit[count]; | ||
| for (int i = 0, j = 0; i < global.units.length; i++) { | ||
| if (global.units[i].body != null) units[j++] = global.units[i]; | ||
| } | ||
| global.units = units; | ||
| } | ||
|
|
||
| /** apply this phase to the given compilation unit | ||
| */ | ||
| public void apply(Unit unit) { | ||
| global.start(); | ||
| unit.body = new Parser(unit).parse(); | ||
| global.stop("parsed " + unit.source); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,205 @@ | ||
| /* ____ ____ ____ ____ ______ *\ | ||
| ** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** | ||
| ** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** | ||
| ** /_____/\____/\___/\____/____/ ** | ||
| ** ** | ||
| ** $Id | ||
| \* */ | ||
|
|
||
| package scalac.ast.parser; | ||
|
|
||
| public final class SourceRepresentation { | ||
|
|
||
| public static int digit2int(byte ch, int base) { | ||
| if ('0' <= ch && ch <= '9' && ch < '0' + base) | ||
| return ch - '0'; | ||
| else if ('A' <= ch && ch < 'A' + base - 10) | ||
| return ch - 'A' + 10; | ||
| else if ('a' <= ch && ch < 'a' + base - 10) | ||
| return ch - 'a' + 10; | ||
| else | ||
| return -1; | ||
| } | ||
|
|
||
| public static byte int2digit(int x) { | ||
| if (x <= 9) | ||
| return (byte)(x + '0'); | ||
| else | ||
| return (byte)(x - 10 + 'A'); | ||
| } | ||
|
|
||
| /* the next 4 functions convert between three fundamental name | ||
| * representations: | ||
| * - string each character 16 bit, | ||
| * - source characters outside 0..127 are represented by | ||
| * unicode escapes, \ u X X X X | ||
| * - ascii characters outside 0..127 are represented by two or three | ||
| * byte sequences with high bit set (as in class file format). | ||
| */ | ||
|
|
||
| /** convert source bytes in source[offset..offset+len-1] to ascii. | ||
| */ | ||
| public static int source2ascii(byte source[], int offset, int len, byte ascii[]) { | ||
| int j = 0; | ||
| int i = 0; | ||
| while (i < len) { | ||
| if (source[offset + i] == '\\' && i + 1 < len) { | ||
| i++; | ||
| switch (source[offset + i]) { | ||
| case 'n': | ||
| ascii[j++] = (byte)'\n'; i++; continue; | ||
| case 't': | ||
| ascii[j++] = (byte)'\t'; i++; continue; | ||
| case 'b': | ||
| ascii[j++] = (byte)'\b'; i++; continue; | ||
| case 'r': | ||
| ascii[j++] = (byte)'\r'; i++; continue; | ||
| case 'f': | ||
| ascii[j++] = (byte)'\f'; i++; continue; | ||
| case 'u': | ||
| if (i + 4 < len) { | ||
| int code = 0; | ||
| int k = 1; | ||
| int d = 0; | ||
| while (k <= 4 && d >= 0) { | ||
| d = digit2int(source[offset + i + k], 16); | ||
| code = code * 16 + d; | ||
| k++; | ||
| } | ||
| if (d >= 0) { | ||
| if (code <= 0x7F) | ||
| ascii[j++] = (byte)code; | ||
| else | ||
| if (code <= 0x3FF) { | ||
| ascii[j++] = (byte)(0xC0 | (code >> 6)); | ||
| ascii[j++] = (byte)(0x80 | (code & 0x3F)); | ||
| } else { | ||
| ascii[j++] = (byte)(0xE0 | (code >> 12)); | ||
| ascii[j++] = (byte)(0x80 | | ||
| ((code >> 6) & 0x3F)); | ||
| ascii[j++] = (byte)(0x80 | (code & 0x3F)); | ||
| } | ||
| i = i + 5; | ||
| continue; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| byte b = source[offset + i++]; | ||
| if (b >= 0) | ||
| ascii[j++] = b; | ||
| else { | ||
| ascii[j++] = (byte)(0xC0 | ((b >> 6) & 0x3)); | ||
| ascii[j++] = (byte)(0x80 | (b & 0x3F)); | ||
| } | ||
| } | ||
| return j; | ||
| } | ||
|
|
||
| /** convert ascii bytes in ascii[offset..offset+len-1] to a string | ||
| */ | ||
| public static String ascii2string(byte ascii[], int offset, int len) { | ||
| char cs[] = new char[len]; | ||
| int i = offset; | ||
| int j = 0; | ||
| len += offset; | ||
| while (i < len) { | ||
| int b = ascii[i++] & 0xFF; | ||
| if (b >= 0xE0) { | ||
| b = ((b & 0x0F) << 12) | (ascii[i++] & 0x3F) << 6; | ||
| b = b | (ascii[i++] & 0x3F); | ||
| } | ||
| else | ||
| if (b >= 0xC0) | ||
| b = ((b & 0x1F) << 6) | (ascii[i++] & 0x3F); | ||
| cs[j++] = (char)b; | ||
| } | ||
| return new String(cs, 0, j); | ||
| } | ||
|
|
||
| /** convert string to array of source bytes | ||
| */ | ||
| public static byte[] string2source(String s) { | ||
| byte[] source = new byte[s.length() * 6]; | ||
| int j = 0; | ||
| for (int i = 0; i < s.length(); i++) { | ||
| char ch = s.charAt(i); | ||
| switch (ch) { | ||
| case '\n': | ||
| source[j++] = (byte)'\\'; | ||
| source[j++] = (byte)'n'; | ||
| break; | ||
| case '\t': | ||
| source[j++] = (byte)'\\'; | ||
| source[j++] = (byte)'t'; | ||
| break; | ||
| case '\b': | ||
| source[j++] = (byte)'\\'; | ||
| source[j++] = (byte)'b'; | ||
| break; | ||
| case '\r': | ||
| source[j++] = (byte)'\\'; | ||
| source[j++] = (byte)'r'; | ||
| break; | ||
| case '\f': | ||
| source[j++] = (byte)'\\'; | ||
| source[j++] = (byte)'f'; | ||
| break; | ||
| case '\"': | ||
| source[j++] = (byte)'\\'; | ||
| source[j++] = (byte)'\"'; | ||
| break; | ||
| case '\'': | ||
| source[j++] = (byte)'\\'; | ||
| source[j++] = (byte)'\''; | ||
| break; | ||
| case '\\': | ||
| source[j++] = (byte)'\\'; | ||
| source[j++] = (byte)'\\'; | ||
| break; | ||
| default: | ||
| if ((' ' <= ch) && (ch <= 127)) | ||
| source[j++] = (byte)ch; | ||
| else { | ||
| source[j++] = (byte)'\\'; | ||
| source[j++] = (byte)'u'; | ||
| source[j++] = int2digit((ch >> 12) & 0xF); | ||
| source[j++] = int2digit((ch >> 8) & 0xF); | ||
| source[j++] = int2digit((ch >> 4) & 0xF); | ||
| source[j++] = int2digit(ch & 0xF); | ||
| } | ||
| } | ||
| } | ||
| byte[] res = new byte[j]; | ||
| System.arraycopy(source, 0, res, 0, j); | ||
| return res; | ||
| } | ||
|
|
||
| /** convert string to array of ascii bytes | ||
| */ | ||
| public static byte[] string2ascii(String s) { | ||
| byte[] source = string2source(s); | ||
| byte[] ascii = new byte[source.length * 2]; | ||
| int alen = source2ascii(source, 0, source.length, ascii); | ||
| byte[] res = new byte[alen]; | ||
| System.arraycopy(ascii, 0, res, 0, alen); | ||
| return res; | ||
| } | ||
|
|
||
| /** escape all characters outside 32..127 in string s | ||
| */ | ||
| public static String escape(String s) { | ||
| try { | ||
| return new String(string2source(s), "8859_1"); | ||
| } catch (java.io.UnsupportedEncodingException e) { | ||
| throw new InternalError(e.getMessage()); | ||
| } | ||
| } | ||
|
|
||
| /** escape character c, if outside 32..127. | ||
| */ | ||
| public static String escape(char c) { | ||
| char[] s = {c}; | ||
| return escape(new String(s)); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,304 @@ | ||
| /* ____ ____ ____ ____ ______ *\ | ||
| ** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** | ||
| ** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** | ||
| ** /_____/\____/\___/\____/____/ ** | ||
| ** ** | ||
| ** $Id$ | ||
| \* */ | ||
|
|
||
| package scalac.ast.parser; | ||
|
|
||
| import java.io.*; | ||
| import java.util.Hashtable; | ||
| import scalac.util.AbstractFile; | ||
| import scalac.util.Name; | ||
| import scalac.util.Position; | ||
|
|
||
|
|
||
| /** This class represents a single scala source file. It provides | ||
| * functionality to read the file and to output error messages on | ||
| * a given line and column. Error messages are logged to | ||
| * decouple the time where an error message is issued from the | ||
| * time where the error messages are displayed. | ||
| * | ||
| * @author Matthias Zenger | ||
| * @version 1.0 | ||
| */ | ||
| public class Sourcefile { | ||
|
|
||
| /** the id management | ||
| */ | ||
| public static int numIds = 1; | ||
| public static String[] files = new String[]{"console", null, null, null}; | ||
| public static Sourcefile[] sources = new Sourcefile[]{null, null, null, null}; | ||
| public int id; | ||
|
|
||
| /** the filename | ||
| */ | ||
| public final boolean console; | ||
| protected String filename; | ||
| public String shortname; | ||
| public String pathname; | ||
|
|
||
| /** the encoding of the file | ||
| */ | ||
| protected String encoding; | ||
|
|
||
| /** a log of all errors generated so far; used to avoid printing an | ||
| * error message more than once | ||
| */ | ||
| protected Hashtable recorded = new Hashtable(); | ||
|
|
||
| /** the buffer containing the file that is currently translated | ||
| */ | ||
| protected byte[] buf = null; | ||
|
|
||
| /** the last error position | ||
| */ | ||
| protected int lastLine = 0; | ||
| protected int lastPos = 0; | ||
| protected int lineEnd = 0; | ||
| protected int newPos = 0; | ||
|
|
||
| /** constants used for source parsing | ||
| */ | ||
| final static byte LF = 0xA; | ||
| final static byte FF = 0xC; | ||
| final static byte CR = 0xD; | ||
| final static byte SU = 0x1A; | ||
|
|
||
| /** set col to NO_COLUMN, if the printLine method should not mark | ||
| * the column | ||
| */ | ||
| final static int NO_COLUMN = -1; | ||
|
|
||
| /** number of lines and bytes (not used internally) | ||
| */ | ||
| public int lines; // set externally | ||
| public int bytes; | ||
|
|
||
| /** prompt after error? | ||
| */ | ||
| public boolean prompt; | ||
|
|
||
| /** constructors | ||
| */ | ||
| public Sourcefile(String filename, boolean console) throws IOException, FileNotFoundException { | ||
| this.console = console; | ||
| if (filename == null) { | ||
| this.filename = "(sourcefile not available)"; | ||
| this.shortname = "?"; | ||
| this.pathname = "?"; | ||
| buf = new byte[]{SU}; | ||
| } else { | ||
| File f = new File(filename); | ||
| this.filename = filename; | ||
| this.shortname = f.getName(); | ||
| this.pathname = f.getAbsoluteFile().getParentFile(). | ||
| getCanonicalPath(); | ||
| fillBuffer(new FileInputStream(f)); | ||
| } | ||
| if (numIds == files.length) { | ||
| String[] newfiles = new String[numIds * 2]; | ||
| System.arraycopy(files, 0, newfiles, 0, numIds); | ||
| files = newfiles; | ||
| Sourcefile[] newsources = new Sourcefile[numIds * 2]; | ||
| System.arraycopy(sources, 0, newsources, 0, numIds); | ||
| sources = newsources; | ||
| } | ||
| sources[numIds] = this; | ||
| files[id = numIds++] = shortname; | ||
| } | ||
|
|
||
| public Sourcefile(AbstractFile abs) throws IOException, FileNotFoundException { | ||
| this.console = false; | ||
| if (filename == null) { | ||
| this.filename = "(sourcefile not available)"; | ||
| this.shortname = "?"; | ||
| this.pathname = "?"; | ||
| buf = new byte[]{SU}; | ||
| } else { | ||
| this.filename = abs.getPath(); | ||
| this.shortname = abs.getName(); | ||
| this.pathname = abs.getPath(); | ||
| fillBuffer(abs.getInputStream()); | ||
| } | ||
| if (numIds == files.length) { | ||
| String[] newfiles = new String[numIds * 2]; | ||
| System.arraycopy(files, 0, newfiles, 0, numIds); | ||
| files = newfiles; | ||
| Sourcefile[] newsources = new Sourcefile[numIds * 2]; | ||
| System.arraycopy(sources, 0, newsources, 0, numIds); | ||
| sources = newsources; | ||
| } | ||
| sources[numIds] = this; | ||
| files[id = numIds++] = shortname; | ||
| } | ||
|
|
||
| public Sourcefile(byte[] input, boolean console) { | ||
| this.console = console; | ||
| if (input == null) { | ||
| this.filename = "(sourcefile not available)"; | ||
| this.shortname = "?"; | ||
| this.pathname = "?"; | ||
| buf = new byte[]{SU}; | ||
| } else { | ||
| this.filename = "console"; | ||
| this.shortname = "console"; | ||
| this.pathname = "console"; | ||
| buf = new byte[input.length + 2]; | ||
| System.arraycopy(input, 0, buf, 0, input.length); | ||
| buf[input.length] = Scanner.LF; | ||
| buf[input.length + 1] = SU; | ||
| } | ||
| sources[0] = this; | ||
| id = 0; | ||
| } | ||
|
|
||
| /** fill the buffer using the InputStream | ||
| */ | ||
| private void fillBuffer(InputStream in) throws IOException { | ||
| try { | ||
| buf = new byte[(bytes = in.available()) + 1]; | ||
| if (in.read(buf) != (buf.length - 1)) | ||
| throw new IOException(); | ||
| in.close(); | ||
| buf[buf.length - 1] = SU; | ||
| } catch (IOException e) { | ||
| throw new IOException("cannot read '" + filename + "'"); | ||
| } | ||
| } | ||
|
|
||
| /** return filename as a string | ||
| */ | ||
| public String toString() { | ||
| return filename; | ||
| } | ||
|
|
||
| /** return filename as a name | ||
| */ | ||
| public Name getName() { | ||
| return Name.fromString(filename); | ||
| } | ||
|
|
||
| /** return the shortname without the suffix | ||
| */ | ||
| public String getShortnameWithoutSuffix() { | ||
| int idx = shortname.lastIndexOf('.'); | ||
| if (idx < 0) | ||
| return shortname; | ||
| else | ||
| return shortname.substring(0, idx); | ||
| } | ||
|
|
||
| /** return the source buffer of this file | ||
| */ | ||
| public byte[] getBuffer() { | ||
| return buf; | ||
| } | ||
|
|
||
| /** number of logged entries | ||
| */ | ||
| public int logged() { | ||
| return recorded.size(); | ||
| } | ||
|
|
||
| /** is there already an entry at position 'pos' | ||
| */ | ||
| public boolean isLogged(int pos) { | ||
| return (recorded.get(new Integer(pos)) != null); | ||
| } | ||
|
|
||
| /** enter entry into log table | ||
| */ | ||
| public void log(int pos, String message) { | ||
| recorded.put(new Integer(pos), message); | ||
| } | ||
|
|
||
| /** set encoding of the file | ||
| */ | ||
| public void setEncoding(String encoding) { | ||
| this.encoding = encoding; | ||
| } | ||
|
|
||
| /** return true if there is an entry for this position, | ||
| * otherwise return false and enter message into log | ||
| */ | ||
| public boolean testAndSetLog(int pos, String message) { | ||
| if (!isLogged(pos)) { | ||
| log(pos, message); | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| /** get error message with line from sourcefile | ||
| */ | ||
| public String getMessage(int pos, String message) { | ||
| if (pos == Position.NOPOS) | ||
| return filename + ": " + message; | ||
| else { | ||
| int fileId = Position.file(pos); | ||
| String filename = files[fileId]; | ||
| int line = Position.line(pos); | ||
| int col = Position.column(pos); | ||
| String main = filename + ":" + line + ": " + message; | ||
| if ((fileId > 0) && | ||
| (fileId < numIds) && | ||
| (sources[fileId] != null)) | ||
| return main + '\n' + sources[fileId].getLine(line, col); | ||
| else | ||
| return main; | ||
| //else | ||
| // System.out.println("(source file not available anymore)"); | ||
| } | ||
| } | ||
|
|
||
| /** get source line | ||
| */ | ||
| public String getLine(int line, int col) { | ||
| int pos = 0; | ||
| if (lastLine > line) | ||
| lastLine = 0; | ||
| else | ||
| pos = newPos; | ||
| while ((pos < buf.length) && (lastLine < line)) | ||
| { | ||
| lastPos = pos; | ||
| while ((pos < buf.length) && (buf[pos] != CR) && | ||
| (buf[pos] != LF) && (buf[pos] != FF)) | ||
| pos++; | ||
| lineEnd = pos; | ||
| if (pos < buf.length) | ||
| pos++; | ||
| if ((pos < buf.length) && (buf[pos-1] == CR) && (buf[pos] == LF)) | ||
| pos++; | ||
| lastLine++; | ||
| } | ||
| newPos = pos; | ||
| try | ||
| { | ||
| String errline = (encoding != null) ? | ||
| new String(buf, lastPos, lineEnd - lastPos, encoding) : | ||
| new String(buf, lastPos, lineEnd - lastPos); | ||
| if (col != NO_COLUMN) | ||
| { | ||
| byte[] ptr = new byte[col]; | ||
| for (int i = col - 2; i >= 0; i--) | ||
| ptr[i] = (byte)' '; | ||
| ptr[col - 1] = (byte)'^'; | ||
| return errline + '\n' + new String(ptr); | ||
| } else | ||
| return errline; | ||
| } catch (UnsupportedEncodingException e) { | ||
| throw new InternalError(e.getMessage()); | ||
| } | ||
| } | ||
|
|
||
| /** release all sourcefile objects | ||
| */ | ||
| public static void flushSources() { | ||
| for (int i = 0; i < sources.length; i++) | ||
| sources[i] = null; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| /* ____ ____ ____ ____ ______ *\ | ||
| ** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** | ||
| ** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** | ||
| ** /_____/\____/\___/\____/____/ ** | ||
| ** ** | ||
| ** $Id$ | ||
| \* */ | ||
|
|
||
| package scalac.ast.parser; | ||
|
|
||
| import scalac.util.Name; | ||
|
|
||
| /** A class for representing a token's data. | ||
| * | ||
| * @author Matthias Zenger | ||
| * @version 1.0 | ||
| */ | ||
| public class TokenData implements Tokens { | ||
|
|
||
| /** the next token | ||
| */ | ||
| public int token = EMPTY; | ||
|
|
||
| /** the token's position. pos = line << Position.LINESHIFT + col | ||
| */ | ||
| public int pos = 0; | ||
|
|
||
| /** the name of an identifier or token | ||
| */ | ||
| public Name name; | ||
|
|
||
| /** the value of a number | ||
| */ | ||
| public long intVal; | ||
| public double floatVal; | ||
|
|
||
| public void copyFrom(TokenData td) { | ||
| this.token = td.token; | ||
| this.pos = td.pos; | ||
| this.name = td.name; | ||
| this.intVal = td.intVal; | ||
| this.floatVal = td.floatVal; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| /* ____ ____ ____ ____ ______ *\ | ||
| ** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** | ||
| ** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** | ||
| ** /_____/\____/\___/\____/____/ ** | ||
| ** ** | ||
| ** $Id$ | ||
| \* */ | ||
|
|
||
| package scalac.ast.parser; | ||
|
|
||
| public interface Tokens { | ||
| byte EMPTY = -3, | ||
| UNDEF = -2, | ||
| ERROR = -1, | ||
| EOF = 0, | ||
|
|
||
| /* literals */ | ||
| CHARLIT = 1, | ||
| INTLIT = 2, | ||
| LONGLIT = 3, | ||
| FLOATLIT = 4, | ||
| DOUBLELIT = 5, | ||
| STRINGLIT = 6, | ||
|
|
||
| /* identifier */ | ||
| IDENTIFIER = 10, | ||
|
|
||
| /* keywords */ | ||
| IF = 20, | ||
| FOR = 21, | ||
| ELSE = 22, | ||
| THIS = 23, | ||
| NULL = 24, | ||
| NEW = 25, | ||
| WITH = 26, | ||
| SUPER = 27, | ||
| CASE = 28, | ||
| CASECLASS = 29, | ||
| VAL = 30, | ||
| ABSTRACT = 31, | ||
| FINAL = 32, | ||
| PRIVATE = 33, | ||
| PROTECTED = 34, | ||
| QUALIFIED = 35, | ||
| OVERRIDE = 36, | ||
| VAR = 37, | ||
| DEF = 38, | ||
| TYPE = 39, | ||
| EXTENDS = 40, | ||
| LET = 41, | ||
| MODULE = 43, | ||
| CLASS = 44, | ||
| CONSTR = 45, | ||
| IMPORT = 46, | ||
| PACKAGE = 47, | ||
| AS = 48, | ||
| IS = 49, | ||
| YIELD = 50, | ||
| DO = 51, | ||
| TRAIT = 52, | ||
|
|
||
| /* special symbols */ | ||
| COMMA = 61, | ||
| SEMI = 62, | ||
| DOT = 63, | ||
| USCORE = 64, | ||
| COLON = 65, | ||
| EQUALS = 66, | ||
| LARROW = 57, | ||
| ARROW = 68, | ||
| SUBTYPE = 69, | ||
| AT = 70, | ||
| HASH = 71, | ||
|
|
||
| /* parenthesis */ | ||
| LPAREN = 90, | ||
| RPAREN = 91, | ||
| LBRACKET = 92, | ||
| RBRACKET = 93, | ||
| LBRACE = 94, | ||
| RBRACE = 95; | ||
| } | ||
|
|
||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,173 @@ | ||
| /* ____ ____ ____ ____ ______ *\ | ||
| ** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala ** | ||
| ** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL ** | ||
| ** /_____/\____/\___/\____/____/ ** | ||
| ** ** | ||
| \* */ | ||
|
|
||
| // $Id$ | ||
|
|
||
| package scalac.ast.printer; | ||
|
|
||
| import scalac.Unit; | ||
| import scalac.symtab.Symbol; | ||
|
|
||
| import java.io.OutputStream; | ||
| import java.io.PrintWriter; | ||
| import java.lang.Math; | ||
| import java.util.HashMap; | ||
|
|
||
| /** | ||
| * HTML pretty printer for Scala abstract syntax trees. | ||
| * | ||
| * @author Michel Schinz | ||
| * @version 1.0 | ||
| */ | ||
|
|
||
| public class HTMLTreePrinter extends TextTreePrinter { | ||
| protected int outSectionLevel = 1; | ||
| protected boolean started = false; | ||
|
|
||
| public HTMLTreePrinter(OutputStream stream) { | ||
| super(stream); | ||
| } | ||
|
|
||
| public void begin() { | ||
| assert !started; | ||
|
|
||
| super.begin(); | ||
| out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">"); | ||
| out.println("<html>"); | ||
| out.println("<head>"); | ||
| out.println("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\">"); | ||
| out.println("<link rel=\"stylesheet\" href=\"scala.css\" type=\"text/css\">"); | ||
| out.println("<title>Scala tree</title>"); | ||
| out.println("</head>"); | ||
| out.println("<body>"); | ||
|
|
||
| started = true; | ||
| } | ||
|
|
||
| public void end() { | ||
| assert started; | ||
|
|
||
| out.println("</body>"); | ||
| out.println("</html>"); | ||
| super.end(); | ||
|
|
||
| started = false; | ||
| } | ||
|
|
||
| public void beginSection(int level, String title) { | ||
| outSectionLevel = Math.min(level, 4); | ||
| beginSection1(outSectionLevel, title); | ||
| } | ||
|
|
||
| protected void beginSection1(int level, String title) { | ||
| if (level == 1) | ||
| out.println("<hr/>"); | ||
| String tag = "h" + level; | ||
| startTag(tag); | ||
| print(Text.Simple(title)); | ||
| endTag(tag); | ||
| } | ||
|
|
||
| protected void startTag(String tag) { | ||
| out.print('<'); out.print(tag); out.print('>'); | ||
| } | ||
|
|
||
| protected void startTag(String tag, String attr1, String val1) { | ||
| out.print('<'); | ||
| out.print(tag); | ||
| out.print(' '); | ||
| out.print(attr1); | ||
| out.print("=\""); | ||
| out.print(val1); | ||
| out.print("\">"); | ||
| } | ||
|
|
||
| protected void endTag(String tag) { | ||
| out.print("</"); out.print(tag); out.print(">"); | ||
| } | ||
|
|
||
| protected void startSpan(String cls) { | ||
| startTag("span", "class", cls); | ||
| } | ||
|
|
||
| protected void endSpan() { | ||
| endTag("span"); | ||
| } | ||
|
|
||
| protected void printString(String str) { | ||
| StringBuffer buf = null; | ||
| int strLen = str.length(); | ||
|
|
||
| for (int i = 0; i < strLen; ++i) { | ||
| String entity; | ||
| char c = str.charAt(i); | ||
| switch (c) { | ||
| case '<': entity = "lt"; break; | ||
| case '>': entity = "gt"; break; | ||
| case '&': entity = "amp"; break; | ||
| default: entity = null; break; | ||
| } | ||
| if (entity != null) { | ||
| out.print('&'); | ||
| out.print(entity); | ||
| out.print(';'); | ||
| } else | ||
| out.print(c); | ||
| } | ||
| } | ||
|
|
||
| protected static HashMap/*<Symbol,Integer>*/ symAnchors = new HashMap(); | ||
| protected String symbolAnchor(Symbol sym, SymbolUsage usage) { | ||
| Integer anchorId = (Integer)symAnchors.get(sym); | ||
| if (anchorId == null) { | ||
| anchorId = new Integer(symAnchors.size()); | ||
| symAnchors.put(sym, anchorId); | ||
| } | ||
| if (usage == SymbolUsage.Definition) | ||
| return anchorId.toString(); | ||
| else | ||
| return "#" + anchorId.toString(); | ||
| } | ||
|
|
||
| protected void print(Text text) { | ||
| switch (text) { | ||
| case Keyword(String name): | ||
| startSpan("kw"); | ||
| printString(name); | ||
| endSpan(); | ||
| break; | ||
| case Literal(String str): | ||
| startSpan("lit"); | ||
| printString(str); | ||
| endSpan(); | ||
| break; | ||
| case Identifier(Symbol symbol, String name, SymbolUsage usage): | ||
| boolean defined = (usage == SymbolUsage.Definition); | ||
| if (defined) startSpan("idDef"); | ||
| if (symbol != null) { | ||
| String attr = (defined ? "name" : "href"); | ||
| startTag("a", attr, symbolAnchor(symbol, usage)); | ||
| } | ||
| printString(name); | ||
| if (symbol != null) | ||
| endTag("a"); | ||
| if (defined) endSpan(); | ||
| break; | ||
| default: | ||
| super.print(text); | ||
| } | ||
| } | ||
|
|
||
| protected void printUnitHeader(Unit unit) { | ||
| beginSection1(outSectionLevel + 1, unit.source.toString()); | ||
| startTag("pre"); | ||
| } | ||
|
|
||
| protected void printUnitFooter(Unit unit) { | ||
| endTag("pre"); | ||
| } | ||
| } |